diff --git a/.gitignore b/.gitignore index 9491a2f..ab36761 100644 --- a/.gitignore +++ b/.gitignore @@ -360,4 +360,6 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd \ No newline at end of file +FodyWeavers.xsd + +!DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug \ No newline at end of file diff --git a/Assemblers.Automation/Assemblers.Automation.csproj b/Assemblers.Automation/Assemblers.Automation.csproj new file mode 100644 index 0000000..040212f --- /dev/null +++ b/Assemblers.Automation/Assemblers.Automation.csproj @@ -0,0 +1,38 @@ + + + + netstandard2.0 + Skyline.DataMiner.CICD.Assemblers.Automation + Skyline.DataMiner.CICD.Assemblers.Automation + True + True + SkylineCommunications + Skyline Communications + LICENSE.txt + True + icon.png + https://skyline.be/ + Skyline;DataMiner;CICD + Library providing methods for converting Visual Studio DIS Automation Solutions to individual DataMiner AutomationScript artifacts (e.g. XML, DLLs,...). + README.md + https://github.com/SkylineCommunications/Skyline.DataMiner.CICD.Packages + git + 0.0.2-local + + + + + + + + + + + + + + + + + + diff --git a/Assemblers.Automation/AutomationScriptBuilder.cs b/Assemblers.Automation/AutomationScriptBuilder.cs new file mode 100644 index 0000000..3c57687 --- /dev/null +++ b/Assemblers.Automation/AutomationScriptBuilder.cs @@ -0,0 +1,725 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Automation +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using System.Text.RegularExpressions; + using System.Threading.Tasks; + + using NuGet.Packaging.Core; + using NuGet.Versioning; + + using Skyline.DataMiner.CICD.Assemblers.Common; + using Skyline.DataMiner.CICD.Common.NuGet; + using Skyline.DataMiner.CICD.FileSystem; + using Skyline.DataMiner.CICD.Loggers; + using Skyline.DataMiner.CICD.Parsers.Automation.Xml; + using Skyline.DataMiner.CICD.Parsers.Common.VisualStudio.Projects; + using Skyline.DataMiner.CICD.Parsers.Common.Xml; + + using EditXml = Skyline.DataMiner.CICD.Parsers.Common.XmlEdit; + + /// + /// Automation script builder. + /// + public class AutomationScriptBuilder + { + private static readonly Regex RegexProjectPlaceholder = new Regex(@"\[Project:(?.*)\]", RegexOptions.Compiled & RegexOptions.IgnoreCase); + private static readonly HashSet NetFramework481ReferenceAssemblies = new HashSet(new[] { "Accessibility.dll", "CustomMarshalers.dll", "ISymWrapper.dll", "Microsoft.Activities.Build.dll", "Microsoft.Build.Conversion.v4.0.dll", "Microsoft.Build.dll", "Microsoft.Build.Engine.dll", "Microsoft.Build.Framework.dll", "Microsoft.Build.Tasks.v4.0.dll", "Microsoft.Build.Utilities.v4.0.dll", "Microsoft.CSharp.dll", "Microsoft.JScript.dll", "Microsoft.VisualBasic.Compatibility.Data.dll", "Microsoft.VisualBasic.Compatibility.dll", "Microsoft.VisualBasic.dll", "Microsoft.VisualC.dll", "Microsoft.VisualC.STLCLR.dll", "Microsoft.Win32.Primitives.dll", "mscorlib.dll", "netstandard.dll", "PresentationBuildTasks.dll", "PresentationCore.dll", "PresentationFramework.Aero.dll", "PresentationFramework.Aero2.dll", "PresentationFramework.AeroLite.dll", "PresentationFramework.Classic.dll", "PresentationFramework.dll", "PresentationFramework.Luna.dll", "PresentationFramework.Royale.dll", "ReachFramework.dll", "sysglobl.dll", "System.Activities.Core.Presentation.dll", "System.Activities.dll", "System.Activities.DurableInstancing.dll", "System.Activities.Presentation.dll", "System.AddIn.Contract.dll", "System.AddIn.dll", "System.AppContext.dll", "System.Collections.Concurrent.dll", "System.Collections.dll", "System.Collections.NonGeneric.dll", "System.Collections.Specialized.dll", "System.ComponentModel.Annotations.dll", "System.ComponentModel.Composition.dll", "System.ComponentModel.Composition.Registration.dll", "System.ComponentModel.DataAnnotations.dll", "System.ComponentModel.dll", "System.ComponentModel.EventBasedAsync.dll", "System.ComponentModel.Primitives.dll", "System.ComponentModel.TypeConverter.dll", "System.Configuration.dll", "System.Configuration.Install.dll", "System.Console.dll", "System.Core.dll", "System.Data.Common.dll", "System.Data.DataSetExtensions.dll", "System.Data.dll", "System.Data.Entity.Design.dll", "System.Data.Entity.dll", "System.Data.Linq.dll", "System.Data.OracleClient.dll", "System.Data.Services.Client.dll", "System.Data.Services.Design.dll", "System.Data.Services.dll", "System.Data.SqlXml.dll", "System.Deployment.dll", "System.Design.dll", "System.Device.dll", "System.Diagnostics.Contracts.dll", "System.Diagnostics.Debug.dll", "System.Diagnostics.FileVersionInfo.dll", "System.Diagnostics.Process.dll", "System.Diagnostics.StackTrace.dll", "System.Diagnostics.TextWriterTraceListener.dll", "System.Diagnostics.Tools.dll", "System.Diagnostics.TraceSource.dll", "System.Diagnostics.Tracing.dll", "System.DirectoryServices.AccountManagement.dll", "System.DirectoryServices.dll", "System.DirectoryServices.Protocols.dll", "System.dll", "System.Drawing.Design.dll", "System.Drawing.dll", "System.Drawing.Primitives.dll", "System.Dynamic.dll", "System.Dynamic.Runtime.dll", "System.EnterpriseServices.dll", "System.EnterpriseServices.Thunk.dll", "System.EnterpriseServices.Wrapper.dll", "System.Globalization.Calendars.dll", "System.Globalization.dll", "System.Globalization.Extensions.dll", "System.IdentityModel.dll", "System.IdentityModel.Selectors.dll", "System.IdentityModel.Services.dll", "System.IO.Compression.dll", "System.IO.Compression.FileSystem.dll", "System.IO.Compression.ZipFile.dll", "System.IO.dll", "System.IO.FileSystem.dll", "System.IO.FileSystem.DriveInfo.dll", "System.IO.FileSystem.Primitives.dll", "System.IO.FileSystem.Watcher.dll", "System.IO.IsolatedStorage.dll", "System.IO.Log.dll", "System.IO.MemoryMappedFiles.dll", "System.IO.Pipes.dll", "System.IO.UnmanagedMemoryStream.dll", "System.Linq.dll", "System.Linq.Expressions.dll", "System.Linq.Parallel.dll", "System.Linq.Queryable.dll", "System.Management.dll", "System.Management.Instrumentation.dll", "System.Messaging.dll", "System.Net.dll", "System.Net.Http.dll", "System.Net.Http.Rtc.dll", "System.Net.Http.WebRequest.dll", "System.Net.NameResolution.dll", "System.Net.NetworkInformation.dll", "System.Net.Ping.dll", "System.Net.Primitives.dll", "System.Net.Requests.dll", "System.Net.Security.dll", "System.Net.Sockets.dll", "System.Net.WebHeaderCollection.dll", "System.Net.WebSockets.Client.dll", "System.Net.WebSockets.dll", "System.Numerics.dll", "System.ObjectModel.dll", "System.Printing.dll", "System.Reflection.Context.dll", "System.Reflection.dll", "System.Reflection.Emit.dll", "System.Reflection.Emit.ILGeneration.dll", "System.Reflection.Emit.Lightweight.dll", "System.Reflection.Extensions.dll", "System.Reflection.Primitives.dll", "System.Resources.Reader.dll", "System.Resources.ResourceManager.dll", "System.Resources.Writer.dll", "System.Runtime.Caching.dll", "System.Runtime.CompilerServices.VisualC.dll", "System.Runtime.dll", "System.Runtime.DurableInstancing.dll", "System.Runtime.Extensions.dll", "System.Runtime.Handles.dll", "System.Runtime.InteropServices.dll", "System.Runtime.InteropServices.RuntimeInformation.dll", "System.Runtime.InteropServices.WindowsRuntime.dll", "System.Runtime.Numerics.dll", "System.Runtime.Remoting.dll", "System.Runtime.Serialization.dll", "System.Runtime.Serialization.Formatters.dll", "System.Runtime.Serialization.Formatters.Soap.dll", "System.Runtime.Serialization.Json.dll", "System.Runtime.Serialization.Primitives.dll", "System.Runtime.Serialization.Xml.dll", "System.Security.Claims.dll", "System.Security.Cryptography.Algorithms.dll", "System.Security.Cryptography.Csp.dll", "System.Security.Cryptography.Encoding.dll", "System.Security.Cryptography.Primitives.dll", "System.Security.Cryptography.X509Certificates.dll", "System.Security.dll", "System.Security.Principal.dll", "System.Security.SecureString.dll", "System.ServiceModel.Activation.dll", "System.ServiceModel.Activities.dll", "System.ServiceModel.Channels.dll", "System.ServiceModel.Discovery.dll", "System.ServiceModel.dll", "System.ServiceModel.Duplex.dll", "System.ServiceModel.Http.dll", "System.ServiceModel.NetTcp.dll", "System.ServiceModel.Primitives.dll", "System.ServiceModel.Routing.dll", "System.ServiceModel.Security.dll", "System.ServiceModel.Web.dll", "System.ServiceProcess.dll", "System.Speech.dll", "System.Text.Encoding.dll", "System.Text.Encoding.Extensions.dll", "System.Text.RegularExpressions.dll", "System.Threading.dll", "System.Threading.Overlapped.dll", "System.Threading.Tasks.dll", "System.Threading.Tasks.Parallel.dll", "System.Threading.Thread.dll", "System.Threading.ThreadPool.dll", "System.Threading.Timer.dll", "System.Transactions.dll", "System.ValueTuple.dll", "System.Web.Abstractions.dll", "System.Web.ApplicationServices.dll", "System.Web.DataVisualization.Design.dll", "System.Web.DataVisualization.dll", "System.Web.dll", "System.Web.DynamicData.Design.dll", "System.Web.DynamicData.dll", "System.Web.Entity.Design.dll", "System.Web.Entity.dll", "System.Web.Extensions.Design.dll", "System.Web.Extensions.dll", "System.Web.Mobile.dll", "System.Web.RegularExpressions.dll", "System.Web.Routing.dll", "System.Web.Services.dll", "System.Windows.Controls.Ribbon.dll", "System.Windows.dll", "System.Windows.Forms.DataVisualization.Design.dll", "System.Windows.Forms.DataVisualization.dll", "System.Windows.Forms.dll", "System.Windows.Input.Manipulations.dll", "System.Windows.Presentation.dll", "System.Workflow.Activities.dll", "System.Workflow.ComponentModel.dll", "System.Workflow.Runtime.dll", "System.WorkflowServices.dll", "System.Xaml.dll", "System.Xml.dll", "System.Xml.Linq.dll", "System.Xml.ReaderWriter.dll", "System.Xml.Serialization.dll", "System.Xml.XDocument.dll", "System.Xml.XmlDocument.dll", "System.Xml.XmlSerializer.dll", "System.Xml.XPath.dll", "System.Xml.XPath.XDocument.dll", "UIAutomationClient.dll", "UIAutomationClientsideProviders.dll", "UIAutomationProvider.dll", "UIAutomationTypes.dll", "WindowsBase.dll", "WindowsFormsIntegration.dll", "XamlBuildTask.dll" }); + + + private readonly IFileSystem _fileSystem = FileSystem.Instance; + private readonly ILogCollector logCollector; + private readonly string directoryForNuGetConfig; + + /// + /// Initializes a new instance of the class. + /// + /// The Automation script. + /// The projects corresponding with the C# Exe blocks. + /// All the scripts in the Automation script solution. + /// is . + [Obsolete("Use the constructor with the directoryForNuGetConfig so it can take in account the NuGet.config from the solution.")] + public AutomationScriptBuilder(Script script, IDictionary projects, IEnumerable +"; + + string expected = @" + +"; + + var projects = new Dictionary() + { + { "Script_1", new Project("Script_1", new[]{ new ProjectFile("Script.cs", "using System;") }) }, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projects = new Dictionary() + { + { "Script_1", new Project("Script_1", new[]{ new ProjectFile("Script.cs", "using System;") }) }, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projects = new Dictionary() + { + { "Script_1", new Project("Script_1", new[]{ new ProjectFile("Script.cs", "using System;") }) }, + { "Script_2", new Project("Script_2", new[]{ new ProjectFile("Script.cs", "using System.Xml;") }) }, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projects = new Dictionary() + { + { "Script_1", new Project("Script_1", new[]{ new ProjectFile("Script.cs", "using System;"), new ProjectFile("Class1.cs", "using System; class Class1 {}") }) }, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + var projects = new Dictionary(); + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + var projects = new Dictionary() + { + { "Script_1", new Project("Script_1", Array.Empty()) }, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projectFiles = new[] { new ProjectFile("Script.cs", "using System;") }; + var references = new[] { new Reference("System.Data.dll") }; + var project1 = new Project("Script_1", projectFiles: projectFiles, references: references); + + var projects = new Dictionary() + { + { "Script_1", project1}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projectFiles = new[] { new ProjectFile("Script.cs", "using System;") }; + var references = new[] { new Reference(@"C:\Skyline DataMiner\Files\System.Data.dll") }; + var project1 = new Project("Script_1", projectFiles: projectFiles, references: references); + + var projects = new Dictionary() + { + { "Script_1", project1}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projectFiles_project1 = new[] { new ProjectFile("Script.cs", "using System;") }; + var projectFiles_project63000 = new[] { new ProjectFile("Script.cs", "namespace Skyline.DataMiner.Library { }") }; + var references_project1 = new[] { new Reference("System.Data.dll") }; + var projectReferences_project1 = new[] { new ProjectReference("AutomationScript_ClassLibrary") }; + var project1 = new Project("Script_1", projectFiles: projectFiles_project1, references: references_project1, projectReferences: projectReferences_project1); + var project63000 = new Project("Script_63000", projectFiles: projectFiles_project63000); + + var projects = new Dictionary() + { + { "Script_63000", project63000}, + { "Script_1", project1}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projectFiles_project1 = new[] { new ProjectFile("Script.cs", "using System;") }; + var projectFiles_project2 = new[] { new ProjectFile("Script.cs", "using System.Xml;") }; + var projectReferences_project2 = new[] { new ProjectReference("Script_1") }; + var project1 = new Project("Script_1", projectFiles: projectFiles_project1); + var project2 = new Project("Script_2", projectFiles: projectFiles_project2, projectReferences: projectReferences_project2); + + var projects = new Dictionary() + { + { "Script_1", project1}, + { "Script_2", project2}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projectFiles = new[] { new ProjectFile("Script.cs", "using System;") }; + var packageReferences = new[] + { + new PackageReference("Skyline.DataMiner.Core.DataMinerSystem.Automation", "1.0.0.1"), + new PackageReference("Skyline.DataMiner.Dev.Automation", "10.3.5"), + new PackageReference("Skyline.DataMiner.Files.SLManagedScripting", "10.3.5"), + new PackageReference("Skyline.DataMiner.Files.SLManagedAutomation", "10.3.5"), + new PackageReference("Skyline.DataMiner.Files.SLMediationSnippets", "10.3.5") + }; + var project1 = new Project("Script_1", tfm: ".NETFramework,Version=v4.6.2", projectFiles: projectFiles, packageReferences: packageReferences); + + var projects = new Dictionary() + { + { "Script_1", project1}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projectFiles = new[] { new ProjectFile("Script.cs", "using System;") }; + var references = new[] { new Reference("Newtonsoft.Json.dll") }; + var project1 = new Project("Script_1", projectFiles: projectFiles, references: references); + + var projects = new Dictionary() + { + { "Script_1", project1}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projectFiles = new[] { new ProjectFile("Script.cs", "using System;") }; + var references = new[] { new Reference("Newtonsoft.Json.dll") }; + var project1 = new Project("Script_1", projectFiles: projectFiles, references: references); + + var projects = new Dictionary() + { + { "Script_1", project1}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projectFiles = new[] { new ProjectFile("Script.cs", "using System;") }; + var references = new[] { new Reference("Newtonsoft.Json.dll") }; + var project1 = new Project("Script_1", projectFiles: projectFiles, references: references); + + var projects = new Dictionary() + { + { "Script_1", project1}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var project1 = new Project("Script_1", new[] { new ProjectFile("Script.cs", "using System;") }); + + var projects = new Dictionary() + { + { "Script_1", project1}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projects = new Dictionary(); + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projects = new Dictionary() + { + { "Script_1", new Project("Script_1", new[]{ new ProjectFile("Script.cs", "using Characterø;") }) }, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List +"; + + string expected = @" + +"; + + var projectFiles = new[] { new ProjectFile("Script.cs", "using System;") }; + var packageReferences = new[] + { + new PackageReference("Skyline.DataMiner.Dev.Automation", "10.3.5"), + new PackageReference("Newtonsoft.Json", "13.0.3"), + new PackageReference("NPOI", "2.4.1"), + new PackageReference("Skyline.DataMiner.ConnectorAPI.EVS.IPD-VIA", "1.0.0.4-Test1"), + new PackageReference("Skyline.DataMiner.ConnectorAPI.YLE.OrderManager", "1.0.0.2-Test1"), + new PackageReference("Skyline.DataMiner.Utils.InteractiveAutomationScriptToolkit", "6.1.0"), + new PackageReference("Skyline.DataMiner.Utils.YLE.Integrations", "1.0.1.6-Test1"), + }; + var project1 = new Project("Script_1", tfm: ".NETFramework,Version=v4.7.2", projectFiles: projectFiles, packageReferences: packageReferences); + + var projects = new Dictionary() + { + { "Script_1", project1}, + }; + + Script script = new Script(XmlDocument.Parse(original)); + AutomationScriptBuilder builder = new AutomationScriptBuilder(script, projects, new List + +"; + + var baseDir = FileSystem.Instance.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var dir = FileSystem.Instance.Path.GetFullPath(FileSystem.Instance.Path.Combine(baseDir, @"TestFiles\Solutions\Solution6")); + var path = FileSystem.Instance.Path.Combine(dir, "AutomationScript.sln"); + + var solution = AutomationScriptSolution.Load(path); + var builder = new AutomationScriptSolutionBuilder(solution); + + // act + var result = await builder.BuildAsync().ConfigureAwait(false); + + // check + Assert.IsNotNull(result); + Assert.HasCount(2, result); + Assert.AreEqual(expectedResult, result.Single(x => x.Key.Name == "SimpleScript").Value.Document); + } + + /// + /// Test for Automation script that refers to a library exe block defined in the same script. + /// + /// + [TestMethod] + public async Task AutomationScriptCompiler_Solution7_BuildAsync() + { + // arrange + string expectedResult = @" + + LibraryInOwnScript + + Automation + SKYLINE2\Pedro + FALSE + + + + + + + + + + + + +"; + + var baseDir = FileSystem.Instance.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var dir = FileSystem.Instance.Path.GetFullPath(FileSystem.Instance.Path.Combine(baseDir, @"TestFiles\Solutions\Solution7")); + var path = FileSystem.Instance.Path.Combine(dir, "AutomationScript.sln"); + + var solution = AutomationScriptSolution.Load(path); + var builder = new AutomationScriptSolutionBuilder(solution); + + // act + var result = await builder.BuildAsync().ConfigureAwait(false); + + // check + Assert.IsNotNull(result); + Assert.HasCount(1, result); + Assert.AreEqual(expectedResult, result[0].Value.Document); + } + + [TestMethod] + public async Task AutomationScriptCompilerUsingNuGetPackages_Solution8_SrmAsync() + { + var baseDir = FileSystem.Instance.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var dir = FileSystem.Instance.Path.GetFullPath(FileSystem.Instance.Path.Combine(baseDir, @"TestFiles\Solutions\Solution8")); + var path = FileSystem.Instance.Path.Combine(dir, "Solution8.sln"); + + var solution = AutomationScriptSolution.Load(path); + var builder = new AutomationScriptSolutionBuilder(solution); + + var result = await builder.BuildAsync().ConfigureAwait(false); + + Assert.HasCount(1, result, "Expected 1 script in build result."); + + var firstItem = result.FirstOrDefault(); + string automationScriptXml = firstItem.Value.Document; + + var document = XDocument.Parse(automationScriptXml); + XNamespace ns = document.Root.GetDefaultNamespace(); + + var referenceNodes = document + ?.Element(ns + "DMSScript") + ?.Element(ns + "Script") + ?.Element(ns + "Exe") + ?.Elements(ns + "Param"); + + Assert.IsNotNull(referenceNodes); + + List generatedEntries = new List(); + foreach (var referenceNode in referenceNodes) + { + generatedEntries.Add(referenceNode.Value); + } + + List expectedEntries = new List + { + @"Microsoft.CSharp.dll", + @"System.Data.dll", + @"System.Data.DataSetExtensions.dll", + @"System.Drawing.dll", + @"System.IO.Compression.FileSystem.dll", + @"System.Runtime.Caching.dll", + @"System.Runtime.Serialization.dll", + @"System.Xml.Linq.dll", + + @"C:\Skyline DataMiner\ProtocolScripts\DllImport\SRM\SLSRMLibrary.dll", + @"C:\Skyline DataMiner\ProtocolScripts\DllImport\SRM\SLDijkstraSearch.dll" + }; + + generatedEntries.Should().BeEquivalentTo(expectedEntries); + } + + [Ignore("Only usable internally, until there is an 'official' NuGet that has SRM as a dependency")] + [TestMethod] + public async Task AutomationScriptCompilerUsingNuGetPackages_Solution9_SrmAsDependencyAsync() + { + var baseDir = FileSystem.Instance.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var dir = FileSystem.Instance.Path.GetFullPath(FileSystem.Instance.Path.Combine(baseDir, @"TestFiles\Solutions\Solution9")); + var path = FileSystem.Instance.Path.Combine(dir, "Solution9.sln"); + + var solution = AutomationScriptSolution.Load(path); + var builder = new AutomationScriptSolutionBuilder(solution); + + var result = await builder.BuildAsync().ConfigureAwait(false); + + Assert.HasCount(1, result, "Expected 1 script in build result."); + + var firstItem = result.FirstOrDefault(); + string automationScriptXml = firstItem.Value.Document; + + var document = XDocument.Parse(automationScriptXml); + XNamespace ns = document.Root.GetDefaultNamespace(); + + var referenceNodes = document + ?.Element(ns + "DMSScript") + ?.Element(ns + "Script") + ?.Element(ns + "Exe") + ?.Elements(ns + "Param"); + + Assert.IsNotNull(referenceNodes); + + List generatedEntries = new List(); + foreach (var referenceNode in referenceNodes) + { + generatedEntries.Add(referenceNode.Value); + } + + List expectedEntries = new List + { + @"Microsoft.CSharp.dll", + @"System.Data.dll", + @"System.Data.DataSetExtensions.dll", + @"System.Drawing.dll", + @"System.IO.Compression.FileSystem.dll", + @"System.Runtime.Caching.dll", + @"System.Runtime.Serialization.dll", + @"System.Xml.Linq.dll", + + @"C:\Skyline DataMiner\ProtocolScripts\DllImport\SRM\SLSRMLibrary.dll", + + // This one has a dependency on SRM package + @"C:\Skyline DataMiner\ProtocolScripts\DllImport\skyline.dataminer.testing.mod\1.0.0-1.0.0.x.3\lib\net462\Skyline.DataMiner.Testing.MOD.dll", + }; + + generatedEntries.Should().BeEquivalentTo(expectedEntries); + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Projects/Project1/Project1.cs b/Assemblers.AutomationTests/TestFiles/Projects/Project1/Project1.cs new file mode 100644 index 0000000..6c641fc --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Projects/Project1/Project1.cs @@ -0,0 +1,107 @@ +/* +**************************************************************************** +* Copyright (c) 2025, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +11/09/2025 1.0.0.1 MOD, Skyline Initial version +**************************************************************************** +*/ + +namespace Project1 +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Text; + using Skyline.DataMiner.Automation; + + /// + /// Represents a DataMiner Automation script. + /// + public class Script + { + /// + /// The script entry point. + /// + /// Link with SLAutomation process. + public void Run(IEngine engine) + { + try + { + RunSafe(engine); + } + catch (ScriptAbortException) + { + // Catch normal abort exceptions (engine.ExitFail or engine.ExitSuccess) + throw; // Comment if it should be treated as a normal exit of the script. + } + catch (ScriptForceAbortException) + { + // Catch forced abort exceptions, caused via external maintenance messages. + throw; + } + catch (ScriptTimeoutException) + { + // Catch timeout exceptions for when a script has been running for too long. + throw; + } + catch (InteractiveUserDetachedException) + { + // Catch a user detaching from the interactive script by closing the window. + // Only applicable for interactive scripts, can be removed for non-interactive scripts. + throw; + } + catch (Exception e) + { + engine.ExitFail("Run|Something went wrong: " + e); + } + } + + private void RunSafe(IEngine engine) + { + // TODO: Define code here + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Projects/Project1/Project1.csproj b/Assemblers.AutomationTests/TestFiles/Projects/Project1/Project1.csproj new file mode 100644 index 0000000..b515203 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Projects/Project1/Project1.csproj @@ -0,0 +1,21 @@ + + + net48 + true + + + AutomationScript + False + 10.3.0.0 - 12752 + 1.0.0 + Initial Version + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Projects/Project1/Project1.xml b/Assemblers.AutomationTests/TestFiles/Projects/Project1/Project1.xml new file mode 100644 index 0000000..528dae8 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Projects/Project1/Project1.xml @@ -0,0 +1,26 @@ + + + Project1 + + Automation + MOD + FALSE + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Projects/global.json b/Assemblers.AutomationTests/TestFiles/Projects/global.json new file mode 100644 index 0000000..95be308 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Projects/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "Skyline.DataMiner.Sdk": "2.1.1" + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/AutomationScript.sln b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/AutomationScript.sln new file mode 100644 index 0000000..1a66932 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/AutomationScript.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30503.244 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{83A162A2-0BE3-4E70-B178-448B71D02A0D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{DC12C1A8-4C06-40EA-B204-30608CE534A6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{0BA1D4BE-635D-4E90-87CC-8DF145A5C25C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Script_1", "Script_1", "{F1C34D24-E21D-4477-B37C-07E5C234FE6C}" + ProjectSection(SolutionItems) = preProject + Script_1.xml = Script_1.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Script_2", "Script_2", "{1BB5378B-1540-4FF6-815B-CEDAB5F7C03B}" + ProjectSection(SolutionItems) = preProject + Script_2.xml = Script_2.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D0EA8C5C-5350-42FA-B9BA-3E5D86070D20}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{BA001170-3E31-42E9-808A-BC7626B683F5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script_1a", "Script_1a\Script_1a.csproj", "{C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script_1b", "Script_1b\Script_1b.csproj", "{3048B168-DC53-4143-ADF1-DCD95B8539ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script_2", "Script_2\Script_2.csproj", "{1AE71A40-7865-4106-A15D-D8688AB231A6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutomationScript_ClassLibrary", "AutomationScript_ClassLibrary\AutomationScript_ClassLibrary.csproj", "{07DBE185-5EB9-4DF9-898E-1874A2907DA6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Release|Any CPU.Build.0 = Release|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Release|Any CPU.Build.0 = Release|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Release|Any CPU.Build.0 = Release|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F1C34D24-E21D-4477-B37C-07E5C234FE6C} = {0BA1D4BE-635D-4E90-87CC-8DF145A5C25C} + {1BB5378B-1540-4FF6-815B-CEDAB5F7C03B} = {0BA1D4BE-635D-4E90-87CC-8DF145A5C25C} + {D0EA8C5C-5350-42FA-B9BA-3E5D86070D20} = {F1C34D24-E21D-4477-B37C-07E5C234FE6C} + {BA001170-3E31-42E9-808A-BC7626B683F5} = {1BB5378B-1540-4FF6-815B-CEDAB5F7C03B} + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653} = {D0EA8C5C-5350-42FA-B9BA-3E5D86070D20} + {3048B168-DC53-4143-ADF1-DCD95B8539ED} = {D0EA8C5C-5350-42FA-B9BA-3E5D86070D20} + {1AE71A40-7865-4106-A15D-D8688AB231A6} = {BA001170-3E31-42E9-808A-BC7626B683F5} + {07DBE185-5EB9-4DF9-898E-1874A2907DA6} = {DC12C1A8-4C06-40EA-B204-30608CE534A6} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {58942BE7-5A68-461B-8F90-E06699C84F5C} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.cs new file mode 100644 index 0000000..b936d2f --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.cs @@ -0,0 +1,5 @@ +// This is auto-generated code by DIS. Do not modify. +namespace Skyline.DataMiner.Library +{ + +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.csproj new file mode 100644 index 0000000..5a72698 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.csproj @@ -0,0 +1,47 @@ + + + + + Debug + AnyCPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6} + Library + Properties + AutomationScript_ClassLibrary + AutomationScript_ClassLibrary + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1.xml new file mode 100644 index 0000000..0b19b6d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1.xml @@ -0,0 +1,29 @@ + + Script_1 + + Automation + FALSE + MyFolder + + + + + + + Reservation ID + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1a/Script.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1a/Script.cs new file mode 100644 index 0000000..8a88f75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1a/Script.cs @@ -0,0 +1,7 @@ +public class Script +{ + public void Run() + { + + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1a/Script_1a.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1a/Script_1a.csproj new file mode 100644 index 0000000..4f11644 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1a/Script_1a.csproj @@ -0,0 +1,58 @@ + + + + + Debug + AnyCPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653} + Library + Properties + Script_1a + Script_1a + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + ..\Newtonsoft.Json.dll + C:\Skyline DataMiner\Files\Newtonsoft.Json.dll + + + ..\MySql.Data.dll + C:\Skyline DataMiner\ProtocolScripts\MySql.Data.dll + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1b/Class1.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1b/Class1.cs new file mode 100644 index 0000000..0da90bf --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1b/Class1.cs @@ -0,0 +1,6 @@ +namespace Script_1b +{ + public class Class1 + { + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1b/Script.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1b/Script.cs new file mode 100644 index 0000000..8a88f75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1b/Script.cs @@ -0,0 +1,7 @@ +public class Script +{ + public void Run() + { + + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1b/Script_1b.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1b/Script_1b.csproj new file mode 100644 index 0000000..2b81127 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_1b/Script_1b.csproj @@ -0,0 +1,51 @@ + + + + + Debug + AnyCPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED} + Library + Properties + Script_1b + Script_1b + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_2.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_2.xml new file mode 100644 index 0000000..4cfbf6d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_2.xml @@ -0,0 +1,23 @@ + + Script_2 + + Automation + FALSE + MyFolder + + + + + + + Reservation ID + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_2/Script.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_2/Script.cs new file mode 100644 index 0000000..8a88f75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_2/Script.cs @@ -0,0 +1,7 @@ +public class Script +{ + public void Run() + { + + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_2/Script_2.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_2/Script_2.csproj new file mode 100644 index 0000000..44e4775 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution1/Script_2/Script_2.csproj @@ -0,0 +1,50 @@ + + + + + Debug + AnyCPU + {1AE71A40-7865-4106-A15D-D8688AB231A6} + Library + Properties + Script_2 + Script_2 + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/AutomationScript.sln b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/AutomationScript.sln new file mode 100644 index 0000000..1071fd9 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/AutomationScript.sln @@ -0,0 +1,79 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30503.244 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{83A162A2-0BE3-4E70-B178-448B71D02A0D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{DC12C1A8-4C06-40EA-B204-30608CE534A6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{0BA1D4BE-635D-4E90-87CC-8DF145A5C25C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Script_1", "Script_1", "{F1C34D24-E21D-4477-B37C-07E5C234FE6C}" + ProjectSection(SolutionItems) = preProject + Script_1.xml = Script_1.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Script_2", "Script_2", "{1BB5378B-1540-4FF6-815B-CEDAB5F7C03B}" + ProjectSection(SolutionItems) = preProject + Script_2.xml = Script_2.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D0EA8C5C-5350-42FA-B9BA-3E5D86070D20}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{BA001170-3E31-42E9-808A-BC7626B683F5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script_1a", "Script_1a\Script_1a.csproj", "{C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script_1b", "Script_1b\Script_1b.csproj", "{3048B168-DC53-4143-ADF1-DCD95B8539ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script_2", "Script_2\Script_2.csproj", "{1AE71A40-7865-4106-A15D-D8688AB231A6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutomationScript_ClassLibrary", "AutomationScript_ClassLibrary\AutomationScript_ClassLibrary.csproj", "{07DBE185-5EB9-4DF9-898E-1874A2907DA6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Subfolder1", "Subfolder1", "{88943879-C091-4E67-9707-F464F9F0546F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Subfolder2", "Subfolder2", "{4F2BD299-2ED7-49CD-A8A0-604C53F0329D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Release|Any CPU.Build.0 = Release|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Release|Any CPU.Build.0 = Release|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Release|Any CPU.Build.0 = Release|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F1C34D24-E21D-4477-B37C-07E5C234FE6C} = {88943879-C091-4E67-9707-F464F9F0546F} + {1BB5378B-1540-4FF6-815B-CEDAB5F7C03B} = {4F2BD299-2ED7-49CD-A8A0-604C53F0329D} + {D0EA8C5C-5350-42FA-B9BA-3E5D86070D20} = {F1C34D24-E21D-4477-B37C-07E5C234FE6C} + {BA001170-3E31-42E9-808A-BC7626B683F5} = {1BB5378B-1540-4FF6-815B-CEDAB5F7C03B} + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653} = {D0EA8C5C-5350-42FA-B9BA-3E5D86070D20} + {3048B168-DC53-4143-ADF1-DCD95B8539ED} = {D0EA8C5C-5350-42FA-B9BA-3E5D86070D20} + {1AE71A40-7865-4106-A15D-D8688AB231A6} = {BA001170-3E31-42E9-808A-BC7626B683F5} + {07DBE185-5EB9-4DF9-898E-1874A2907DA6} = {DC12C1A8-4C06-40EA-B204-30608CE534A6} + {88943879-C091-4E67-9707-F464F9F0546F} = {0BA1D4BE-635D-4E90-87CC-8DF145A5C25C} + {4F2BD299-2ED7-49CD-A8A0-604C53F0329D} = {0BA1D4BE-635D-4E90-87CC-8DF145A5C25C} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {58942BE7-5A68-461B-8F90-E06699C84F5C} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.cs new file mode 100644 index 0000000..b936d2f --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.cs @@ -0,0 +1,5 @@ +// This is auto-generated code by DIS. Do not modify. +namespace Skyline.DataMiner.Library +{ + +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.csproj new file mode 100644 index 0000000..5a72698 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.csproj @@ -0,0 +1,47 @@ + + + + + Debug + AnyCPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6} + Library + Properties + AutomationScript_ClassLibrary + AutomationScript_ClassLibrary + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1.xml new file mode 100644 index 0000000..0b19b6d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1.xml @@ -0,0 +1,29 @@ + + Script_1 + + Automation + FALSE + MyFolder + + + + + + + Reservation ID + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1a/Script.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1a/Script.cs new file mode 100644 index 0000000..8a88f75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1a/Script.cs @@ -0,0 +1,7 @@ +public class Script +{ + public void Run() + { + + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1a/Script_1a.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1a/Script_1a.csproj new file mode 100644 index 0000000..99e2362 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1a/Script_1a.csproj @@ -0,0 +1,50 @@ + + + + + Debug + AnyCPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653} + Library + Properties + Script_1a + Script_1a + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1b/Class1.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1b/Class1.cs new file mode 100644 index 0000000..0da90bf --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1b/Class1.cs @@ -0,0 +1,6 @@ +namespace Script_1b +{ + public class Class1 + { + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1b/Script.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1b/Script.cs new file mode 100644 index 0000000..8a88f75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1b/Script.cs @@ -0,0 +1,7 @@ +public class Script +{ + public void Run() + { + + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1b/Script_1b.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1b/Script_1b.csproj new file mode 100644 index 0000000..2b81127 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_1b/Script_1b.csproj @@ -0,0 +1,51 @@ + + + + + Debug + AnyCPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED} + Library + Properties + Script_1b + Script_1b + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_2.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_2.xml new file mode 100644 index 0000000..4cfbf6d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_2.xml @@ -0,0 +1,23 @@ + + Script_2 + + Automation + FALSE + MyFolder + + + + + + + Reservation ID + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_2/Script.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_2/Script.cs new file mode 100644 index 0000000..8a88f75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_2/Script.cs @@ -0,0 +1,7 @@ +public class Script +{ + public void Run() + { + + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_2/Script_2.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_2/Script_2.csproj new file mode 100644 index 0000000..44e4775 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution2/Script_2/Script_2.csproj @@ -0,0 +1,50 @@ + + + + + Debug + AnyCPU + {1AE71A40-7865-4106-A15D-D8688AB231A6} + Library + Properties + Script_2 + Script_2 + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/AutomationScript.sln b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/AutomationScript.sln new file mode 100644 index 0000000..089a900 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/AutomationScript.sln @@ -0,0 +1,85 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.1267 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{83A162A2-0BE3-4E70-B178-448B71D02A0D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{DC12C1A8-4C06-40EA-B204-30608CE534A6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{0BA1D4BE-635D-4E90-87CC-8DF145A5C25C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Script_1", "Script_1", "{F1C34D24-E21D-4477-B37C-07E5C234FE6C}" + ProjectSection(SolutionItems) = preProject + Script_1.xml = Script_1.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Script_2", "Script_2", "{1BB5378B-1540-4FF6-815B-CEDAB5F7C03B}" + ProjectSection(SolutionItems) = preProject + Script_2.xml = Script_2.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D0EA8C5C-5350-42FA-B9BA-3E5D86070D20}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{BA001170-3E31-42E9-808A-BC7626B683F5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script_1a", "Script_1a\Script_1a.csproj", "{C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script_1b", "Script_1b\Script_1b.csproj", "{3048B168-DC53-4143-ADF1-DCD95B8539ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Script_2", "Script_2\Script_2.csproj", "{1AE71A40-7865-4106-A15D-D8688AB231A6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutomationScript_ClassLibrary", "AutomationScript_ClassLibrary\AutomationScript_ClassLibrary.csproj", "{07DBE185-5EB9-4DF9-898E-1874A2907DA6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Subfolder1", "Subfolder1", "{88943879-C091-4E67-9707-F464F9F0546F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Subfolder2", "Subfolder2", "{4F2BD299-2ED7-49CD-A8A0-604C53F0329D}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SharedProject", "SharedProject\SharedProject.shproj", "{1EC081DC-91E9-437F-8E08-47AD8048EF64}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + SharedProject\SharedProject.projitems*{1ec081dc-91e9-437f-8e08-47ad8048ef64}*SharedItemsImports = 13 + SharedProject\SharedProject.projitems*{3048b168-dc53-4143-adf1-dcd95b8539ed}*SharedItemsImports = 4 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653}.Release|Any CPU.Build.0 = Release|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED}.Release|Any CPU.Build.0 = Release|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1AE71A40-7865-4106-A15D-D8688AB231A6}.Release|Any CPU.Build.0 = Release|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F1C34D24-E21D-4477-B37C-07E5C234FE6C} = {88943879-C091-4E67-9707-F464F9F0546F} + {1BB5378B-1540-4FF6-815B-CEDAB5F7C03B} = {4F2BD299-2ED7-49CD-A8A0-604C53F0329D} + {D0EA8C5C-5350-42FA-B9BA-3E5D86070D20} = {F1C34D24-E21D-4477-B37C-07E5C234FE6C} + {BA001170-3E31-42E9-808A-BC7626B683F5} = {1BB5378B-1540-4FF6-815B-CEDAB5F7C03B} + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653} = {D0EA8C5C-5350-42FA-B9BA-3E5D86070D20} + {3048B168-DC53-4143-ADF1-DCD95B8539ED} = {D0EA8C5C-5350-42FA-B9BA-3E5D86070D20} + {1AE71A40-7865-4106-A15D-D8688AB231A6} = {BA001170-3E31-42E9-808A-BC7626B683F5} + {07DBE185-5EB9-4DF9-898E-1874A2907DA6} = {DC12C1A8-4C06-40EA-B204-30608CE534A6} + {88943879-C091-4E67-9707-F464F9F0546F} = {0BA1D4BE-635D-4E90-87CC-8DF145A5C25C} + {4F2BD299-2ED7-49CD-A8A0-604C53F0329D} = {0BA1D4BE-635D-4E90-87CC-8DF145A5C25C} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {58942BE7-5A68-461B-8F90-E06699C84F5C} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.cs new file mode 100644 index 0000000..7e8f0cc --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.cs @@ -0,0 +1,5 @@ +// --- auto-generated code --- do not modify --- +namespace Skyline.DataMiner.Library +{ + +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.csproj new file mode 100644 index 0000000..5a72698 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/AutomationScript_ClassLibrary/AutomationScript_ClassLibrary.csproj @@ -0,0 +1,47 @@ + + + + + Debug + AnyCPU + {07DBE185-5EB9-4DF9-898E-1874A2907DA6} + Library + Properties + AutomationScript_ClassLibrary + AutomationScript_ClassLibrary + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1.xml new file mode 100644 index 0000000..0b19b6d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1.xml @@ -0,0 +1,29 @@ + + Script_1 + + Automation + FALSE + MyFolder + + + + + + + Reservation ID + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1a/Script.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1a/Script.cs new file mode 100644 index 0000000..8a88f75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1a/Script.cs @@ -0,0 +1,7 @@ +public class Script +{ + public void Run() + { + + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1a/Script_1a.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1a/Script_1a.csproj new file mode 100644 index 0000000..99e2362 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1a/Script_1a.csproj @@ -0,0 +1,50 @@ + + + + + Debug + AnyCPU + {C17D3C87-4F2C-47B4-AC1A-0B3BB66E1653} + Library + Properties + Script_1a + Script_1a + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1b/Class1.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1b/Class1.cs new file mode 100644 index 0000000..0da90bf --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1b/Class1.cs @@ -0,0 +1,6 @@ +namespace Script_1b +{ + public class Class1 + { + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1b/Script.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1b/Script.cs new file mode 100644 index 0000000..fbc9e04 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1b/Script.cs @@ -0,0 +1,10 @@ +using SharedProject; +public class Script +{ + public void Run() + { + + SharedCode myCode = new SharedCode(); + myCode.TestSharedCall(); + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1b/Script_1b.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1b/Script_1b.csproj new file mode 100644 index 0000000..9ceb518 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_1b/Script_1b.csproj @@ -0,0 +1,52 @@ + + + + + Debug + AnyCPU + {3048B168-DC53-4143-ADF1-DCD95B8539ED} + Library + Properties + Script_1b + Script_1b + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_2.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_2.xml new file mode 100644 index 0000000..4cfbf6d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_2.xml @@ -0,0 +1,23 @@ + + Script_2 + + Automation + FALSE + MyFolder + + + + + + + Reservation ID + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_2/Script.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_2/Script.cs new file mode 100644 index 0000000..8a88f75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_2/Script.cs @@ -0,0 +1,7 @@ +public class Script +{ + public void Run() + { + + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_2/Script_2.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_2/Script_2.csproj new file mode 100644 index 0000000..44e4775 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/Script_2/Script_2.csproj @@ -0,0 +1,50 @@ + + + + + Debug + AnyCPU + {1AE71A40-7865-4106-A15D-D8688AB231A6} + Library + Properties + Script_2 + Script_2 + v4.7 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/MoreSharedCode.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/MoreSharedCode.cs new file mode 100644 index 0000000..e8d3927 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/MoreSharedCode.cs @@ -0,0 +1,12 @@ +namespace SharedProject +{ + using System.Threading; + + public class UnusedSharedCode + { + public void JustAnotherCall() + { + Thread.Sleep(100); + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/SharedCode.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/SharedCode.cs new file mode 100644 index 0000000..a8bf4f8 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/SharedCode.cs @@ -0,0 +1,10 @@ +namespace SharedProject +{ + public class SharedCode + { + public bool TestSharedCall() + { + return true; + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/SharedProject.projitems b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/SharedProject.projitems new file mode 100644 index 0000000..31f694d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/SharedProject.projitems @@ -0,0 +1,15 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 1ec081dc-91e9-437f-8e08-47ad8048ef64 + + + SharedProject + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/SharedProject.shproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/SharedProject.shproj new file mode 100644 index 0000000..a8c4b15 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution3/SharedProject/SharedProject.shproj @@ -0,0 +1,13 @@ + + + + 1ec081dc-91e9-437f-8e08-47ad8048ef64 + 14.0 + + + + + + + + diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/AutomationScript.sln b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/AutomationScript.sln new file mode 100644 index 0000000..a65093d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/AutomationScript.sln @@ -0,0 +1,58 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.1684 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{E7D3511B-D22F-4DBD-B2C2-7A8C727B3C0F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{48D8F878-FAEF-4765-B4CF-80FF2639D521}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{DB881A31-8F8F-47B9-8FAE-4CF141CF9587}" + ProjectSection(SolutionItems) = preProject + Dlls\readme.txt = Dlls\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{C7CE0082-E626-4AAC-B896-FA9633E802DD}" + ProjectSection(SolutionItems) = preProject + Documentation\readme.txt = Documentation\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{B48FAA81-E887-4C35-8C4D-0C22E76AD7D7}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\SonarLint-QuickActions-Active.ruleset = Internal\Code Analysis\SonarLint-QuickActions-Active.ruleset + Internal\Code Analysis\SonarLint-QuickActions-Inactive.ruleset = Internal\Code Analysis\SonarLint-QuickActions-Inactive.ruleset + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NewNugetTest", "NewNugetTest", "{A9C49E31-C166-481A-82F8-1884440C9A1A}" + ProjectSection(SolutionItems) = preProject + NewNugetTest.xml = NewNugetTest.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{46AAC8F1-FF8D-43BC-BA59-E8E52C22BAF7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NewNugetTest_1", "NewNugetTest_1\NewNugetTest_1.csproj", "{6CD1E51A-B664-48D4-8A51-8E6D987774F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6CD1E51A-B664-48D4-8A51-8E6D987774F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CD1E51A-B664-48D4-8A51-8E6D987774F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CD1E51A-B664-48D4-8A51-8E6D987774F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CD1E51A-B664-48D4-8A51-8E6D987774F2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {B48FAA81-E887-4C35-8C4D-0C22E76AD7D7} = {E7D3511B-D22F-4DBD-B2C2-7A8C727B3C0F} + {A9C49E31-C166-481A-82F8-1884440C9A1A} = {48D8F878-FAEF-4765-B4CF-80FF2639D521} + {46AAC8F1-FF8D-43BC-BA59-E8E52C22BAF7} = {A9C49E31-C166-481A-82F8-1884440C9A1A} + {6CD1E51A-B664-48D4-8A51-8E6D987774F2} = {46AAC8F1-FF8D-43BC-BA59-E8E52C22BAF7} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9769F039-DCCE-4887-8816-3C2B8E219941} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest.xml new file mode 100644 index 0000000..5041371 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest.xml @@ -0,0 +1,26 @@ + + + NewNugetTest + + Automation + SKYLINE2\Pedro + FALSE + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/.editorconfig b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/NewNugetTest_1.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/NewNugetTest_1.cs new file mode 100644 index 0000000..1ce974e --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/NewNugetTest_1.cs @@ -0,0 +1,71 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using Skyline.DataMiner.Automation; + +/// +/// DataMiner Script Class. +/// +public class Script +{ + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/NewNugetTest_1.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/NewNugetTest_1.csproj new file mode 100644 index 0000000..0afdb1c --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/NewNugetTest_1.csproj @@ -0,0 +1,83 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {6CD1E51A-B664-48D4-8A51-8E6D987774F2} + Library + Properties + NewNugetTest_1 + NewNugetTest_1 + v4.6.2 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\SonarLint-QuickActions-Active.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\SonarLint-QuickActions-Inactive.ruleset + + + None + + + + + C:\Skyline DataMiner\Files\SLManagedAutomation.dll + + + C:\Skyline DataMiner\Files\SLNetTypes.dll + + + + C:\Skyline DataMiner\Files\Skyline.DataMiner.Storage.Types.dll + + + C:\Skyline DataMiner\ProtocolScripts\SLLoggerUtil.dll + + + + + + + + + + + 0.1.0 + + + 1.0.2 + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/Properties/AssemblyInfo.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a4785c2 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("NewNugetTest_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("NewNugetTest_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("61EDA42D-AB3D-40AA-9D1C-EBC5AEEB2C67")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/Settings.StyleCop b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/Settings.StyleCop new file mode 100644 index 0000000..341ff75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution4/NewNugetTest_1/Settings.StyleCop @@ -0,0 +1,301 @@ + + + NoMerge + + + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + + ab + ac + ad + af + ai + al + ao + as + ax + b + by + c + d + dt + e + f + hs + i + ip + is + l + lb + lc + ld + lf + li + ll + lo + ls + lx + no + o + qb + qc + qd + qf + qi + ql + qo + qs + qx + rx + s + sb + sc + sd + sf + sh + si + sl + so + ss + sx + to + ts + tx + ui + ul + x + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + True + + + + + True + + + + + True + + + + + False + + + + + False + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/.gitignore b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/.gitignore new file mode 100644 index 0000000..7ded850 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/.gitignore @@ -0,0 +1,17 @@ +**/bin/* +**/obj/* +.vs/* +packages/* +**/.svn +_git2_* +**/StyleCop.Cache +# solution user option files +*.suo +# protocol checklist template +**/*.dotx +# Temporary MS Office file (opened document) +~$* +# visual studio project user setting +**/*.csproj.user +# resharper solution user settings +*sln.DotSettings.user \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/AutomationScript.sln b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/AutomationScript.sln new file mode 100644 index 0000000..85a836d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/AutomationScript.sln @@ -0,0 +1,58 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33110.190 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{3362CAC5-3701-4E61-83EF-3CB7BF5F3E94}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{03C1835A-27E5-4514-B9A9-19F184AFFB5D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{0B655075-9F22-4C94-B53F-6F403E25AC0E}" + ProjectSection(SolutionItems) = preProject + Dlls\readme.txt = Dlls\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{D9AD8CEE-CE8F-41E6-97D0-241941A6A5AD}" + ProjectSection(SolutionItems) = preProject + Documentation\readme.txt = Documentation\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{C6E1C69B-206C-4E66-B2C2-681032A75D80}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\qaction-debug.ruleset = Internal\Code Analysis\qaction-debug.ruleset + Internal\Code Analysis\qaction-release.ruleset = Internal\Code Analysis\qaction-release.ruleset + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "New", "New", "{93EAC44B-4FA9-477D-9362-3C0E1913F54B}" + ProjectSection(SolutionItems) = preProject + New.xml = New.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{ED261820-7657-4A75-B768-893FE426237E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "New_1", "New_1\New_1.csproj", "{E4790A62-ED3B-4FE8-8B27-75CAA38C3F74}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4790A62-ED3B-4FE8-8B27-75CAA38C3F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4790A62-ED3B-4FE8-8B27-75CAA38C3F74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4790A62-ED3B-4FE8-8B27-75CAA38C3F74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4790A62-ED3B-4FE8-8B27-75CAA38C3F74}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C6E1C69B-206C-4E66-B2C2-681032A75D80} = {3362CAC5-3701-4E61-83EF-3CB7BF5F3E94} + {93EAC44B-4FA9-477D-9362-3C0E1913F54B} = {03C1835A-27E5-4514-B9A9-19F184AFFB5D} + {ED261820-7657-4A75-B768-893FE426237E} = {93EAC44B-4FA9-477D-9362-3C0E1913F54B} + {E4790A62-ED3B-4FE8-8B27-75CAA38C3F74} = {ED261820-7657-4A75-B768-893FE426237E} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {92A0A026-B765-43A6-98A0-931CA4DBD93E} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Dlls/MyCustomDll.dll b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Dlls/MyCustomDll.dll new file mode 100644 index 0000000..d6c69d5 Binary files /dev/null and b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Dlls/MyCustomDll.dll differ diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Dlls/readme.txt b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Dlls/readme.txt new file mode 100644 index 0000000..a3170b3 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Dlls/readme.txt @@ -0,0 +1 @@ +This folder contains DLL files that should be placed under the ProtocolScripts folder of DataMiner for this solution to work correctly. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Documentation/readme.txt b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Documentation/readme.txt new file mode 100644 index 0000000..11d30e6 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Documentation/readme.txt @@ -0,0 +1 @@ +This folder can be used to add documentation related to this solution. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Internal/Code Analysis/qaction-debug.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Internal/Code Analysis/qaction-debug.ruleset new file mode 100644 index 0000000..d7c0503 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Internal/Code Analysis/qaction-debug.ruleset @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Internal/Code Analysis/qaction-release.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Internal/Code Analysis/qaction-release.ruleset new file mode 100644 index 0000000..4981097 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/Internal/Code Analysis/qaction-release.ruleset @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New.xml new file mode 100644 index 0000000..db68c5a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New.xml @@ -0,0 +1,26 @@ + + + New + + Automation + SKYLINE2\Pedro + FALSE + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/.editorconfig b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/Class1.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/Class1.cs new file mode 100644 index 0000000..bf47ca4 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/Class1.cs @@ -0,0 +1,72 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +using Skyline.DataMiner.Automation; + +/// +/// DataMiner Script Class. +/// +public class Script +{ + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + engine.GenerateInformation("testing"); + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/New_1.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/New_1.csproj new file mode 100644 index 0000000..e506387 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/New_1.csproj @@ -0,0 +1,30 @@ + + + + netframework462 + disable + disable + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + ..\Dlls\MyCustomDll.dll + myCustomValue + + + + + + + + + + diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/Subfolder/Class2.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/Subfolder/Class2.cs new file mode 100644 index 0000000..04de83f --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/Subfolder/Class2.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace New_1.Subfolder +{ + internal class Class2 + { + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/stylecop.json b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution5/New_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/AutomationScript.sln b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/AutomationScript.sln new file mode 100644 index 0000000..32898ba --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/AutomationScript.sln @@ -0,0 +1,74 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33502.453 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{892C2BFC-8E2F-48DD-9B8A-890124492FE7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{34958EFF-5785-4B05-820A-539D79CEF5AB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{DE6BEE84-EFC7-412F-95A6-19AFBF1D1C4C}" + ProjectSection(SolutionItems) = preProject + Dlls\readme.txt = Dlls\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{5E0D403E-AF71-4AEB-8209-B1FA672633B0}" + ProjectSection(SolutionItems) = preProject + Documentation\readme.txt = Documentation\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{C5010500-5CCC-415A-B900-839A85064AD5}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\qaction-debug.ruleset = Internal\Code Analysis\qaction-debug.ruleset + Internal\Code Analysis\qaction-release.ruleset = Internal\Code Analysis\qaction-release.ruleset + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utils", "Utils", "{1C822BEE-4BD0-42B3-AFE4-E7187B995140}" + ProjectSection(SolutionItems) = preProject + Utils.xml = Utils.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{B96B64C6-06B9-4B2C-9AB3-1034A4FCB5EC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils_2", "Utils_2\Utils_2.csproj", "{87166617-8543-461B-AAD9-D1251586D3A9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SimpleScript", "SimpleScript", "{64B29F28-AD64-4691-AD38-B2DEDF3047F8}" + ProjectSection(SolutionItems) = preProject + SimpleScript.xml = SimpleScript.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{CB60A7F9-F32C-4673-A492-44CDE4583280}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleScript_2", "SimpleScript_2\SimpleScript_2.csproj", "{9A325A21-7645-4FD2-98B7-98BBB53464F3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {87166617-8543-461B-AAD9-D1251586D3A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87166617-8543-461B-AAD9-D1251586D3A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87166617-8543-461B-AAD9-D1251586D3A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87166617-8543-461B-AAD9-D1251586D3A9}.Release|Any CPU.Build.0 = Release|Any CPU + {9A325A21-7645-4FD2-98B7-98BBB53464F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A325A21-7645-4FD2-98B7-98BBB53464F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A325A21-7645-4FD2-98B7-98BBB53464F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A325A21-7645-4FD2-98B7-98BBB53464F3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C5010500-5CCC-415A-B900-839A85064AD5} = {892C2BFC-8E2F-48DD-9B8A-890124492FE7} + {1C822BEE-4BD0-42B3-AFE4-E7187B995140} = {34958EFF-5785-4B05-820A-539D79CEF5AB} + {B96B64C6-06B9-4B2C-9AB3-1034A4FCB5EC} = {1C822BEE-4BD0-42B3-AFE4-E7187B995140} + {87166617-8543-461B-AAD9-D1251586D3A9} = {B96B64C6-06B9-4B2C-9AB3-1034A4FCB5EC} + {64B29F28-AD64-4691-AD38-B2DEDF3047F8} = {34958EFF-5785-4B05-820A-539D79CEF5AB} + {CB60A7F9-F32C-4673-A492-44CDE4583280} = {64B29F28-AD64-4691-AD38-B2DEDF3047F8} + {9A325A21-7645-4FD2-98B7-98BBB53464F3} = {CB60A7F9-F32C-4673-A492-44CDE4583280} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FEBD1C0E-0FBA-4B7B-8B02-991A1E16EF9A} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Dlls/readme.txt b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Dlls/readme.txt new file mode 100644 index 0000000..a3170b3 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Dlls/readme.txt @@ -0,0 +1 @@ +This folder contains DLL files that should be placed under the ProtocolScripts folder of DataMiner for this solution to work correctly. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Documentation/readme.txt b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Documentation/readme.txt new file mode 100644 index 0000000..11d30e6 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Documentation/readme.txt @@ -0,0 +1 @@ +This folder can be used to add documentation related to this solution. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Internal/Code Analysis/qaction-debug.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Internal/Code Analysis/qaction-debug.ruleset new file mode 100644 index 0000000..d7c0503 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Internal/Code Analysis/qaction-debug.ruleset @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Internal/Code Analysis/qaction-release.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Internal/Code Analysis/qaction-release.ruleset new file mode 100644 index 0000000..4981097 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Internal/Code Analysis/qaction-release.ruleset @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript.xml new file mode 100644 index 0000000..f20d465 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript.xml @@ -0,0 +1,20 @@ + + SimpleScript + + Automation + SKYLINE2\Pedro + FALSE + + + + + + + + + diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/.editorconfig b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/Properties/AssemblyInfo.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..26421d8 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("SimpleScript_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("SimpleScript_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("B0CE18F2-D752-484B-AFB6-7872E5EE9C3E")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/SimpleScript_2.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/SimpleScript_2.cs new file mode 100644 index 0000000..b959a14 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/SimpleScript_2.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using Skyline.DataMiner.Automation; +using MyUtils; + +/// +/// DataMiner Script Class. +/// +public class Script +{ + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + engine.GenerateInformation(Utils.MakeUppercase("test")); + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/SimpleScript_2.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/SimpleScript_2.csproj new file mode 100644 index 0000000..b02bde5 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/SimpleScript_2.csproj @@ -0,0 +1,78 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {9A325A21-7645-4FD2-98B7-98BBB53464F3} + Library + Properties + SimpleScript_2 + SimpleScript_2 + v4.6.2 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\SimpleScript_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\SimpleScript_2.xml + + + None + + + + {87166617-8543-461b-aad9-d1251586d3a9} + Utils_2 + + + + + + + + + + + + 10.0.0.5 + + + 1.1.118 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/stylecop.json b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/SimpleScript_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils.xml new file mode 100644 index 0000000..67dbc74 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils.xml @@ -0,0 +1,22 @@ + + Utils + + Automation + SKYLINE2\Pedro + FALSE + + + + + + + + + diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/.editorconfig b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/Properties/AssemblyInfo.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8c5e770 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Utils_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("Utils_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("25C16F9B-80D8-45DE-B4F6-A17E277E12DD")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/Utils_2.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/Utils_2.cs new file mode 100644 index 0000000..b0fb546 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/Utils_2.cs @@ -0,0 +1,10 @@ +namespace MyUtils +{ + public static class Utils + { + public static string MakeUppercase(string input) + { + return input.ToUpper(); + } + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/Utils_2.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/Utils_2.csproj new file mode 100644 index 0000000..8d2492d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/Utils_2.csproj @@ -0,0 +1,74 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {87166617-8543-461B-AAD9-D1251586D3A9} + Library + Properties + Utils_2 + Utils_2 + v4.6.2 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\Utils_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\Utils_2.xml + + + None + + + + + + + + + + + + + 10.0.0.5 + + + 1.1.118 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/stylecop.json b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution6/Utils_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/AutomationScript.sln b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/AutomationScript.sln new file mode 100644 index 0000000..0d00cfd --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/AutomationScript.sln @@ -0,0 +1,65 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33502.453 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{74EC3B5D-279A-4458-B23E-235E86366109}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{82AC8482-EA26-4153-9C1B-994469D318CC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{6940B21B-8AC6-4D0D-B025-F49C90DDE4DA}" + ProjectSection(SolutionItems) = preProject + Dlls\readme.txt = Dlls\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{F100D64F-A820-4171-ACC1-D832C68B0B5F}" + ProjectSection(SolutionItems) = preProject + Documentation\readme.txt = Documentation\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{A13EA19C-3E66-422E-9342-ACDE32D832C9}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\qaction-debug.ruleset = Internal\Code Analysis\qaction-debug.ruleset + Internal\Code Analysis\qaction-release.ruleset = Internal\Code Analysis\qaction-release.ruleset + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LibraryInOwnScript", "LibraryInOwnScript", "{1EF77561-8791-4C0E-B761-83971BB91E91}" + ProjectSection(SolutionItems) = preProject + LibraryInOwnScript.xml = LibraryInOwnScript.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{91D5272F-D073-4BFF-9902-A3B9D5E55628}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibraryInOwnScript_1", "LibraryInOwnScript_1\LibraryInOwnScript_1.csproj", "{294DDEE0-3E2C-404D-8800-42FE6E040093}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibraryInOwnScript_2", "LibraryInOwnScript_2\LibraryInOwnScript_2.csproj", "{11CD0370-EB38-4DC2-8889-A8F4C9153618}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {294DDEE0-3E2C-404D-8800-42FE6E040093}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {294DDEE0-3E2C-404D-8800-42FE6E040093}.Debug|Any CPU.Build.0 = Debug|Any CPU + {294DDEE0-3E2C-404D-8800-42FE6E040093}.Release|Any CPU.ActiveCfg = Release|Any CPU + {294DDEE0-3E2C-404D-8800-42FE6E040093}.Release|Any CPU.Build.0 = Release|Any CPU + {11CD0370-EB38-4DC2-8889-A8F4C9153618}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11CD0370-EB38-4DC2-8889-A8F4C9153618}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11CD0370-EB38-4DC2-8889-A8F4C9153618}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11CD0370-EB38-4DC2-8889-A8F4C9153618}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {A13EA19C-3E66-422E-9342-ACDE32D832C9} = {74EC3B5D-279A-4458-B23E-235E86366109} + {1EF77561-8791-4C0E-B761-83971BB91E91} = {82AC8482-EA26-4153-9C1B-994469D318CC} + {91D5272F-D073-4BFF-9902-A3B9D5E55628} = {1EF77561-8791-4C0E-B761-83971BB91E91} + {294DDEE0-3E2C-404D-8800-42FE6E040093} = {91D5272F-D073-4BFF-9902-A3B9D5E55628} + {11CD0370-EB38-4DC2-8889-A8F4C9153618} = {91D5272F-D073-4BFF-9902-A3B9D5E55628} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FFF3BC1D-E941-48A5-810C-4733E5CDB21A} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Dlls/readme.txt b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Dlls/readme.txt new file mode 100644 index 0000000..a3170b3 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Dlls/readme.txt @@ -0,0 +1 @@ +This folder contains DLL files that should be placed under the ProtocolScripts folder of DataMiner for this solution to work correctly. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Documentation/readme.txt b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Documentation/readme.txt new file mode 100644 index 0000000..11d30e6 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Documentation/readme.txt @@ -0,0 +1 @@ +This folder can be used to add documentation related to this solution. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Internal/Code Analysis/qaction-debug.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Internal/Code Analysis/qaction-debug.ruleset new file mode 100644 index 0000000..d7c0503 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Internal/Code Analysis/qaction-debug.ruleset @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Internal/Code Analysis/qaction-release.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Internal/Code Analysis/qaction-release.ruleset new file mode 100644 index 0000000..4981097 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/Internal/Code Analysis/qaction-release.ruleset @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript.xml new file mode 100644 index 0000000..06a1fe8 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript.xml @@ -0,0 +1,33 @@ + + + LibraryInOwnScript + + Automation + SKYLINE2\Pedro + FALSE + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/.editorconfig b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/LibraryInOwnScript_1.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/LibraryInOwnScript_1.cs new file mode 100644 index 0000000..e44f3e9 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/LibraryInOwnScript_1.cs @@ -0,0 +1,11 @@ +using MyUtils; + +using Skyline.DataMiner.Automation; + +public class Script +{ + public void Run(Engine engine) + { + engine.GenerateInformation(Utils.MakeUppercase("test")); + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/LibraryInOwnScript_1.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/LibraryInOwnScript_1.csproj new file mode 100644 index 0000000..c123d58 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/LibraryInOwnScript_1.csproj @@ -0,0 +1,80 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {294DDEE0-3E2C-404D-8800-42FE6E040093} + Library + Properties + LibraryInOwnScript_1 + LibraryInOwnScript_1 + v4.6.2 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\LibraryInOwnScript_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\LibraryInOwnScript_1.xml + + + None + + + + + + + + + + + + + 10.0.0.5 + + + 1.1.118 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + {11cd0370-eb38-4dc2-8889-a8f4c9153618} + LibraryInOwnScript_2 + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/Properties/AssemblyInfo.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..11a9e3b --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("LibraryInOwnScript_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("LibraryInOwnScript_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("94A92E5F-97D1-4154-92AB-6739FA50259B")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/stylecop.json b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/.editorconfig b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/LibraryInOwnScript_2.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/LibraryInOwnScript_2.cs new file mode 100644 index 0000000..b0fb546 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/LibraryInOwnScript_2.cs @@ -0,0 +1,10 @@ +namespace MyUtils +{ + public static class Utils + { + public static string MakeUppercase(string input) + { + return input.ToUpper(); + } + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/LibraryInOwnScript_2.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/LibraryInOwnScript_2.csproj new file mode 100644 index 0000000..53fe672 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/LibraryInOwnScript_2.csproj @@ -0,0 +1,74 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {11CD0370-EB38-4DC2-8889-A8F4C9153618} + Library + Properties + LibraryInOwnScript_2 + LibraryInOwnScript_2 + v4.6.2 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\LibraryInOwnScript_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\LibraryInOwnScript_2.xml + + + None + + + + + + + + + + + + + 10.0.0.5 + + + 1.1.118 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/Properties/AssemblyInfo.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ed58ab8 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("LibraryInOwnScript_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("LibraryInOwnScript_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("E78B87C1-A88E-4D9D-B050-82B9C27D0B8E")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/stylecop.json b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution7/LibraryInOwnScript_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/CompanionFiles/Skyline DataMiner/AboutThisFolder.md b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/CompanionFiles/Skyline DataMiner/AboutThisFolder.md new file mode 100644 index 0000000..a7fc8db --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/CompanionFiles/Skyline DataMiner/AboutThisFolder.md @@ -0,0 +1 @@ +This folder can contain any file you would like to add under the Skyline DataMiner folder while installing the Automation scripts. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Directory.Build.props b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Directory.Build.props new file mode 100644 index 0000000..5c71c5b --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Directory.Build.props @@ -0,0 +1,20 @@ + + + x86 + true + + + + Properties\stylecop.json + + + Properties\.editorconfig + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Dlls/ABOUT.md b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Dlls/ABOUT.md new file mode 100644 index 0000000..a3170b3 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Dlls/ABOUT.md @@ -0,0 +1 @@ +This folder contains DLL files that should be placed under the ProtocolScripts folder of DataMiner for this solution to work correctly. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Documentation/ABOUT.md b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Documentation/ABOUT.md new file mode 100644 index 0000000..a150545 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Documentation/ABOUT.md @@ -0,0 +1 @@ +Looking for README.md? Check your Solution Root folder. This folder can be used to add documentation related to this solution. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/.editorconfig b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/Code Analysis/qaction-debug.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/Code Analysis/qaction-debug.ruleset new file mode 100644 index 0000000..26e7d46 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/Code Analysis/qaction-debug.ruleset @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/Code Analysis/qaction-release.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/Code Analysis/qaction-release.ruleset new file mode 100644 index 0000000..de0890a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/Code Analysis/qaction-release.ruleset @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/Code Analysis/stylecop.json b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/Code Analysis/stylecop.json new file mode 100644 index 0000000..b2d519d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Internal/Code Analysis/stylecop.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "indentation": { + "useTabs": true, + "tabSize": 4 + }, + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/README.md b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/README.md new file mode 100644 index 0000000..f325b14 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/README.md @@ -0,0 +1 @@ +# SRM_References \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/SRM_References.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/SRM_References.xml new file mode 100644 index 0000000..9700ca2 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/SRM_References.xml @@ -0,0 +1,26 @@ + + + SRM_References + + Automation + SKYLINE2\XXX + FALSE + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/SRM_References_1/SRM_References_1.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/SRM_References_1/SRM_References_1.cs new file mode 100644 index 0000000..4c6d345 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/SRM_References_1/SRM_References_1.cs @@ -0,0 +1,74 @@ +/* +**************************************************************************** +* Copyright (c) 2024, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +09/01/2024 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace SRM_References_1 +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Text; + using Skyline.DataMiner.Automation; + + /// + /// Represents a DataMiner Automation script. + /// + public class Script + { + /// + /// The script entry point. + /// + /// Link with SLAutomation process. + public void Run(IEngine engine) + { + + } + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/SRM_References_1/SRM_References_1.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/SRM_References_1/SRM_References_1.csproj new file mode 100644 index 0000000..e48e0d6 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/SRM_References_1/SRM_References_1.csproj @@ -0,0 +1,29 @@ + + + net462 + Skyline Communications + © Skyline Communications + true + + + full + ..\Internal\Code Analysis\qaction-debug.ruleset + + + pdbonly + ..\Internal\Code Analysis\qaction-release.ruleset + + + $(DefineConstants);DCFv1;DBInfo;ALARM_SQUASHING + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Solution8.sln b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Solution8.sln new file mode 100644 index 0000000..9018e75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution8/Solution8.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33502.453 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{A87088A1-0B35-4491-909D-187087198E1B}" + ProjectSection(SolutionItems) = preProject + Internal\.editorconfig = Internal\.editorconfig + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{6F70CA70-E53E-4109-92E7-265D98D548BE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{471BB13E-D62E-407F-9F53-B3EA4653F9BD}" + ProjectSection(SolutionItems) = preProject + Dlls\ABOUT.md = Dlls\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CompanionFiles", "CompanionFiles", "{26FCFCA0-71B5-4026-B097-AA5A17659EC0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Skyline DataMiner", "Skyline DataMiner", "{5032461D-2741-41E8-B247-27EBBA68E05E}" + ProjectSection(SolutionItems) = preProject + CompanionFiles\Skyline DataMiner\AboutThisFolder.md = CompanionFiles\Skyline DataMiner\AboutThisFolder.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{B3274593-F594-45F2-932A-16488B459B5B}" + ProjectSection(SolutionItems) = preProject + Documentation\ABOUT.md = Documentation\ABOUT.md + README.md = README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{F8938D60-51A0-4880-9CFC-19C66379BB5D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{EE32BE80-C8BB-4815-B894-A5C78DD4E4E1}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\qaction-debug.ruleset = Internal\Code Analysis\qaction-debug.ruleset + Internal\Code Analysis\qaction-release.ruleset = Internal\Code Analysis\qaction-release.ruleset + Internal\Code Analysis\stylecop.json = Internal\Code Analysis\stylecop.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SRM_References", "SRM_References", "{8DF060FB-76A9-43D6-85DD-1BEA7F4D34E7}" + ProjectSection(SolutionItems) = preProject + SRM_References.xml = SRM_References.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{7D094640-D749-4446-9BC3-F6BC0FA431CE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SRM_References_1", "SRM_References_1\SRM_References_1.csproj", "{8C08780C-A0D6-4957-A375-ABC625462D26}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8C08780C-A0D6-4957-A375-ABC625462D26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C08780C-A0D6-4957-A375-ABC625462D26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C08780C-A0D6-4957-A375-ABC625462D26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C08780C-A0D6-4957-A375-ABC625462D26}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5032461D-2741-41E8-B247-27EBBA68E05E} = {26FCFCA0-71B5-4026-B097-AA5A17659EC0} + {EE32BE80-C8BB-4815-B894-A5C78DD4E4E1} = {A87088A1-0B35-4491-909D-187087198E1B} + {8DF060FB-76A9-43D6-85DD-1BEA7F4D34E7} = {6F70CA70-E53E-4109-92E7-265D98D548BE} + {7D094640-D749-4446-9BC3-F6BC0FA431CE} = {8DF060FB-76A9-43D6-85DD-1BEA7F4D34E7} + {8C08780C-A0D6-4957-A375-ABC625462D26} = {7D094640-D749-4446-9BC3-F6BC0FA431CE} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E417B42F-4058-46CD-83CA-C981FA714F7C} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/CompanionFiles/Skyline DataMiner/AboutThisFolder.md b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/CompanionFiles/Skyline DataMiner/AboutThisFolder.md new file mode 100644 index 0000000..a7fc8db --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/CompanionFiles/Skyline DataMiner/AboutThisFolder.md @@ -0,0 +1 @@ +This folder can contain any file you would like to add under the Skyline DataMiner folder while installing the Automation scripts. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Directory.Build.props b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Directory.Build.props new file mode 100644 index 0000000..5c71c5b --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Directory.Build.props @@ -0,0 +1,20 @@ + + + x86 + true + + + + Properties\stylecop.json + + + Properties\.editorconfig + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Dlls/ABOUT.md b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Dlls/ABOUT.md new file mode 100644 index 0000000..a3170b3 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Dlls/ABOUT.md @@ -0,0 +1 @@ +This folder contains DLL files that should be placed under the ProtocolScripts folder of DataMiner for this solution to work correctly. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Documentation/ABOUT.md b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Documentation/ABOUT.md new file mode 100644 index 0000000..a150545 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Documentation/ABOUT.md @@ -0,0 +1 @@ +Looking for README.md? Check your Solution Root folder. This folder can be used to add documentation related to this solution. \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/.editorconfig b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/Code Analysis/qaction-debug.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/Code Analysis/qaction-debug.ruleset new file mode 100644 index 0000000..26e7d46 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/Code Analysis/qaction-debug.ruleset @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/Code Analysis/qaction-release.ruleset b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/Code Analysis/qaction-release.ruleset new file mode 100644 index 0000000..de0890a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/Code Analysis/qaction-release.ruleset @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/Code Analysis/stylecop.json b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/Code Analysis/stylecop.json new file mode 100644 index 0000000..b2d519d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Internal/Code Analysis/stylecop.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "indentation": { + "useTabs": true, + "tabSize": 4 + }, + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/README.md b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/README.md new file mode 100644 index 0000000..f325b14 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/README.md @@ -0,0 +1 @@ +# SRM_References \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/SRM_References.xml b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/SRM_References.xml new file mode 100644 index 0000000..9700ca2 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/SRM_References.xml @@ -0,0 +1,26 @@ + + + SRM_References + + Automation + SKYLINE2\XXX + FALSE + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/SRM_References_1/SRM_References_1.cs b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/SRM_References_1/SRM_References_1.cs new file mode 100644 index 0000000..4c6d345 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/SRM_References_1/SRM_References_1.cs @@ -0,0 +1,74 @@ +/* +**************************************************************************** +* Copyright (c) 2024, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +09/01/2024 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace SRM_References_1 +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Text; + using Skyline.DataMiner.Automation; + + /// + /// Represents a DataMiner Automation script. + /// + public class Script + { + /// + /// The script entry point. + /// + /// Link with SLAutomation process. + public void Run(IEngine engine) + { + + } + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/SRM_References_1/SRM_References_1.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/SRM_References_1/SRM_References_1.csproj new file mode 100644 index 0000000..105a39f --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/SRM_References_1/SRM_References_1.csproj @@ -0,0 +1,28 @@ + + + net462 + Skyline Communications + © Skyline Communications + true + + + full + ..\Internal\Code Analysis\qaction-debug.ruleset + + + pdbonly + ..\Internal\Code Analysis\qaction-release.ruleset + + + $(DefineConstants);DCFv1;DBInfo;ALARM_SQUASHING + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Solution9.sln b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Solution9.sln new file mode 100644 index 0000000..9018e75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/Solution9/Solution9.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33502.453 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{A87088A1-0B35-4491-909D-187087198E1B}" + ProjectSection(SolutionItems) = preProject + Internal\.editorconfig = Internal\.editorconfig + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{6F70CA70-E53E-4109-92E7-265D98D548BE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{471BB13E-D62E-407F-9F53-B3EA4653F9BD}" + ProjectSection(SolutionItems) = preProject + Dlls\ABOUT.md = Dlls\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CompanionFiles", "CompanionFiles", "{26FCFCA0-71B5-4026-B097-AA5A17659EC0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Skyline DataMiner", "Skyline DataMiner", "{5032461D-2741-41E8-B247-27EBBA68E05E}" + ProjectSection(SolutionItems) = preProject + CompanionFiles\Skyline DataMiner\AboutThisFolder.md = CompanionFiles\Skyline DataMiner\AboutThisFolder.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{B3274593-F594-45F2-932A-16488B459B5B}" + ProjectSection(SolutionItems) = preProject + Documentation\ABOUT.md = Documentation\ABOUT.md + README.md = README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{F8938D60-51A0-4880-9CFC-19C66379BB5D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{EE32BE80-C8BB-4815-B894-A5C78DD4E4E1}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\qaction-debug.ruleset = Internal\Code Analysis\qaction-debug.ruleset + Internal\Code Analysis\qaction-release.ruleset = Internal\Code Analysis\qaction-release.ruleset + Internal\Code Analysis\stylecop.json = Internal\Code Analysis\stylecop.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SRM_References", "SRM_References", "{8DF060FB-76A9-43D6-85DD-1BEA7F4D34E7}" + ProjectSection(SolutionItems) = preProject + SRM_References.xml = SRM_References.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{7D094640-D749-4446-9BC3-F6BC0FA431CE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SRM_References_1", "SRM_References_1\SRM_References_1.csproj", "{8C08780C-A0D6-4957-A375-ABC625462D26}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8C08780C-A0D6-4957-A375-ABC625462D26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C08780C-A0D6-4957-A375-ABC625462D26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C08780C-A0D6-4957-A375-ABC625462D26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C08780C-A0D6-4957-A375-ABC625462D26}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5032461D-2741-41E8-B247-27EBBA68E05E} = {26FCFCA0-71B5-4026-B097-AA5A17659EC0} + {EE32BE80-C8BB-4815-B894-A5C78DD4E4E1} = {A87088A1-0B35-4491-909D-187087198E1B} + {8DF060FB-76A9-43D6-85DD-1BEA7F4D34E7} = {6F70CA70-E53E-4109-92E7-265D98D548BE} + {7D094640-D749-4446-9BC3-F6BC0FA431CE} = {8DF060FB-76A9-43D6-85DD-1BEA7F4D34E7} + {8C08780C-A0D6-4957-A375-ABC625462D26} = {7D094640-D749-4446-9BC3-F6BC0FA431CE} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E417B42F-4058-46CD-83CA-C981FA714F7C} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/AutomationScript.sln b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/AutomationScript.sln new file mode 100644 index 0000000..a65093d --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/AutomationScript.sln @@ -0,0 +1,58 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.1684 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{E7D3511B-D22F-4DBD-B2C2-7A8C727B3C0F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{48D8F878-FAEF-4765-B4CF-80FF2639D521}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{DB881A31-8F8F-47B9-8FAE-4CF141CF9587}" + ProjectSection(SolutionItems) = preProject + Dlls\readme.txt = Dlls\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{C7CE0082-E626-4AAC-B896-FA9633E802DD}" + ProjectSection(SolutionItems) = preProject + Documentation\readme.txt = Documentation\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{B48FAA81-E887-4C35-8C4D-0C22E76AD7D7}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\SonarLint-QuickActions-Active.ruleset = Internal\Code Analysis\SonarLint-QuickActions-Active.ruleset + Internal\Code Analysis\SonarLint-QuickActions-Inactive.ruleset = Internal\Code Analysis\SonarLint-QuickActions-Inactive.ruleset + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NewNugetTest", "NewNugetTest", "{A9C49E31-C166-481A-82F8-1884440C9A1A}" + ProjectSection(SolutionItems) = preProject + NewNugetTest.xml = NewNugetTest.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{46AAC8F1-FF8D-43BC-BA59-E8E52C22BAF7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NewNugetTest_1", "NewNugetTest_1\NewNugetTest_1.csproj", "{6CD1E51A-B664-48D4-8A51-8E6D987774F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6CD1E51A-B664-48D4-8A51-8E6D987774F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CD1E51A-B664-48D4-8A51-8E6D987774F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CD1E51A-B664-48D4-8A51-8E6D987774F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CD1E51A-B664-48D4-8A51-8E6D987774F2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {B48FAA81-E887-4C35-8C4D-0C22E76AD7D7} = {E7D3511B-D22F-4DBD-B2C2-7A8C727B3C0F} + {A9C49E31-C166-481A-82F8-1884440C9A1A} = {48D8F878-FAEF-4765-B4CF-80FF2639D521} + {46AAC8F1-FF8D-43BC-BA59-E8E52C22BAF7} = {A9C49E31-C166-481A-82F8-1884440C9A1A} + {6CD1E51A-B664-48D4-8A51-8E6D987774F2} = {46AAC8F1-FF8D-43BC-BA59-E8E52C22BAF7} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9769F039-DCCE-4887-8816-3C2B8E219941} + EndGlobalSection +EndGlobal diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest.xml b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest.xml new file mode 100644 index 0000000..5041371 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest.xml @@ -0,0 +1,26 @@ + + + NewNugetTest + + Automation + SKYLINE2\Pedro + FALSE + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/.editorconfig b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/NewNugetTest_1.cs b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/NewNugetTest_1.cs new file mode 100644 index 0000000..00ecbff --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/NewNugetTest_1.cs @@ -0,0 +1,9 @@ +using Skyline.DataMiner.Automation; + +public class Script +{ + public void Run(Engine engine) + { + engine.GenerateInformation("test ›"); + } +} \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/NewNugetTest_1.csproj b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/NewNugetTest_1.csproj new file mode 100644 index 0000000..0afdb1c --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/NewNugetTest_1.csproj @@ -0,0 +1,83 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {6CD1E51A-B664-48D4-8A51-8E6D987774F2} + Library + Properties + NewNugetTest_1 + NewNugetTest_1 + v4.6.2 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\SonarLint-QuickActions-Active.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\SonarLint-QuickActions-Inactive.ruleset + + + None + + + + + C:\Skyline DataMiner\Files\SLManagedAutomation.dll + + + C:\Skyline DataMiner\Files\SLNetTypes.dll + + + + C:\Skyline DataMiner\Files\Skyline.DataMiner.Storage.Types.dll + + + C:\Skyline DataMiner\ProtocolScripts\SLLoggerUtil.dll + + + + + + + + + + + 0.1.0 + + + 1.0.2 + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/Properties/AssemblyInfo.cs b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a4785c2 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("NewNugetTest_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("NewNugetTest_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("61EDA42D-AB3D-40AA-9D1C-EBC5AEEB2C67")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/Settings.StyleCop b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/Settings.StyleCop new file mode 100644 index 0000000..341ff75 --- /dev/null +++ b/Assemblers.AutomationTests/TestFiles/Solutions/SpecialChar/NewNugetTest_1/Settings.StyleCop @@ -0,0 +1,301 @@ + + + NoMerge + + + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + + ab + ac + ad + af + ai + al + ao + as + ax + b + by + c + d + dt + e + f + hs + i + ip + is + l + lb + lc + ld + lf + li + ll + lo + ls + lx + no + o + qb + qc + qd + qf + qi + ql + qo + qs + qx + rx + s + sb + sc + sd + sf + sh + si + sl + so + ss + sx + to + ts + tx + ui + ul + x + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + True + + + + + True + + + + + True + + + + + False + + + + + False + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + \ No newline at end of file diff --git a/Assemblers.Common/AssemblerException.cs b/Assemblers.Common/AssemblerException.cs new file mode 100644 index 0000000..19f5d50 --- /dev/null +++ b/Assemblers.Common/AssemblerException.cs @@ -0,0 +1,45 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common +{ + using System; + using System.Runtime.Serialization; + + /// + /// The exception that is thrown when the DataMiner item could not be assembled. + /// + [Serializable] + public class AssemblerException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public AssemblerException() + { + } + + /// + /// Initializes a new instance of the class with a specified error message.. + /// + /// The message that describes the error. + public AssemblerException(string message) : base(message) + { + } + + /// + /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception. If the inner parameter is not null, the current exception is raised in a catch block that handles the inner exception. + public AssemblerException(string message, Exception inner) : base(message, inner) + { + } + + /// + /// Initializes a new instance of the class with serialized data. + /// + /// The object that holds the serialized object data. + /// The contextual information about the source or destination. + protected AssemblerException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} diff --git a/Assemblers.Common/Assemblers.Common.csproj b/Assemblers.Common/Assemblers.Common.csproj new file mode 100644 index 0000000..57c95f3 --- /dev/null +++ b/Assemblers.Common/Assemblers.Common.csproj @@ -0,0 +1,39 @@ + + + + netstandard2.0 + Skyline.DataMiner.CICD.Assemblers.Common + Skyline.DataMiner.CICD.Assemblers.Common + True + True + SkylineCommunications + Skyline Communications + LICENSE.txt + True + icon.png + https://skyline.be/ + Skyline;DataMiner;CICD + Library providing common methods for converting Visual Studio DIS Solutions to individual DataMiner artifacts (e.g. xml, dlls,...). + README.md + https://github.com/SkylineCommunications/Skyline.DataMiner.CICD.Packages + git + 0.0.2-local + + + + + + + + + + + + + + + + + + + diff --git a/Assemblers.Common/BuildResultItems.cs b/Assemblers.Common/BuildResultItems.cs new file mode 100644 index 0000000..750abd7 --- /dev/null +++ b/Assemblers.Common/BuildResultItems.cs @@ -0,0 +1,36 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common +{ + using System.Collections.Generic; + + /// + /// Represents the result items of a build. + /// + public class BuildResultItems + { + /// + /// Initializes a new instance of the class. + /// + public BuildResultItems() + { + Assemblies = new List(); + DllAssemblies = new List(); + } + + /// + /// Gets or sets the protocol or Automation script XML content. + /// + /// The protocol or Automation script XML content. + public string Document { get; set; } + + /// + /// Gets the assemblies of the used NuGet packages. + /// + /// The assemblies of the used NuGet packages. + public ICollection Assemblies { get; } + + /// + /// Gets the assemblies of the used DLLs (non-NuGet packages). + /// + public ICollection DllAssemblies { get; } + } +} diff --git a/Assemblers.Common/CSharpCodeCombiner.cs b/Assemblers.Common/CSharpCodeCombiner.cs new file mode 100644 index 0000000..911eac6 --- /dev/null +++ b/Assemblers.Common/CSharpCodeCombiner.cs @@ -0,0 +1,92 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + using Microsoft.CodeAnalysis.CSharp; + using Microsoft.CodeAnalysis.CSharp.Syntax; + + using Skyline.DataMiner.CICD.Parsers.Common.VisualStudio.Projects; + + /// + /// Combines code of multiple C# code files into a single file. + /// + public static class CSharpCodeCombiner + { + /// + /// Combines the code of the specified C# code files into a single file. + /// + /// The C# code files to combine. + /// The string that contains the combined code. + /// is null. + public static string CombineFiles(IList files) + { + if (files == null) + { + throw new ArgumentNullException(nameof(files)); + } + + StringBuilder newCode = new StringBuilder(); + + if (files.Count > 1) + { + var syntaxTrees = files.Select(f => CSharpSyntaxTree.ParseText(f.Content, path: f.Name)).ToList(); + var compilationUnitRoots = syntaxTrees.Where(t => t.HasCompilationUnitRoot).Select(t => t.GetCompilationUnitRoot()).ToList(); + + var usings = GetCombinedUsings(compilationUnitRoots); + newCode.AppendLine(SyntaxFactory.List(usings).ToFullString()); + + for (int i = 0; i < compilationUnitRoots.Count; i++) + { + var root = compilationUnitRoots[i]; + + if (i != 0) + { + newCode.AppendLine(); + } + + newCode.AppendLine("//---------------------------------"); + newCode.AppendLine("// " + root.SyntaxTree.FilePath); + newCode.AppendLine("//---------------------------------"); + + string code = root.Members.ToFullString(); + + newCode.Append(code); + } + } + else if (files.Count > 0) + { + newCode.Append(files[0].Content); + } + else + { + // No files. + } + + return newCode.ToString(); + } + + private static IEnumerable GetCombinedUsings(IList compilationUnitRoots) + { + var usings = new HashSet<(string, string)>(); + + foreach (var r in compilationUnitRoots) + { + foreach (var u in r.Usings) + { + string name = u.Name.ToString(); + string alias = u.Alias?.Name?.ToString(); + + if (!usings.Add((alias, name))) + { + continue; + } + + yield return u; + } + } + } + } +} \ No newline at end of file diff --git a/Assemblers.Common/DllAssemblyReference.cs b/Assemblers.Common/DllAssemblyReference.cs new file mode 100644 index 0000000..dec9b39 --- /dev/null +++ b/Assemblers.Common/DllAssemblyReference.cs @@ -0,0 +1,64 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common +{ + /// + /// Represents an assembly reference of a local DLL. + /// + public class DllAssemblyReference + { + /// + /// Initializes a new instance of the class. + /// + /// The import value for the QAction@dllImport attribute or Exe/Param element. + /// The assembly file path. + public DllAssemblyReference(string dllImport, string assemblyPath) + { + DllImport = dllImport; + AssemblyPath = assemblyPath; + } + + /// + /// Initializes a new instance of the class. + /// + /// The import value for the QAction@dllImport attribute or Exe/Param element. + /// The assembly file path. + /// Determine if this is a package of the Files folder. + public DllAssemblyReference(string dllImport, string assemblyPath, bool isFilesPackage) : this(dllImport, assemblyPath) + { + IsFilesPackage = isFilesPackage; + } + + /// + /// Gets the dllImport value. + /// + /// The dllImport value. + /// + /// + /// + /// This is the value after C:\Skyline DataMiner\ProtocolScripts\. + /// + /// + /// + public string DllImport { get; } + + /// + /// Gets the Local path for the reference. + /// + /// The Local path for the reference. + public string AssemblyPath { get; } + + /// + /// Defines if this reference should be located in the Files a 'Skyline.DataMiner.Files' package. + /// + public bool IsFilesPackage { get; } + + /// + /// Returns a string that represents the current object, including the values of the DllImport, AssemblyPath, + /// and IsFilesPackage properties. + /// + /// A string containing the DllImport, AssemblyPath, and IsFilesPackage values separated by vertical bars (|). + public override string ToString() + { + return $"{DllImport}|{AssemblyPath}|{IsFilesPackage}"; + } + } +} diff --git a/Assemblers.Common/NuGetHelper.cs b/Assemblers.Common/NuGetHelper.cs new file mode 100644 index 0000000..079479f --- /dev/null +++ b/Assemblers.Common/NuGetHelper.cs @@ -0,0 +1,42 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common +{ + using System.Collections.Generic; + using System.Linq; + + using Skyline.DataMiner.CICD.Common.NuGet; + + internal static class NuGetHelper + { + public static readonly IReadOnlyDictionary CustomNuGetPackages = new Dictionary + { + ["Skyline.DataMiner.Core.SRM"] = (@"SRM\SLSRMLibrary.dll", true), + ["Skyline.DataMiner.Core.SRM.Utils.Dijkstra"] = (@"SRM\SLDijkstraSearch.dll", true), + ["Skyline.DataMiner.Core.SRM.Utils.IAS"] = (@"SRM\Skyline.DataMiner.Core.SRM.Utils.IAS.dll", true) + }; + + public static bool IsDevPackNuGetPackage(string packageId) + { + return DevPackHelper.DevPackNuGetPackages.Contains(packageId) || packageId.StartsWith(DevPackHelper.FilesPrefix); + } + + public static bool SkipPackageDependencies(string packageId) + { + return CustomNuGetPackages.ContainsKey(packageId) || IsSolutionLibraryNuGetPackage(packageId, out _); + } + + public static bool IsSolutionLibraryNuGetPackage(string packageId, out string name) + { + // Solution 'devpacks' (like MediaOps) + const string prefix = "Skyline.DataMiner.Dev.Utils."; + + if (packageId.StartsWith(prefix)) + { + name = packageId.Substring(prefix.Length); + return true; + } + + name = null; + return false; + } + } +} \ No newline at end of file diff --git a/Assemblers.Common/NuGetPackageAssemblyData.cs b/Assemblers.Common/NuGetPackageAssemblyData.cs new file mode 100644 index 0000000..7b01a42 --- /dev/null +++ b/Assemblers.Common/NuGetPackageAssemblyData.cs @@ -0,0 +1,136 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common +{ + using System.Collections.Generic; + using System.Text; + + /// + /// Represents NuGet package assembly data. + /// + public class NuGetPackageAssemblyData + { + /// + /// Initializes a new instance of the class. + /// + public NuGetPackageAssemblyData() + { + DllImportNugetAssemblyReferences = new List(); + DllImportFrameworkAssemblyReferences = new HashSet(); + DllImportDirectoryReferences = new HashSet(); + DllImportDirectoryReferencesAssembly = new Dictionary(); + + ImplicitDllImportDirectoryReferences = new HashSet(); + + NugetAssemblies = new List(); + + ProcessedAssemblies = new HashSet(); + } + + /// + /// Gets all the NuGet package assemblies that need to be provided in the protocol package. + /// + /// The NuGet package assemblies that need to be provided in the protocol package. + public IList NugetAssemblies { get; } + + /// + /// Gets the NuGet package assemblies that need to be provided in the dllImportAttribute. + /// + /// The NuGet package assemblies that need to be provided in the dllImportAttribute. + public IList DllImportNugetAssemblyReferences { get; } + + /// + /// Gets the framework assemblies that need to be provided in the dllImport attribute. + /// + /// The framework assemblies that need to be provided in the dllImport attribute. + public ISet DllImportFrameworkAssemblyReferences { get; } + + /// + /// Gets the directory paths that need to be added to the dllImport attribute. + /// This is always windows style. + /// + /// The directory paths that need to be added to the dllImport attribute. + public ISet DllImportDirectoryReferences { get; } + + /// + /// Gets a map of a folder and an assembly that resides in that folder. + /// + /// A map of a folder and an assembly that resides in that folder. + /// For Automation scripts, providing a directory is not supported. Therefore, a DLL of that exists in the specified folder must be provided. This map stores the name of an assembly that exists in the specified folder. + public IDictionary DllImportDirectoryReferencesAssembly { get; } + + /// + /// Gets the directory paths that are implicitly already covered because an assembly from this folder has already been added to the dllImport attribute. + /// + /// The directory paths that are implicitly already covered because an assembly from this folder has already been added to the dllImport attribute. + public ISet ImplicitDllImportDirectoryReferences { get; } + + /// + /// Gets the names of all assemblies that have been processed. + /// + /// The names of all assemblies that have been processed. + public ISet ProcessedAssemblies { get; } + + /// + /// Returns a string that provides a detailed, multi-line summary of the current assembly and reference + /// collections managed by this instance. + /// + /// The returned string is intended for diagnostic or debugging purposes and includes all + /// relevant reference collections tracked by the instance. The format may change if the structure of the + /// collections changes. + /// A formatted string containing counts and lists of NuGet assemblies, DllImport references, directory + /// references, and processed assemblies. Each collection is displayed on a separate line for readability. + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + sb.AppendLine($"NuGetAssemblies: {NugetAssemblies.Count}"); + foreach (PackageAssemblyReference reference in NugetAssemblies) + { + sb.AppendLine($"\t{reference}"); + } + + sb.AppendLine(); + sb.AppendLine($"DllImportNugetAssemblyReferences: {DllImportNugetAssemblyReferences.Count}"); + foreach (PackageAssemblyReference reference in DllImportNugetAssemblyReferences) + { + sb.AppendLine($"\t{reference}"); + } + + sb.AppendLine(); + sb.AppendLine($"DllImportFrameworkAssemblyReferences: {DllImportFrameworkAssemblyReferences.Count}"); + foreach (string reference in DllImportFrameworkAssemblyReferences) + { + sb.AppendLine($"\t{reference}"); + } + + sb.AppendLine(); + sb.AppendLine($"DllImportDirectoryReferences: {DllImportDirectoryReferences.Count}"); + foreach (string reference in DllImportDirectoryReferences) + { + sb.AppendLine($"\t{reference}"); + } + + sb.AppendLine(); + sb.AppendLine($"DllImportDirectoryReferencesAssembly: {DllImportDirectoryReferencesAssembly.Count}"); + foreach (var pair in DllImportDirectoryReferencesAssembly) + { + sb.AppendLine($"\t{pair.Key}|{pair.Value}"); + } + + sb.AppendLine(); + sb.AppendLine($"ImplicitDllImportDirectoryReferences: {ImplicitDllImportDirectoryReferences.Count}"); + foreach (string reference in ImplicitDllImportDirectoryReferences) + { + sb.AppendLine($"\t{reference}"); + } + + sb.AppendLine(); + sb.AppendLine($"ProcessedAssemblies: {ProcessedAssemblies.Count}"); + foreach (string processedAssembly in ProcessedAssemblies) + { + sb.AppendLine($"\t{processedAssembly}"); + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Assemblers.Common/PackageAssemblyReference.cs b/Assemblers.Common/PackageAssemblyReference.cs new file mode 100644 index 0000000..de6ed73 --- /dev/null +++ b/Assemblers.Common/PackageAssemblyReference.cs @@ -0,0 +1,64 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common +{ + /// + /// Represents an assembly reference of a NuGet package. + /// + public class PackageAssemblyReference + { + /// + /// Initializes a new instance of the class. + /// + /// The import value for the QAction@dllImport attribute or Exe/Param element. + /// The assembly file path. + public PackageAssemblyReference(string dllImport, string assemblyPath) + { + DllImport = dllImport; + AssemblyPath = assemblyPath; + } + + /// + /// Initializes a new instance of the class. + /// + /// The import value for the QAction@dllImport attribute or Exe/Param element. + /// The assembly file path. + /// Determine if this is a package of the Files folder. + public PackageAssemblyReference(string dllImport, string assemblyPath, bool isFilesPackage) : this(dllImport, assemblyPath) + { + IsFilesPackage = isFilesPackage; + } + + /// + /// Gets the dllImport value. + /// + /// The dllImport value. + /// + /// + /// + /// This is the value after C:\Skyline DataMiner\ProtocolScripts\DllImport\. + /// + /// + /// + public string DllImport { get; } + + /// + /// Gets the Local path for the reference. + /// + /// The Local path for the reference. + public string AssemblyPath { get; } + + /// + /// Defines if this references is a 'Skyline.DataMiner.Files' package. + /// + public bool IsFilesPackage { get; } + + /// + /// Returns a string that represents the current object, including the values of DllImport, AssemblyPath, and + /// IsFilesPackage. + /// + /// A string containing the DllImport, AssemblyPath, and IsFilesPackage values separated by vertical bars ("|"). + public override string ToString() + { + return $"{DllImport}|{AssemblyPath}|{IsFilesPackage}"; + } + } +} diff --git a/Assemblers.Common/PackageReferenceProcessor.cs b/Assemblers.Common/PackageReferenceProcessor.cs new file mode 100644 index 0000000..3ac778d --- /dev/null +++ b/Assemblers.Common/PackageReferenceProcessor.cs @@ -0,0 +1,725 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + + using NuGet.Common; + using NuGet.Configuration; + using NuGet.Frameworks; + using NuGet.Packaging; + using NuGet.Packaging.Core; + using NuGet.Packaging.Signing; + using NuGet.Protocol; + using NuGet.Protocol.Core.Types; + using NuGet.Resolver; + using NuGet.Versioning; + + using Skyline.DataMiner.CICD.Common.NuGet; + using Skyline.DataMiner.CICD.FileSystem; + using Skyline.DataMiner.CICD.Loggers; + + /// + /// Determines all references required for a specific NuGet package. + /// + public class PackageReferenceProcessor + { + private readonly ILogCollector logCollector; + private readonly ISettings settings; + private readonly ILogger nuGetLogger; + private readonly ICollection repositories; + private readonly SourceRepository rootRepository; + + // V3 package path resolver + private readonly VersionFolderPathResolver versionFolderPathResolver; + private readonly FrameworkReducer frameworkReducer; + private readonly SourceRepositoryProvider sourceRepositoryProvider; + private readonly ClientPolicyContext clientPolicyContext; + + private readonly IFileSystem _fileSystem = FileSystem.Instance; + + /// + /// Initializes a new instance of the class. + /// + [Obsolete("Use the constructor with the directory path to be able to read out the nuget.config.")] + public PackageReferenceProcessor() : this(directoryForNuGetConfig: null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Directory path (to find the NuGet.config) + public PackageReferenceProcessor(string directoryForNuGetConfig) + { + nuGetLogger = NullLogger.Instance; + + // Start with the lowest settings. It will automatically look at the other NuGet.config files it can find on the default locations + settings = Settings.LoadDefaultSettings(root: directoryForNuGetConfig); + + clientPolicyContext = ClientPolicyContext.GetClientPolicy(settings, nuGetLogger); + + var provider = new PackageSourceProvider(settings); + sourceRepositoryProvider = new SourceRepositoryProvider(provider, Repository.Provider.GetCoreV3()); + + NuGetRootPath = SettingsUtility.GetGlobalPackagesFolder(settings); + + // Add global packages to be the first repository as it speeds up everything when reading from disk then via internet. + var repos = sourceRepositoryProvider.GetRepositories().ToList(); + rootRepository = new SourceRepository(new PackageSource(NuGetRootPath), Repository.Provider.GetCoreV3()); + repos.Insert(0, rootRepository); + repositories = repos; + + // https://docs.microsoft.com/en-us/nuget/consume-packages/managing-the-global-packages-and-cache-folders + versionFolderPathResolver = new VersionFolderPathResolver(NuGetRootPath); + + frameworkReducer = new FrameworkReducer(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The log collector. + /// is . + [Obsolete("Use the constructor with the solution directory path to be able to read out the nuget.config from the solution.")] + public PackageReferenceProcessor(ILogCollector logCollector) : this(logCollector, directoryForNuGetConfig: null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The log collector. + /// Directory path (to find the NuGet.config) + /// is . + public PackageReferenceProcessor(ILogCollector logCollector, string directoryForNuGetConfig) : this(directoryForNuGetConfig) + { + this.logCollector = logCollector ?? throw new ArgumentNullException(nameof(logCollector)); + + foreach (SourceRepository sourceRepository in repositories) + { + LogDebug($"Source: [{sourceRepository.PackageSource?.Name}] {sourceRepository.PackageSource?.Source}"); + } + + LogDebug($"NuGet Root Path: {NuGetRootPath}"); + } + + /// + /// Gets the NuGet root path. + /// + /// The NuGet root path. + public string NuGetRootPath { get; } + + /// + /// Processes the NuGet packages. + /// + /// The NuGet packages referenced by the project. + /// The target framework moniker. + /// The assembly info of the processed packages. + /// Cannot find the package with the identity. + public async Task ProcessAsync(IList projectPackages, string targetFrameworkMoniker) + { + return await ProcessAsync(projectPackages, targetFrameworkMoniker, new List()); + } + + /// + /// Processes the NuGet packages. + /// + /// The NuGet packages referenced by the project. + /// The target framework moniker. + /// Specifies the NuGet package IDs that are included by default. + /// The assembly info of the processed packages. + /// Cannot find the package with the identity. + public async Task ProcessAsync(IList projectPackages, string targetFrameworkMoniker, IReadOnlyCollection defaultIncludedFilesNuGetPackages) + { + var cancellationToken = CancellationToken.None; + + var provider = DefaultFrameworkNameProvider.Instance; + NuGetFramework nugetFramework = NuGetFramework.ParseFrameworkName(targetFrameworkMoniker, provider); + + using (var cacheContext = new SourceCacheContext()) + { + cacheContext.MaxAge = DateTimeOffset.UtcNow; + + var allDependenciesPackageInfos = new HashSet(PackageIdentityComparer.Default); + + var filteredProjectPackages = new List(); + foreach (var projectPackage in projectPackages) + { + // Verify whether the specified package version actually is available. + var packageIdentity = await GetPackageIdentityAsync(projectPackage, cacheContext, cancellationToken).ConfigureAwait(false); + + if (packageIdentity is null) + { + throw new InvalidOperationException($"Cannot find package {projectPackage.Id}, version {projectPackage.Version}."); + } + + if (DevPackHelper.DevPackNuGetPackages.Contains(packageIdentity.Id) || defaultIncludedFilesNuGetPackages.Contains(packageIdentity.Id)) + { + continue; + } + + filteredProjectPackages.Add(packageIdentity); + + await AddPackagesAndDependenciesAsync(packageIdentity, cacheContext, nugetFramework, nuGetLogger, repositories, allDependenciesPackageInfos, cancellationToken).ConfigureAwait(false); + } + + var unifiedPackages = GetResolvedPackages(sourceRepositoryProvider, nuGetLogger, filteredProjectPackages, allDependenciesPackageInfos); + + var references = await ProcessPackagesAsync(unifiedPackages, allDependenciesPackageInfos, nugetFramework, defaultIncludedFilesNuGetPackages); + + return references; + } + } + + /// + /// Determines which packages to install after resolving. + /// + /// Source repository provider. + /// The NuGet Logger + /// The NuGet packages. + /// All top level packages and their dependencies. + /// The resolved NuGet packages. + private static IEnumerable GetResolvedPackages(ISourceRepositoryProvider sourceRepositoryProvider, + ILogger logger, IList extensions, + HashSet allPackagesAndDependencies) + { + if (allPackagesAndDependencies.Count == 0) + { + // If no dependencies, then return the main package(s) at least. + return extensions; + } + + // Create a package resolver context (this is used to help figure out which actual package versions to install). + var resolverContext = new PackageResolverContext( + DependencyBehavior.Lowest, + extensions.Select(identity => identity.Id).Distinct(), + Enumerable.Empty(), + Enumerable.Empty(), + Enumerable.Empty(), + allPackagesAndDependencies, + sourceRepositoryProvider.GetRepositories().Select(s => s.PackageSource), + logger); + + var resolver = new PackageResolver(); + + // Work out the actual set of packages to install. + IEnumerable packagesToInstall = resolver.Resolve(resolverContext, CancellationToken.None) + .Select(identity => allPackagesAndDependencies.Single(info => PackageIdentityComparer.Default.Equals(info, identity))); + + return packagesToInstall; + } + + private async Task ProcessPackagesAsync(IEnumerable resolvedPackages, HashSet filteredAllPackages, NuGetFramework nugetFramework, IReadOnlyCollection defaultIncludedFilesNuGetPackages) + { + var nugetPackageAssemblies = new NuGetPackageAssemblyData(); + + if (resolvedPackages == null || !resolvedPackages.Any()) + { + return nugetPackageAssemblies; + } + + HashSet processedPackages = new HashSet(); + + // Resolved Packages are top level NuGet Packages + await ProcessResolvedPackagesAsync(resolvedPackages, nugetPackageAssemblies, processedPackages, nugetFramework, defaultIncludedFilesNuGetPackages); + + // Remaining Packages are Dependencies + await ProcessRemainingPackagesAsync(filteredAllPackages, nugetPackageAssemblies, processedPackages, nugetFramework); + + return nugetPackageAssemblies; + } + + /// + /// Processes the resolved/unified packages. + /// + /// The resolved packages. + /// The NuGet package assemblies. + /// The processed packages. + /// The NuGet framework. + /// The default NuGet "Skyline.DataMiner.Files." NuGet packages that are already referenced by default. + private async Task ProcessResolvedPackagesAsync(IEnumerable resolvedPackages, NuGetPackageAssemblyData nugetPackageAssemblies, ISet processedPackages, NuGetFramework nugetFramework, IReadOnlyCollection defaultIncludedFilesNuGetPackages) + { + // For all assemblies in the resolved package list we provide the reference to the assembly. + foreach (var resolvedPackage in resolvedPackages) + { + string packageKey = resolvedPackage.Id.ToLower() + "\\" + resolvedPackage.Version.ToString().ToLower(); + processedPackages.Add(packageKey); + + using (PackageReaderBase packageReader = GetPackageReader(resolvedPackage)) + { + if (packageReader.GetDevelopmentDependency() || (NuGetHelper.IsDevPackNuGetPackage(resolvedPackage.Id) && defaultIncludedFilesNuGetPackages.Contains(resolvedPackage.Id))) + { + continue; + } + + var libItems = packageReader.GetLibItems().ToList(); + + var nearestLibItems = frameworkReducer.GetNearest(nugetFramework, libItems.Select(x => x.TargetFramework)); + var filteredLibItems = (await ExtractPrimaryAssembliesAsync(libItems, nearestLibItems, packageReader)).ToList(); + + if (filteredLibItems.Any()) + { + // Lib items corresponding to the nuspec file. + // See: https://docs.microsoft.com/en-us/nuget/reference/nuspec#including-assembly-files + foreach (var filteredLibItem in filteredLibItems) + { + string assemblyName = _fileSystem.Path.GetFileName(filteredLibItem); + string dllImportDirectory = packageKey + "\\" + _fileSystem.Path.GetDirectoryName(filteredLibItem).Replace("/", "\\"); + + nugetPackageAssemblies.ProcessedAssemblies.Add(assemblyName); + + if (!resolvedPackage.Id.StartsWith(DevPackHelper.FilesPrefix)) + { + nugetPackageAssemblies.ImplicitDllImportDirectoryReferences.Add(dllImportDirectory); + } + + string fullPath = null; + string dllImportValue; + bool isFilePackage = false; + bool dontAddToPackageToInstall = false; + + if (resolvedPackage.Id.StartsWith(DevPackHelper.FilesPrefix)) + { + // Full path is not set as it should not be included. + dllImportValue = assemblyName; + isFilePackage = true; + dontAddToPackageToInstall = true; + } + else if (NuGetHelper.CustomNuGetPackages.TryGetValue(resolvedPackage.Id, out (string Path, bool InDllImportDirectory) info)) + { + dllImportValue = info.Path; + isFilePackage = !info.InDllImportDirectory; + dontAddToPackageToInstall = true; + } + else if (NuGetHelper.IsSolutionLibraryNuGetPackage(resolvedPackage.Id, out string name)) + { + // Use the name of the solution library as the folder name. Everything after 'Skyline.DataMiner.Dev.Utils.' is considered the name. + dllImportValue = $"SolutionLibraries\\{name}\\{assemblyName}"; + dontAddToPackageToInstall = true; + } + else + { + fullPath = _fileSystem.Path.GetFullPath(_fileSystem.Path.Combine(NuGetRootPath, resolvedPackage.Id.ToLower(), resolvedPackage.Version.ToString().ToLower(), filteredLibItem)); + dllImportValue = dllImportDirectory + "\\" + assemblyName; // fileInfo.Name + } + + var packageAssemblyReference = new PackageAssemblyReference(dllImportValue, fullPath, isFilePackage); + + // Needs to be added as a reference in the dllImport attribute/script references. + nugetPackageAssemblies.DllImportNugetAssemblyReferences.Add(packageAssemblyReference); + + if (dontAddToPackageToInstall) + { + // Should not be provided in the package to install. + continue; + } + + nugetPackageAssemblies.NugetAssemblies.Add(packageAssemblyReference); + } + } + + // Frameworkitems are items that are that are part of the targeted .NET framework. These are specified in the nuspec file. + // See: https://docs.microsoft.com/en-us/nuget/reference/nuspec#framework-assembly-references + var frameworkItems = packageReader.GetFrameworkItems().ToList(); + var nearestFramework = frameworkReducer.GetNearest(nugetFramework, frameworkItems.Select(x => x.TargetFramework)); + + var filteredFrameworkItems = frameworkItems + .Where(x => x.TargetFramework.Equals(nearestFramework)) + .SelectMany(x => x.Items) + .Select(x => x + ".dll") + .ToList(); + + nugetPackageAssemblies.ProcessedAssemblies.AddRange(filteredFrameworkItems); + nugetPackageAssemblies.DllImportFrameworkAssemblyReferences.AddRange(filteredFrameworkItems); + } + } + } + + private static async Task> ExtractPrimaryAssembliesAsync(List libItems, NuGetFramework nearestVersion, PackageReaderBase packageReader) + { + if (nearestVersion == null) + { + return Array.Empty(); + } + + var nearestLibItems = libItems.FirstOrDefault(x => x.TargetFramework.Equals(nearestVersion)); + + if (nearestLibItems?.Items == null || !nearestLibItems.Items.Any()) + { + return Array.Empty(); + } + + // Determine short folder name as follows because nearestVersion.GetShortFolderName(); could give a different result (e.g. net40) compared to what is used in the actual package (e.g. net4). + var firstItem = nearestLibItems.Items.First(); + var firstItemParts = firstItem.Split('/'); + + string shortFolderName = null; + + if (firstItemParts.Length > 1) + { + shortFolderName = firstItemParts[1]; + } + + if (shortFolderName == null) + { + return Array.Empty(); + } + + var filteredLibItems = new List(); + foreach (var libItem in nearestLibItems.Items) + { + if (!libItem.EndsWith(".dll")) + { + // Only process DLL files. + continue; + } + + string prefix = "lib/" + shortFolderName + '/'; + + // Safeguard. + if (!libItem.StartsWith(prefix)) + { + continue; + } + + string subPath = libItem.Substring(prefix.Length); + int subfolderNameIndex = subPath.IndexOf('/'); + + if (subfolderNameIndex != -1) + { + string subfolderName = subPath.Substring(0, subfolderNameIndex); + + // Verify whether the assembly is a satellite assembly. + // If it is a satellite assembly, do not include it. + // For more info about satellite assemblies, refer to https://learn.microsoft.com/en-us/dotnet/core/extensions/create-satellite-assemblies. + var satelliteAssemblies = await packageReader.GetSatelliteFilesAsync(subfolderName, CancellationToken.None); + var satelliteAssembliesList = satelliteAssemblies.ToList(); + + if (satelliteAssembliesList.ToList().Count == 0 || !satelliteAssembliesList.Contains(libItem)) + { + filteredLibItems.Add(libItem); + } + } + else + { + // Root item, cannot be a satellite assembly. + filteredLibItems.Add(libItem); + } + } + + return filteredLibItems; + } + + /// + /// Processes the remaining packages skipping the ones that are already processes. + /// + /// All packages. + /// The NuGet package assemblies. + /// The processed packages. + /// The NuGet framework. + private async Task ProcessRemainingPackagesAsync(HashSet allPackages, NuGetPackageAssemblyData nugetPackageAssemblies, ICollection processedPackages, NuGetFramework nugetFramework) + { + // For all assemblies that are not in the resolved package list, we provide the folder where the assembly can be found. + foreach (var packageToInstall in allPackages) + { + string packageKey = packageToInstall.Id.ToLower() + "\\" + packageToInstall.Version.ToString().ToLower(); + if (processedPackages.Contains(packageKey)) + { + continue; + } + + using (PackageReaderBase packageReader = GetPackageReader(packageToInstall)) + { + if (packageReader.GetDevelopmentDependency() || NuGetHelper.IsDevPackNuGetPackage(packageToInstall.Id)) + { + continue; + } + + var libItems = packageReader.GetLibItems().ToList(); + var nearestLibItems = frameworkReducer.GetNearest(nugetFramework, libItems.Select(x => x.TargetFramework)); + var filteredLibItems = (await ExtractPrimaryAssembliesAsync(libItems, nearestLibItems, packageReader)).ToList(); + + if (filteredLibItems.Any()) + { + var firstFilteredLibItem = filteredLibItems.First(); + string dllImportDirectory = packageKey + "\\" + _fileSystem.Path.GetDirectoryName(firstFilteredLibItem).Replace("/", "\\"); + + // Add the directory to be added to the dllImport attribute so the assembly can be found at runtime. + if (!nugetPackageAssemblies.ImplicitDllImportDirectoryReferences.Contains(dllImportDirectory)) + { + nugetPackageAssemblies.DllImportDirectoryReferences.Add(dllImportDirectory + "\\"); + + // For Automation scripts we cannot provide a path, so instead the first assembly is provided (as this will result in the path of that assembly to be used as a hint path as well). + nugetPackageAssemblies.DllImportDirectoryReferencesAssembly.Add(dllImportDirectory + "\\", dllImportDirectory + "\\" + _fileSystem.Path.GetFileName(firstFilteredLibItem)); + } + + // Add all assemblies so these get included in the dllImports folder to be loaded at runtime. + foreach (var filteredLibItem in filteredLibItems) + { + var fullPath = _fileSystem.Path.Combine(NuGetRootPath, packageToInstall.Id.ToLower(), packageToInstall.Version.ToString().ToLower(), filteredLibItem); + var dllImportValue = dllImportDirectory + "\\" + _fileSystem.Path.GetFileName(filteredLibItem); + + nugetPackageAssemblies.NugetAssemblies.Add(new PackageAssemblyReference(dllImportValue, fullPath)); + } + } + + var frameworkItems = packageReader.GetFrameworkItems().ToList(); + var nearestFramework = frameworkReducer.GetNearest(nugetFramework, frameworkItems.Select(x => x.TargetFramework)); + + var filteredFrameworkItems = frameworkItems + .Where(x => x.TargetFramework.Equals(nearestFramework)) + .SelectMany(x => x.Items) + .Select(x => x + ".dll"); + + nugetPackageAssemblies.ProcessedAssemblies.AddRange(filteredFrameworkItems); + } + } + } + + private PackageReaderBase GetPackageReader(PackageIdentity packageToInstall) + { + var installedPath = versionFolderPathResolver.GetInstallPath(packageToInstall.Id, packageToInstall.Version); + + PackageReaderBase packageReader = new PackageFolderReader(installedPath); + + return packageReader; + } + + /// + /// Retrieves the package. + /// + /// The package for which the identity should be retrieved. + /// The cache. + /// A cancellation token. + /// The package identity. + private async Task GetPackageIdentityAsync( + PackageIdentity nugetPackage, SourceCacheContext cache, CancellationToken cancelToken) + { + if (nugetPackage.HasVersion) + { + return nugetPackage; + } + + foreach (var sourceRepository in repositories) + { + if (cancelToken.IsCancellationRequested) + { + break; + } + + FindPackageByIdResource findPackageResource = await sourceRepository.GetResourceAsync(cancelToken).ConfigureAwait(false); + var allVersions = await findPackageResource.GetAllVersionsAsync(nugetPackage.Id, cache, nuGetLogger, cancelToken).ConfigureAwait(false); + + // No version; choose the latest, allow pre-release if configured. + NuGetVersion selected = allVersions.LastOrDefault(); + + if (selected == null) + { + // No versions found in this source. + continue; + } + + return new PackageIdentity(nugetPackage.Id, selected); + } + + return null; + } + + /// + /// Searches the package dependency graph for the chain of all packages to install. + /// + private async Task AddPackagesAndDependenciesAsync(PackageIdentity package, SourceCacheContext cacheContext, NuGetFramework framework, ILogger logger, ICollection repositories, ISet allPackages, CancellationToken cancellationToken) + { + if (allPackages.Contains(package)) + { + // Package was already processed. + return; + } + + await InstallPackageIfNotFound(package, cacheContext, cancellationToken); + + if (NuGetHelper.SkipPackageDependencies(package.Id)) + { + // Add it to the allPackages as the PackageResolver later on needs it (in case there would be multiple versions). + SourceRepository packageSourceRepository = null; + foreach (var sourceRepository in repositories) + { + FindPackageByIdResource findPackageResource = await sourceRepository.GetResourceAsync(cancellationToken).ConfigureAwait(false); + var exists = await findPackageResource.DoesPackageExistAsync(package.Id, package.Version, cacheContext, nuGetLogger, cancellationToken).ConfigureAwait(false); + + if (exists) + { + packageSourceRepository = sourceRepository; + break; + } + } + + if (packageSourceRepository == null) + { + logCollector?.ReportError($"PackageReferenceProcessor|InstallPackageIfNotFound|Unable to find package '{package.Id}' with version '{package.Version}"); + return; + } + + allPackages.Add(new SourcePackageDependencyInfo(package.Id, package.Version, Array.Empty(), true, + packageSourceRepository)); + return; + } + + foreach (var sourceRepository in repositories) + { + if (cancellationToken.IsCancellationRequested) + { + break; + } + + // Get the dependency info for the package. + var dependencyInfoResource = await sourceRepository.GetResourceAsync(cancellationToken).ConfigureAwait(false); + var dependencyInfo = await dependencyInfoResource.ResolvePackage( + package, + framework, + cacheContext, + logger, + cancellationToken).ConfigureAwait(false); + + if (dependencyInfo == null) + { + continue; + } + + var filteredDependencyInfo = dependencyInfo.Dependencies.Where(d => !NuGetHelper.IsDevPackNuGetPackage(d.Id)); + + var filteredDependencies = new SourcePackageDependencyInfo(dependencyInfo.Id, dependencyInfo.Version, filteredDependencyInfo, dependencyInfo.Listed, dependencyInfo.Source); + + allPackages.Add(filteredDependencies); + + // Process dependencies of dependency. + foreach (var dependency in dependencyInfo.Dependencies) + { + if (cancellationToken.IsCancellationRequested) + { + break; + } + + if (NuGetHelper.IsDevPackNuGetPackage(dependency.Id)) + { + continue; + } + + await AddPackagesAndDependenciesAsync( + new PackageIdentity(dependency.Id, dependency.VersionRange.MinVersion), + cacheContext, + framework, + logger, + repositories, + allPackages, + cancellationToken).ConfigureAwait(false); + } + + break; + } + } + + private async Task InstallPackageIfNotFound(PackageIdentity packageToInstall, SourceCacheContext cacheContext, CancellationToken cancelToken) + { + var existsResource = await rootRepository.GetResourceAsync(cancelToken); + if (existsResource.Exists(packageToInstall, nuGetLogger, cancelToken)) + { + // Package is already installed. + return; + } + + LogDebug($"InstallPackageIfNotFound|Installing package: {packageToInstall.Id} - {packageToInstall.Version}"); + + PackageSource packageSource = null; + // Figure out which packageSource is needed + foreach (var sourceRepository in repositories) + { + FindPackageByIdResource findPackageResource = await sourceRepository.GetResourceAsync(cancelToken).ConfigureAwait(false); + var exists = await findPackageResource.DoesPackageExistAsync(packageToInstall.Id, packageToInstall.Version, cacheContext, nuGetLogger, cancelToken).ConfigureAwait(false); + + if (exists) + { + packageSource = sourceRepository.PackageSource; + break; + } + } + + if (packageSource == null) + { + logCollector?.ReportError($"PackageReferenceProcessor|InstallPackageIfNotFound|Unable to find package '{packageToInstall.Id}' with version '{packageToInstall.Version}"); + return; + } + + var repository = Repository.Factory.GetCoreV3(packageSource); + var resource = await repository.GetResourceAsync(cancelToken); + + try + { + using (DownloadResourceResult downloadResourceResult = await resource.GetDownloadResourceResultAsync( + packageToInstall, + new PackageDownloadContext(cacheContext), + SettingsUtility.GetGlobalPackagesFolder(settings), + nuGetLogger, + cancelToken)) + { + // Add it to the global package folder + using (DownloadResourceResult result = await GlobalPackagesFolderUtility.AddPackageAsync( + packageSource.Source, + packageToInstall, + downloadResourceResult.PackageStream, + NuGetRootPath, + Guid.Empty, + clientPolicyContext, + nuGetLogger, + CancellationToken.None)) + { + LogDebug($"InstallPackageIfNotFound|Finished installing package {packageToInstall.Id} - {packageToInstall.Version} with status: " + result?.Status); + } + } + } + catch + { + LogDebug("Retrying to add package without caching"); + string tempDir = FileSystem.Instance.Directory.CreateTemporaryDirectory(); + + try + { + // Retrying without cache + using (DownloadResourceResult downloadResourceResult = await resource.GetDownloadResourceResultAsync( + packageToInstall, + new PackageDownloadContext(cacheContext, tempDir, true), + SettingsUtility.GetGlobalPackagesFolder(settings), + nuGetLogger, + cancelToken)) + { + // Add it to the global package folder + using (DownloadResourceResult result = await GlobalPackagesFolderUtility.AddPackageAsync( + packageSource.Source, + packageToInstall, + downloadResourceResult.PackageStream, + NuGetRootPath, + Guid.Empty, + clientPolicyContext, + nuGetLogger, + CancellationToken.None)) + { + LogDebug($"InstallPackageIfNotFound|Finished installing package {packageToInstall.Id} - {packageToInstall.Version} with status: " + result?.Status); + } + } + } + finally + { + FileSystem.Instance.Directory.DeleteDirectory(tempDir); + } + } + } + + private void LogDebug(string message) + { + logCollector?.ReportDebug($"PackageReferenceProcessor|{message}"); + } + } +} \ No newline at end of file diff --git a/Assemblers.CommonTests/Assemblers.CommonTests.csproj b/Assemblers.CommonTests/Assemblers.CommonTests.csproj new file mode 100644 index 0000000..2369db3 --- /dev/null +++ b/Assemblers.CommonTests/Assemblers.CommonTests.csproj @@ -0,0 +1,21 @@ + + + + net48;net8.0 + false + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/Assemblers.CommonTests/CSharpCodeCombinerTests.cs b/Assemblers.CommonTests/CSharpCodeCombinerTests.cs new file mode 100644 index 0000000..0912a7e --- /dev/null +++ b/Assemblers.CommonTests/CSharpCodeCombinerTests.cs @@ -0,0 +1,209 @@ +namespace Assemblers.CommonTests +{ + using System; + using System.Collections.Generic; + using System.Text; + + using FluentAssertions; + + using Microsoft.VisualStudio.TestTools.UnitTesting; + + using Skyline.DataMiner.CICD.Assemblers.Common; + using Skyline.DataMiner.CICD.Parsers.Common.VisualStudio.Projects; + + [TestClass] + public class CSharpCodeCombinerTests + { + [TestMethod] + public void CombineFiles_Null_ExpectedArgumentNullException() + { + // Arrange + + // Act + Action act = () => CSharpCodeCombiner.CombineFiles(null); + + // Assert + act.Should().ThrowExactly(); + } + + [TestMethod] + public void CombineFiles_EmptyList() + { + // Arrange + + // Act + var result = CSharpCodeCombiner.CombineFiles(new List(0)); + + // Assert + result.Should().BeEmpty(); + } + + [TestMethod] + public void CombineFiles_SingleFile() + { + // Arrange + const string content = "ABC"; + List files = new List + { + new ProjectFile("MyProjectFile", content) + }; + + // Act + var result = CSharpCodeCombiner.CombineFiles(files); + + // Assert + result.Should().BeEquivalentTo(content); + } + + [TestMethod] + public void CombineFiles_MultipleFiles_RandomText() + { + // Arrange + const string contentFile1 = "ABC"; + const string contentFile2 = "DEF"; + List files = new List + { + new ProjectFile("MyProjectFile1", contentFile1), + new ProjectFile("MyProjectFile2", contentFile2) + }; + + StringBuilder sb = new StringBuilder(); + sb.AppendLine() // usings but there aren't any + .AppendLine("//---------------------------------") + .AppendLine("// MyProjectFile1") + .AppendLine("//---------------------------------") + .AppendLine(contentFile1) + .AppendLine("//---------------------------------") + .AppendLine("// MyProjectFile2") + .AppendLine("//---------------------------------") + .Append(contentFile2); + string expectedResult = sb.ToString(); + + // Act + var result = CSharpCodeCombiner.CombineFiles(files); + + // Assert + result.Should().BeEquivalentTo(expectedResult); + } + + [TestMethod] + public void CombineFiles_MultipleFiles_ActualCSharp_WithoutNamespaces() + { + // Arrange + const string contentFile1 = @"using System; + +public static class MyExtensions +{ + public static string MyMethod() + { + return String.Empty; + } +} +"; + const string contentFile2 = @"using System; +using System.IO; + +public static class MyOtherExtensions +{ + public static bool MyOtherMethod(string path) + { + return Path.HasExtension(path); + } +}"; + List files = new List + { + new ProjectFile("MyProjectFile1", contentFile1), + new ProjectFile("MyProjectFile2", contentFile2) + }; + + const string expectedContentFile1 = @"public static class MyExtensions +{ + public static string MyMethod() + { + return String.Empty; + } +} +"; + const string expectedContentFile2 = @"public static class MyOtherExtensions +{ + public static bool MyOtherMethod(string path) + { + return Path.HasExtension(path); + } +}"; + StringBuilder sb = new StringBuilder(); + sb.AppendLine("using System;" + Environment.NewLine + "using System.IO;") + .AppendLine() + .AppendLine("//---------------------------------") + .AppendLine("// MyProjectFile1") + .AppendLine("//---------------------------------") + .AppendLine() + .AppendLine(expectedContentFile1) + .AppendLine("//---------------------------------") + .AppendLine("// MyProjectFile2") + .AppendLine("//---------------------------------") + .AppendLine() + .Append(expectedContentFile2); + string expectedResult = sb.ToString(); + + // Act + var result = CSharpCodeCombiner.CombineFiles(files); + + // Assert + result.Should().BeEquivalentTo(expectedResult); + } + + [TestMethod] + public void CombineFiles_MultipleFiles_ActualCSharp_WithNamespaces() + { + // Arrange + const string contentFile1 = @"namespace Skyline.Protocol +{ + using System; + + public static class MyExtensions + { + public static string MyMethod() + { + return String.Empty; + } + } +}"; + const string contentFile2 = @"namespace Skyline.Protocol.Files +{ + using System.IO; + + public static class MyOtherExtensions + { + public static bool MyOtherMethod(string path) + { + return Path.HasExtension(path); + } + } +}"; + List files = new List + { + new ProjectFile("MyProjectFile1", contentFile1), + new ProjectFile("MyProjectFile2", contentFile2) + }; + + StringBuilder sb = new StringBuilder(); + sb.AppendLine() + .AppendLine("//---------------------------------") + .AppendLine("// MyProjectFile1") + .AppendLine("//---------------------------------") + .AppendLine(contentFile1) + .AppendLine("//---------------------------------") + .AppendLine("// MyProjectFile2") + .AppendLine("//---------------------------------") + .Append(contentFile2); + string expectedResult = sb.ToString(); + + // Act + var result = CSharpCodeCombiner.CombineFiles(files); + + // Assert + result.Should().BeEquivalentTo(expectedResult); + } + } +} \ No newline at end of file diff --git a/Assemblers.CommonTests/PackageReferenceProcessorTests.cs b/Assemblers.CommonTests/PackageReferenceProcessorTests.cs new file mode 100644 index 0000000..6afe61e --- /dev/null +++ b/Assemblers.CommonTests/PackageReferenceProcessorTests.cs @@ -0,0 +1,440 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common.Tests +{ + using System.Collections.Generic; + using System.Threading.Tasks; + + using FluentAssertions; + using FluentAssertions.Equivalency; + + using Microsoft.VisualStudio.TestTools.UnitTesting; + + using NuGet.Packaging.Core; + using NuGet.Versioning; + + using Skyline.DataMiner.CICD.Common.NuGet; + + [TestClass] + public class PackageReferenceProcessorTests + { + [TestMethod] + public async Task ProcessAsyncTest_FilesNuGet_OnlyReturnsAssemblyName_Protocol() + { + var packageReferenceProcessor = new PackageReferenceProcessor(directoryForNuGetConfig: null); + + IList projectPackages = new List + { + new PackageIdentity("Skyline.DataMiner.Dev.Protocol", new NuGetVersion("10.3.4.1")), + new PackageIdentity("Skyline.DataMiner.Files.SLManagedAutomation", new NuGetVersion("10.3.4.1")), + new PackageIdentity("Skyline.DataMiner.Files.SLMediationSnippets", new NuGetVersion("10.3.4.1")) + }; + + string targetFrameworkMoniker = ".NETFramework,Version=v4.6.2"; + + var result = await packageReferenceProcessor.ProcessAsync(projectPackages, targetFrameworkMoniker, DevPackHelper.ProtocolDevPackNuGetDependenciesIncludingTransitive); + + Assert.IsNotNull(result); + Assert.IsEmpty(result.ImplicitDllImportDirectoryReferences); + Assert.IsEmpty(result.DllImportFrameworkAssemblyReferences); + Assert.IsEmpty(result.DllImportDirectoryReferences); + Assert.IsEmpty(result.DllImportDirectoryReferencesAssembly); + + Assert.IsEmpty(result.NugetAssemblies); // Assembly must not be included in package, only needs to be added to dllImport. + Assert.HasCount(2, result.DllImportNugetAssemblyReferences); + + Assert.HasCount(2, result.ProcessedAssemblies); + } + + [TestMethod] + public async Task ProcessAsyncTest_FilesNuGet_OnlyReturnsAssemblyName_Automation() + { + var packageReferenceProcessor = new PackageReferenceProcessor(directoryForNuGetConfig: null); + + IList projectPackages = new List + { + new PackageIdentity("Skyline.DataMiner.Dev.Automation", new NuGetVersion("10.3.4.1")), + new PackageIdentity("Skyline.DataMiner.Files.SLManagedScripting", new NuGetVersion("10.3.4.1")), + new PackageIdentity("Skyline.DataMiner.Files.SLMediationSnippets", new NuGetVersion("10.3.4.1")) + }; + + string targetFrameworkMoniker = ".NETFramework,Version=v4.6.2"; + + var result = await packageReferenceProcessor.ProcessAsync(projectPackages, targetFrameworkMoniker, DevPackHelper.AutomationDevPackNuGetDependenciesIncludingTransitive); + + Assert.IsNotNull(result); + Assert.IsEmpty(result.ImplicitDllImportDirectoryReferences); + Assert.IsEmpty(result.DllImportFrameworkAssemblyReferences); + Assert.IsEmpty(result.DllImportDirectoryReferences); + Assert.IsEmpty(result.DllImportDirectoryReferencesAssembly); + + Assert.IsEmpty(result.NugetAssemblies); // Assembly must not be included in package, only needs to be added to dllImport. + Assert.HasCount(2, result.DllImportNugetAssemblyReferences); + + Assert.HasCount(2, result.ProcessedAssemblies); + } + + [TestMethod] + public async Task ProcessAsyncTest_CommonScenario() + { + // Arrange + var packageReferenceProcessor = new PackageReferenceProcessor(directoryForNuGetConfig: null); + + IList projectPackages = new List + { + new PackageIdentity("Skyline.DataMiner.Dev.Automation", new NuGetVersion("10.3.4.1")), + new PackageIdentity("Newtonsoft.Json", new NuGetVersion("13.0.3")), + new PackageIdentity("Skyline.DataMiner.Utils.ExportImport", new NuGetVersion("1.0.0")), + }; + + const string targetFrameworkMoniker = ".NETFramework,Version=v4.6.2"; + + const string pathJson = "newtonsoft.json\\13.0.3\\lib\\net45"; + const string pathExportImport = "skyline.dataminer.utils.exportimport\\1.0.0\\lib\\netstandard2.0"; + var expectedResult = new NuGetPackageAssemblyData + { + ImplicitDllImportDirectoryReferences = + { + pathJson, + pathExportImport, + }, + DllImportNugetAssemblyReferences = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + new PackageAssemblyReference(pathExportImport + "\\Skyline.DataMiner.Utils.ExportImport.dll", null, false), + }, + NugetAssemblies = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + new PackageAssemblyReference(pathExportImport + "\\Skyline.DataMiner.Utils.ExportImport.dll", null, false), + }, + ProcessedAssemblies = + { + "Newtonsoft.Json.dll", + "Skyline.DataMiner.Utils.ExportImport.dll", + } + }; + + // Act + var result = await packageReferenceProcessor.ProcessAsync(projectPackages, targetFrameworkMoniker); + + // Assert + result.Should().BeEquivalentTo(expectedResult, ExcludeAssemblyPath); + } + + [TestMethod] + public async Task ProcessAsyncTest_UseOfOtherDevPackFile() + { + // Arrange + var packageReferenceProcessor = new PackageReferenceProcessor(directoryForNuGetConfig: null); + + IList projectPackages = new List + { + new PackageIdentity("Skyline.DataMiner.Dev.Automation", new NuGetVersion("10.3.4.1")), + new PackageIdentity("Skyline.DataMiner.Files.SLManagedScripting", new NuGetVersion("10.3.4.1")), + new PackageIdentity("Newtonsoft.Json", new NuGetVersion("13.0.3")), + new PackageIdentity("Skyline.DataMiner.Utils.ExportImport", new NuGetVersion("1.0.0")), + }; + + const string targetFrameworkMoniker = ".NETFramework,Version=v4.6.2"; + + const string pathJson = "newtonsoft.json\\13.0.3\\lib\\net45"; + const string pathExportImport = "skyline.dataminer.utils.exportimport\\1.0.0\\lib\\netstandard2.0"; + var expectedResult = new NuGetPackageAssemblyData + { + ImplicitDllImportDirectoryReferences = + { + pathJson, + pathExportImport, + }, + DllImportNugetAssemblyReferences = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + new PackageAssemblyReference(pathExportImport + "\\Skyline.DataMiner.Utils.ExportImport.dll", null, false), + + // Is a files package + new PackageAssemblyReference("SLManagedScripting.dll", null, true), + }, + NugetAssemblies = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + new PackageAssemblyReference(pathExportImport + "\\Skyline.DataMiner.Utils.ExportImport.dll", null, false), + }, + ProcessedAssemblies = + { + "Newtonsoft.Json.dll", + "Skyline.DataMiner.Utils.ExportImport.dll", + + "SLManagedScripting.dll" + } + }; + + // Act + var result = await packageReferenceProcessor.ProcessAsync(projectPackages, targetFrameworkMoniker); + + // Assert + result.Should().BeEquivalentTo(expectedResult, ExcludeAssemblyPath); + } + + [TestMethod] + public async Task ProcessAsyncTest_UnitTestScenario() + { + // Arrange + var packageReferenceProcessor = new PackageReferenceProcessor(directoryForNuGetConfig: null); + + IList projectPackages = new List + { + new PackageIdentity("Skyline.DataMiner.Dev.Automation", new NuGetVersion("10.3.4.1")), + new PackageIdentity("Newtonsoft.Json", new NuGetVersion("13.0.3")), + new PackageIdentity("Skyline.DataMiner.Utils.ExportImport", new NuGetVersion("1.0.0")), + new PackageIdentity("Moq", new NuGetVersion("4.18.4")) + }; + + const string targetFrameworkMoniker = ".NETFramework,Version=v4.6.2"; + + const string pathJson = "newtonsoft.json\\13.0.3\\lib\\net45"; + const string pathExportImport = "skyline.dataminer.utils.exportimport\\1.0.0\\lib\\netstandard2.0"; + const string pathMoq = "moq\\4.18.4\\lib\\net462"; + const string pathCastleCore = "castle.core\\5.1.1\\lib\\net462"; + const string pathThreading = "system.threading.tasks.extensions\\4.5.4\\lib\\net461"; + const string pathCompiler = "system.runtime.compilerservices.unsafe\\4.5.3\\lib\\net461"; + var expectedResult = new NuGetPackageAssemblyData + { + ImplicitDllImportDirectoryReferences = + { + pathJson, + pathExportImport, + pathMoq, + pathCastleCore, + pathThreading, + pathCompiler, + }, + DllImportNugetAssemblyReferences = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + new PackageAssemblyReference(pathExportImport + "\\Skyline.DataMiner.Utils.ExportImport.dll", null, false), + new PackageAssemblyReference(pathMoq + "\\Moq.dll", null, false), + + // Dependencies from Moq + new PackageAssemblyReference(pathCastleCore + "\\Castle.Core.dll", null, false), + new PackageAssemblyReference(pathThreading + "\\System.Threading.Tasks.Extensions.dll", null, false), + + // Dependencies from System.Threading.Tasks.Extensions + new PackageAssemblyReference(pathCompiler + "\\System.Runtime.CompilerServices.Unsafe.dll", null, false), + }, + NugetAssemblies = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + new PackageAssemblyReference(pathExportImport + "\\Skyline.DataMiner.Utils.ExportImport.dll", null, false), + new PackageAssemblyReference(pathMoq + "\\Moq.dll", null, false), + + // Dependencies from Moq + new PackageAssemblyReference(pathCastleCore + "\\Castle.Core.dll", null, false), + new PackageAssemblyReference(pathThreading + "\\System.Threading.Tasks.Extensions.dll", null, false), + + // Dependencies from System.Threading.Tasks.Extensions + new PackageAssemblyReference(pathCompiler + "\\System.Runtime.CompilerServices.Unsafe.dll", null, false), + }, + ProcessedAssemblies = + { + "Newtonsoft.Json.dll", + "Skyline.DataMiner.Utils.ExportImport.dll", + "Moq.dll", + + // Dependencies from Moq + "Castle.Core.dll", + "System.Threading.Tasks.Extensions.dll", + + // Dependencies from System.Threading.Tasks.Extensions + "System.Runtime.CompilerServices.Unsafe.dll", + + "System.Configuration.dll", + "mscorlib.dll", + }, + DllImportFrameworkAssemblyReferences = + { + "System.Configuration.dll", + "mscorlib.dll", + }, + }; + + // Act + var result = await packageReferenceProcessor.ProcessAsync(projectPackages, targetFrameworkMoniker); + + // Assert + result.Should().BeEquivalentTo(expectedResult, ExcludeAssemblyPath); + } + + [TestMethod] + public async Task ProcessAsyncTest_UnitTestScenario_Yle_Library() + { + // Arrange + var packageReferenceProcessor = new PackageReferenceProcessor(directoryForNuGetConfig: null); + + IList projectPackages = new List + { + new PackageIdentity("Skyline.DataMiner.Dev.Automation", new NuGetVersion("10.3.5")), + new PackageIdentity("Newtonsoft.Json", new NuGetVersion("13.0.3")), + new PackageIdentity("NPOI", new NuGetVersion("2.4.1")), + new PackageIdentity("Skyline.DataMiner.ConnectorAPI.EVS.IPD-VIA", new NuGetVersion("1.0.0.4-Test1")), + new PackageIdentity("Skyline.DataMiner.ConnectorAPI.YLE.OrderManager", new NuGetVersion("1.0.0.2-Test1")), + new PackageIdentity("Skyline.DataMiner.Utils.InteractiveAutomationScriptToolkit", new NuGetVersion("6.1.0")), + new PackageIdentity("Skyline.DataMiner.Utils.YLE.Integrations", new NuGetVersion("1.0.1.6-Test1")), + }; + + const string targetFrameworkMoniker = ".NETFramework,Version=v4.7.2"; + + const string pathJson = "newtonsoft.json\\13.0.3\\lib\\net45"; + const string pathJsonOld = "newtonsoft.json\\13.0.2\\lib\\net45"; + const string pathSharpZipLib = "sharpziplib\\1.0.0\\lib\\net45"; + const string pathNpoi = "npoi\\2.4.1\\lib\\net45"; + const string pathCoreDmsCommonNew = "skyline.dataminer.core.dataminersystem.common\\1.1.0.5\\lib\\net462"; + const string pathCoreDmsCommonOld = "skyline.dataminer.core.dataminersystem.common\\1.0.0.2\\lib\\net462"; + const string pathCoreInterApp = "skyline.dataminer.core.interappcalls.common\\1.0.0.2\\lib\\net462"; + const string pathEvs = "skyline.dataminer.connectorapi.evs.ipd-via\\1.0.0.4-test1\\lib\\net472"; + const string pathOrder = "skyline.dataminer.connectorapi.yle.ordermanager\\1.0.0.2-test1\\lib\\net472"; + const string pathToolkit = "skyline.dataminer.utils.interactiveautomationscripttoolkit\\6.1.0\\lib\\net462"; + const string pathIntegrations = "skyline.dataminer.utils.yle.integrations\\1.0.1.6-test1\\lib\\net472"; + var expectedResult = new NuGetPackageAssemblyData + { + ImplicitDllImportDirectoryReferences = + { + pathJson, + pathSharpZipLib, + pathNpoi, + pathCoreDmsCommonNew, + pathCoreInterApp, + pathEvs, + pathOrder, + pathToolkit, + pathIntegrations + }, + DllImportNugetAssemblyReferences = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + new PackageAssemblyReference(pathSharpZipLib + "\\ICSharpCode.SharpZipLib.dll", null, false), + new PackageAssemblyReference(pathNpoi + "\\NPOI.dll", null, false), + new PackageAssemblyReference(pathNpoi + "\\NPOI.OOXML.dll", null, false), + new PackageAssemblyReference(pathNpoi + "\\NPOI.OpenXml4Net.dll", null, false), + new PackageAssemblyReference(pathNpoi + "\\NPOI.OpenXmlFormats.dll", null, false), + new PackageAssemblyReference(pathCoreDmsCommonNew + "\\Skyline.DataMiner.Core.DataMinerSystem.Common.dll", null, false), + new PackageAssemblyReference(pathCoreInterApp + "\\Skyline.DataMiner.Core.InterAppCalls.Common.dll", null, false), + new PackageAssemblyReference(pathEvs + "\\Skyline.DataMiner.ConnectorAPI.EVS.IPD-VIA.dll", null, false), + new PackageAssemblyReference(pathOrder + "\\Skyline.DataMiner.ConnectorAPI.YLE.OrderManager.dll", null, false), + new PackageAssemblyReference(pathToolkit + "\\Skyline.DataMiner.Utils.InteractiveAutomationScriptToolkit.dll", null, false), + new PackageAssemblyReference(pathIntegrations + "\\Skyline.DataMiner.Utils.YLE.Integrations.dll", null, false), + }, + NugetAssemblies = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + new PackageAssemblyReference(pathSharpZipLib + "\\ICSharpCode.SharpZipLib.dll", null, false), + new PackageAssemblyReference(pathNpoi + "\\NPOI.dll", null, false), + new PackageAssemblyReference(pathNpoi + "\\NPOI.OOXML.dll", null, false), + new PackageAssemblyReference(pathNpoi + "\\NPOI.OpenXml4Net.dll", null, false), + new PackageAssemblyReference(pathNpoi + "\\NPOI.OpenXmlFormats.dll", null, false), + new PackageAssemblyReference(pathCoreDmsCommonNew + "\\Skyline.DataMiner.Core.DataMinerSystem.Common.dll", null, false), + new PackageAssemblyReference(pathCoreInterApp + "\\Skyline.DataMiner.Core.InterAppCalls.Common.dll", null, false), + new PackageAssemblyReference(pathEvs + "\\Skyline.DataMiner.ConnectorAPI.EVS.IPD-VIA.dll", null, false), + new PackageAssemblyReference(pathOrder + "\\Skyline.DataMiner.ConnectorAPI.YLE.OrderManager.dll", null, false), + new PackageAssemblyReference(pathToolkit + "\\Skyline.DataMiner.Utils.InteractiveAutomationScriptToolkit.dll", null, false), + new PackageAssemblyReference(pathIntegrations + "\\Skyline.DataMiner.Utils.YLE.Integrations.dll", null, false), + new PackageAssemblyReference(pathCoreDmsCommonOld + "\\Skyline.DataMiner.Core.DataMinerSystem.Common.dll", null, false), + new PackageAssemblyReference(pathJsonOld + "\\Newtonsoft.Json.dll", null, false), + }, + ProcessedAssemblies = + { + "Newtonsoft.Json.dll", + "ICSharpCode.SharpZipLib.dll", + + "NPOI.dll", + + // Dependencies of NPOI + "NPOI.OOXML.dll", + "NPOI.OpenXml4Net.dll", + "NPOI.OpenXmlFormats.dll", + + "Skyline.DataMiner.Core.DataMinerSystem.Common.dll", + "Skyline.DataMiner.Core.InterAppCalls.Common.dll", + "Skyline.DataMiner.ConnectorAPI.EVS.IPD-VIA.dll", + "Skyline.DataMiner.ConnectorAPI.YLE.OrderManager.dll", + "Skyline.DataMiner.Utils.InteractiveAutomationScriptToolkit.dll", + "Skyline.DataMiner.Utils.YLE.Integrations.dll", + }, + DllImportDirectoryReferencesAssembly = + { + [pathCoreDmsCommonOld + "\\"] = pathCoreDmsCommonOld + "\\Skyline.DataMiner.Core.DataMinerSystem.Common.dll", + [pathJsonOld + "\\"] = pathJsonOld + "\\Newtonsoft.Json.dll", + }, + DllImportDirectoryReferences = + { + pathCoreDmsCommonOld + "\\", + pathJsonOld + "\\", + } + }; + + // Act + var result = await packageReferenceProcessor.ProcessAsync(projectPackages, targetFrameworkMoniker); + + // Assert + result.Should().BeEquivalentTo(expectedResult, ExcludeAssemblyPath); + } + + [TestMethod] + public async Task ProcessAsyncTest_SolutionLibraries() + { + // Arrange + var packageReferenceProcessor = new PackageReferenceProcessor(directoryForNuGetConfig: null); + + IList projectPackages = new List + { + new PackageIdentity("Skyline.DataMiner.Dev.Automation", new NuGetVersion("10.3.5")), + new PackageIdentity("Newtonsoft.Json", new NuGetVersion("13.0.3")), + new PackageIdentity("Skyline.DataMiner.Dev.Utils.ModSolutionLib", new NuGetVersion("1.0.0")), + }; + + const string targetFrameworkMoniker = ".NETFramework,Version=v4.8"; + + const string pathJson = "newtonsoft.json\\13.0.3\\lib\\net45"; + const string pathSolutionLib = "skyline.dataminer.dev.utils.modsolutionlib\\1.0.0\\lib\\netstandard2.0"; + var expectedResult = new NuGetPackageAssemblyData + { + ImplicitDllImportDirectoryReferences = + { + pathJson, + pathSolutionLib, + }, + DllImportNugetAssemblyReferences = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + new PackageAssemblyReference("SolutionLibraries\\ModSolutionLib\\Skyline.DataMiner.Dev.Utils.ModSolutionLib.dll", null, false), + }, + NugetAssemblies = + { + new PackageAssemblyReference(pathJson + "\\Newtonsoft.Json.dll", null, false), + }, + ProcessedAssemblies = + { + "Newtonsoft.Json.dll", + + "Skyline.DataMiner.Dev.Utils.ModSolutionLib.dll", + }, + DllImportDirectoryReferencesAssembly = + { + }, + DllImportDirectoryReferences = + { + } + }; + + // Act + var result = await packageReferenceProcessor.ProcessAsync(projectPackages, targetFrameworkMoniker); + + // Assert + result.Should().BeEquivalentTo(expectedResult, ExcludeAssemblyPath); + } + + private static EquivalencyAssertionOptions ExcludeAssemblyPath(EquivalencyAssertionOptions arg) + { + arg.Excluding(x => x.Path.EndsWith("AssemblyPath")); + return arg; + } + } +} \ No newline at end of file diff --git a/Assemblers.Protocol/AsciiTable.cs b/Assemblers.Protocol/AsciiTable.cs new file mode 100644 index 0000000..d968052 --- /dev/null +++ b/Assemblers.Protocol/AsciiTable.cs @@ -0,0 +1,80 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Protocol +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + internal class AsciiTable + { + private readonly List rows = new List(); + const int spacing = 4; + + public void AddRow(params string[] fields) + { + rows.Add(fields); + } + + private IDictionary CalculateColumnOffsets() + { + var result = new Dictionary(); + + int offset = 0; + result.Add(0, offset); + + if (rows.Count > 0) + { + int numColumns = rows.Max(r => r.Length); + + for (int col = 0; col < numColumns; col++) + { + int maxLength = 0; + + foreach (var row in rows) + { + if (row.Length > col && row[col] != null) + { + maxLength = Math.Max(row[col].Length, maxLength); + } + } + + offset += maxLength + spacing; + + result.Add(col + 1, offset); + } + } + + return result; + } + + public override string ToString() + { + var columnOffsets = CalculateColumnOffsets(); + + StringBuilder sb = new StringBuilder(); + + foreach (var row in rows) + { + for (int col = 0; col < row.Length; col++) + { + string field = row[col] ?? ""; + sb.Append(field); + + if (col != row.Length - 1) + { + int offset = columnOffsets[col]; + int nextOffset = columnOffsets[col + 1]; + int width = nextOffset - offset; + + int spaces = width - field.Length; + sb.Append(new String(' ', spaces)); + } + } + + sb.AppendLine(); + } + + return sb.ToString(); + } + } +} diff --git a/Assemblers.Protocol/Assemblers.Protocol.csproj b/Assemblers.Protocol/Assemblers.Protocol.csproj new file mode 100644 index 0000000..daa1c0c --- /dev/null +++ b/Assemblers.Protocol/Assemblers.Protocol.csproj @@ -0,0 +1,40 @@ + + + netstandard2.0 + Skyline.DataMiner.CICD.Assemblers.Protocol + Skyline.DataMiner.CICD.Assemblers.Protocol + True + True + SkylineCommunications + Skyline Communications + LICENSE.txt + True + icon.png + https://skyline.be/ + Skyline;DataMiner;CICD + Library providing methods for converting Visual Studio DIS connector solutions to individual DataMiner connector artifacts (e.g. XML, DLLs,...). + README.md + https://github.com/SkylineCommunications/Skyline.DataMiner.CICD.Packages + git + 0.0.1-local + + + + + + + + + + + + + + + + + + + + + diff --git a/Assemblers.Protocol/AssemblyFilter.cs b/Assemblers.Protocol/AssemblyFilter.cs new file mode 100644 index 0000000..cdb761d --- /dev/null +++ b/Assemblers.Protocol/AssemblyFilter.cs @@ -0,0 +1,204 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Protocol +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using System.Threading.Tasks; + + using NuGet.Packaging.Core; + + using Skyline.DataMiner.CICD.Assemblers.Common; + using Skyline.DataMiner.CICD.FileSystem; + + /// + /// Provides functionality to filter assemblies based on target framework, package references, and build result items. + /// + public static class AssemblyFilter + { + /// + /// Filters assemblies based on the specified criteria. + /// + /// The target framework moniker. + /// The package reference processor. + /// The build result items. + /// A set of DLL imports. + /// A list of package identities. + /// The filtered NuGet package assembly data. + public static async Task FilterAsync(string targetFrameworkMoniker, PackageReferenceProcessor packageReferenceProcessor, BuildResultItems buildResultItems, HashSet dllImports, IList packageIdentities) + { + var nugetAssemblyData = await packageReferenceProcessor.ProcessAsync(packageIdentities, targetFrameworkMoniker, + Skyline.DataMiner.CICD.Common.NuGet.DevPackHelper.ProtocolDevPackNuGetDependenciesIncludingTransitive).ConfigureAwait(false); + + ProcessFrameworkAssemblies(dllImports, nugetAssemblyData); + ProcessLibAssemblies(buildResultItems, dllImports, nugetAssemblyData); + + return nugetAssemblyData; + } + + /// + /// Adds a new DLL import to the set if it does not already contain an import with the same name. + /// + /// A set of DLL imports. + /// The new import to add. + private static bool AddToDllImport(HashSet dllImports, string newImport) + { + if (!dllImports.Select(FileSystem.Instance.Path.GetFileName).Contains(FileSystem.Instance.Path.GetFileName(newImport))) + { + dllImports.Add(newImport); + return true; + } + + return false; + } + + /// + /// Processes NuGet assembly references for DLL import and updates the set of DLL imports and directory references accordingly. + /// + /// A set of DLL imports. + /// The NuGet package assembly data. + private static void ProcessDllImportNuGetAssemblyReferences(HashSet dllImports, NuGetPackageAssemblyData nugetAssemblyData) + { + if (nugetAssemblyData.DllImportNugetAssemblyReferences.Count <= 0) + { + return; + } + + var directoriesWithExplicitDllImport = new HashSet(); + var potentialRemainingDirectoryImports = new List(); + var assemblies = new Dictionary>(); + + foreach (var libItem in nugetAssemblyData.DllImportNugetAssemblyReferences) + { + string assemblyName = FileSystem.Instance.Path.GetFileName(libItem.DllImport); + + if (assemblies.TryGetValue(assemblyName, out var entries)) + { + entries.Add(libItem); + } + else + { + assemblies[assemblyName] = new List { libItem }; + } + } + + foreach (var assembly in assemblies) + { + var packagesContainingAssembly = assembly.Value; + + if (packagesContainingAssembly.Count == 1) + { + var libItem = packagesContainingAssembly[0]; + if (AddToDllImport(dllImports, libItem.DllImport)) + { + directoriesWithExplicitDllImport.Add(libItem.DllImport.Substring(0, libItem.DllImport.Length - assembly.Key.Length)); + } + else + { + potentialRemainingDirectoryImports.Add(FileSystem.Instance.Path.GetDirectoryName(libItem.DllImport) + "\\"); + } + } + else + { + PackageAssemblyReference mostRecentLibItem = SelectMostRecentVersion(packagesContainingAssembly); + if (mostRecentLibItem == null) + { + continue; + } + + if (AddToDllImport(dllImports, mostRecentLibItem.DllImport)) + { + directoriesWithExplicitDllImport.Add(mostRecentLibItem.DllImport.Substring(0, mostRecentLibItem.DllImport.Length - assembly.Key.Length)); + } + else + { + potentialRemainingDirectoryImports.Add(FileSystem.Instance.Path.GetDirectoryName(mostRecentLibItem.DllImport) + "\\"); + } + + foreach (var libItem in packagesContainingAssembly) + { + if (libItem != mostRecentLibItem) + { + string directoryPath = libItem.DllImport.Substring(0, libItem.DllImport.Length - assembly.Key.Length); + potentialRemainingDirectoryImports.Add(directoryPath); + } + } + } + } + + foreach (var directoryPath in potentialRemainingDirectoryImports) + { + if (!directoriesWithExplicitDllImport.Contains(directoryPath)) + { + nugetAssemblyData.DllImportDirectoryReferences.Add(directoryPath); + } + } + } + + /// + /// Processes framework assemblies and adds them to the set of DLL imports if not already present. + /// + /// A set of DLL imports. + /// The NuGet package assembly data. + private static void ProcessFrameworkAssemblies(HashSet dllImports, NuGetPackageAssemblyData nugetAssemblyData) + { + foreach (var frameworkAssembly in nugetAssemblyData.DllImportFrameworkAssemblyReferences) + { + if (!Helper.QActionDefaultImportDLLs.Any(a => String.Equals(a, frameworkAssembly, StringComparison.OrdinalIgnoreCase))) + { + dllImports.Add(frameworkAssembly); + } + } + } + + /// + /// Processes library assemblies and updates the build result items and DLL imports accordingly. + /// + /// The build result items. + /// A set of DLL imports. + /// The NuGet package assembly data. + private static void ProcessLibAssemblies(BuildResultItems buildResultItems, HashSet dllImports, NuGetPackageAssemblyData nugetAssemblyData) + { + ProcessDllImportNuGetAssemblyReferences(dllImports, nugetAssemblyData); + + foreach (var dir in nugetAssemblyData.DllImportDirectoryReferences) + { + if (!Helper.QActionDefaultImportDLLs.Any(d => String.Equals(d, dir, StringComparison.OrdinalIgnoreCase))) + { + dllImports.Add(dir); + } + } + + foreach (var libItem in nugetAssemblyData.NugetAssemblies) + { + if (!dllImports.Contains(FileSystem.Instance.Path.GetFileName(libItem.AssemblyPath)) && buildResultItems.Assemblies.FirstOrDefault(b => b.AssemblyPath == libItem.AssemblyPath) == null) + { + buildResultItems.Assemblies.Add(libItem); + } + } + } + + /// + /// Selects the most recent version of a package assembly reference from a list. + /// + /// The list of package assembly references. + /// The most recent package assembly reference, or null if the list is empty. + private static PackageAssemblyReference SelectMostRecentVersion(List packagesContainingAssembly) + { + PackageAssemblyReference mostRecentLibItem = null; + Version mostRecentVersion = null; + + foreach (var libItem in packagesContainingAssembly) + { + var version = AssemblyName.GetAssemblyName(libItem.AssemblyPath).Version; + if (mostRecentVersion == null || version > mostRecentVersion) + { + mostRecentVersion = version; + mostRecentLibItem = libItem; + } + } + + return mostRecentLibItem; + } + } +} \ No newline at end of file diff --git a/Assemblers.Protocol/AttachedBehavior.cs b/Assemblers.Protocol/AttachedBehavior.cs new file mode 100644 index 0000000..547a453 --- /dev/null +++ b/Assemblers.Protocol/AttachedBehavior.cs @@ -0,0 +1,13 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Protocol +{ + using System.Collections.Generic; + using System.Linq; + + internal static class AttachedBehavior + { + public static IEnumerable OrEmptyIfNull(this IEnumerable source) + { + return source ?? Enumerable.Empty(); + } + } +} diff --git a/Assemblers.Protocol/DevPackHelper.cs b/Assemblers.Protocol/DevPackHelper.cs new file mode 100644 index 0000000..4cee006 --- /dev/null +++ b/Assemblers.Protocol/DevPackHelper.cs @@ -0,0 +1,28 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Protocol +{ + using System; + using System.Collections.Generic; + + using Skyline.DataMiner.CICD.Parsers.Common.VisualStudio.Projects; + + internal static class DevPackHelper + { + private const string CommonDevPackName = "Skyline.DataMiner.Dev.Common"; + + private static readonly HashSet DevPackDllsToIgnore = new HashSet + { + "ICSharpCode.SharpZipLib.dll", + "Newtonsoft.Json.dll", + "protobuf-net.dll", + "SLProtoBufLibrary.dll", + }; + + public static bool IsDevPackDllReference(Reference reference) + { + string referenceDllName = reference.GetDllName(); + + return DevPackDllsToIgnore.Contains(referenceDllName) && + (reference.HintPath == null || reference.HintPath.Contains(CommonDevPackName)); + } + } +} \ No newline at end of file diff --git a/Assemblers.Protocol/Helper.cs b/Assemblers.Protocol/Helper.cs new file mode 100644 index 0000000..ed613ca --- /dev/null +++ b/Assemblers.Protocol/Helper.cs @@ -0,0 +1,50 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Protocol +{ + using System; + using System.Collections.Generic; + + using Skyline.DataMiner.CICD.Parsers.Common.VisualStudio.Projects; + using Skyline.DataMiner.CICD.Parsers.Protocol.Xml.QActions; + + /// + /// Protocol assembler helper class. + /// + public static class Helper + { + /// + /// Defines the assemblies that are referenced by default in DataMiner when a QAction is compiled. + /// + public static readonly IReadOnlyList QActionDefaultImportDLLs = new List() + { + "Interop.SLDms.dll", + "mscorlib.dll", + "QactionHelperBaseClasses.dll", + "Skyline.DataMiner.Storage.Types.dll", + "SLLoggerUtil.dll", + "SLManagedScripting.dll", + "SLNetTypes.dll", + "System.dll", + "System.Xml.dll", + "System.Core.dll", + }; + + /// + /// Retrieves the ID of the specified QAction project reference. A return value indicates whether the operation succeeded. + /// + /// The project reference. + /// The ID of the specified QAction project reference + /// true if the ID was successfully retrieved; otherwise, false. + public static bool TryGetQActionId(ProjectReference reference, out int id) + { + var m = QAction.RegexExtractQActionID.Match(reference.Name); + if (m.Success) + { + id = Convert.ToInt32(m.Groups["id"].Value); + return true; + } + + id = default(int); + return false; + } + } +} diff --git a/Assemblers.Protocol/ProtocolBuilder.cs b/Assemblers.Protocol/ProtocolBuilder.cs new file mode 100644 index 0000000..f7f0411 --- /dev/null +++ b/Assemblers.Protocol/ProtocolBuilder.cs @@ -0,0 +1,564 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Protocol +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Reflection; + using System.Text; + using System.Threading.Tasks; + + using NuGet.Packaging.Core; + using NuGet.Versioning; + + using Skyline.DataMiner.CICD.Assemblers.Common; + using Skyline.DataMiner.CICD.FileSystem; + using Skyline.DataMiner.CICD.Loggers; + using Skyline.DataMiner.CICD.Models.Protocol.Enums; + using Skyline.DataMiner.CICD.Models.Protocol.Read; + using Skyline.DataMiner.CICD.Models.Protocol.Read.Interfaces; + using Skyline.DataMiner.CICD.Parsers.Common.VisualStudio.Projects; + using Skyline.DataMiner.CICD.Parsers.Common.Xml; + using Skyline.DataMiner.CICD.Parsers.Protocol.VisualStudio; + + using EditXml = Skyline.DataMiner.CICD.Parsers.Common.XmlEdit; + using ProtocolDocumentEdit = Skyline.DataMiner.CICD.Models.Protocol.Edit.ProtocolDocumentEdit; + using QActionsQAction = Skyline.DataMiner.CICD.Models.Protocol.Edit.QActionsQAction; + + /// + /// Protocol builder. + /// + public class ProtocolBuilder + { + private readonly ILogCollector logCollector; + + /// + /// Initializes a new instance of the class using the specified protocol solution. + /// + /// The protocol solution. + /// is . + public ProtocolBuilder(ProtocolSolution solution) + { + if (solution == null) + { + throw new ArgumentNullException(nameof(solution)); + } + + Document = solution.ProtocolDocument; + Model = new ProtocolModel(Document); + + Projects = new Dictionary(); + + foreach (var p in solution.Projects) + { + Projects[p.Name] = solution.LoadProject(p); + } + } + + /// + /// Initializes a new instance of the class using the specified protocol solution. + /// + /// The protocol solution. + /// The log collector. + /// is . + public ProtocolBuilder(ProtocolSolution solution, ILogCollector logCollector) + : this(solution) + { + this.logCollector = logCollector; + } + + /// + /// Initializes a new instance of the class using the specified protocol solution. + /// + /// The protocol solution. + /// The log collector. + /// Version that will be used to override the version in the protocol itself. + /// is . + /// is , empty or whitespace. + public ProtocolBuilder(ProtocolSolution solution, ILogCollector logCollector, string overrideVersion) + : this(solution, logCollector) + { + if (String.IsNullOrWhiteSpace(overrideVersion)) + { + throw new ArgumentException(nameof(overrideVersion)); + } + + var edit = new EditXml.XmlDocument(solution.ProtocolDocument); + var version = edit.Root.Element["Version"]; + if (version == null) + { + throw new AssemblerException("Protocol does not contain a Version tag."); + } + + version.InnerText = overrideVersion; + + // Override the Document & Model as it now has the overridden version. + Document = XmlDocument.Parse(edit.GetXml()); + Model = new ProtocolModel(Document); + } + + /// + /// Initializes a new instance of the class using the specified document and projects. + /// + /// The protocol XML document. + /// The project dictionary. + /// Version that will be used to override the version in the protocol itself. + /// , or is . + internal ProtocolBuilder(XmlDocument document, IDictionary projects, string overrideVersion = null) + { + if (document is null) + { + throw new ArgumentNullException(nameof(document)); + } + + if (!String.IsNullOrWhiteSpace(overrideVersion)) + { + var edit = new EditXml.XmlDocument(document); + var version = edit.Root.Element["Version"]; + if (version == null) + { + throw new AssemblerException("Protocol does not contain a Version tag."); + } + + version.InnerText = overrideVersion; + + Document = XmlDocument.Parse(edit.GetXml()); + } + else + { + Document = document; + } + + Model = new ProtocolModel(Document); + Projects = projects ?? throw new ArgumentNullException(nameof(projects)); + } + + /// + /// Gets the XML document of the protocol. + /// + /// The protocol model. + public XmlDocument Document { get; } + + /// + /// Gets the protocol model/ + /// + /// The protocol model. + public IProtocolModel Model { get; } + + /// + /// Gets the projects dictionary. + /// + /// The projects dictionary. + public IDictionary Projects { get; } + + /// + /// Builds the protocol assembling the protocol document and projects into the full protocol XML document and assemblies of NuGet packages. + /// + /// The build result items. + /// Project with name '{projectName}' could not be found -or- + /// No code files found for QAction -or- + /// File could not be found in project -or- + /// Cannot replace QAction, because the target XML node is not empty. + public async Task BuildAsync() + { + logCollector?.ReportStatus("Building the protocol."); + var protocolEdit = new ProtocolDocumentEdit(Document, Model); + return await BuildResultsAsync(protocolEdit).ConfigureAwait(false); + } + + /// + /// Combines all the cs files in the project into a single string. + /// + /// Project. + /// String with all the code from the cs files. + /// No code files found in specified project. + public static string CombineProjectFiles(Project project) + { + var files = GetRelevantCodeFilesSorted(project); + + if (files.Count == 0) + { + throw new AssemblerException($"No code files found in project '{project.AssemblyName}'"); + } + + return CSharpCodeCombiner.CombineFiles(files); + } + + /// + /// Retrieves the C# files (.cs) of the QAction project in sorted order. + /// + /// The QAction project. + /// The C# files (.cs) of the QAction project in sorted order. + /// This method excludes any AssemblyInfo.cs file present in the project. + /// is . + public static IList GetRelevantCodeFilesSorted(Project project) + { + if (project == null) + { + throw new ArgumentNullException(nameof(project)); + } + + var files = project.Files + .Where(x => x.Name.EndsWith(".cs") && !x.Name.EndsWith("AssemblyInfo.cs")) + .OrderByDescending(x => x.Name.StartsWith("QAction_")) + .ThenBy(x => x.Name) + .ToList(); + + return files; + } + + private async Task BuildResultsAsync(ProtocolDocumentEdit protocolEdit) + { + BuildResultItems buildResultItems = new BuildResultItems(); + + await BuildQActions(protocolEdit, buildResultItems, Model?.Protocol?.Compliancies).ConfigureAwait(false); + BuildVersionHistoryComment(protocolEdit, Model); + buildResultItems.Document = protocolEdit.Document.GetXml(); + + return buildResultItems; + } + + private async Task BuildQActions(ProtocolDocumentEdit protocolEdit, BuildResultItems buildResultItems, ICompliancies compliancies) + { + logCollector?.ReportDebug("Building QActions"); + var packageReferenceProcessor = new PackageReferenceProcessor(directoryForNuGetConfig: null); + + var qactions = protocolEdit.Protocol?.QActions; + if (qactions != null) + { + foreach (var qa in qactions) + { + await BuildQAction(qa, qactions.Read, packageReferenceProcessor, buildResultItems, compliancies).ConfigureAwait(false); + } + } + } + + private async Task BuildQAction(QActionsQAction qa, IQActions allQActions, PackageReferenceProcessor packageReferenceProcessor, BuildResultItems buildResultItems, ICompliancies compliancies) + { + if (qa.Encoding?.Value != EnumQActionEncoding.Csharp) + { + // skip JScript etc.. + return; + } + + var qaId = qa.Id?.Value; + + string projectName = $"QAction_{qaId}"; + if (!Projects.TryGetValue(projectName, out var project)) + { + throw new AssemblerException($"Project with name '{projectName}' could not be found!"); + } + + // replace code + var hasQActionCodeChanges = BuildQActionCode(qa, project, qaId); + + // DLL imports + var hasDllImportChanges = await BuildQActionDllImports(qa, project, allQActions, packageReferenceProcessor, buildResultItems, compliancies).ConfigureAwait(false); + + // format + if (hasQActionCodeChanges || hasDllImportChanges) + { + qa.EditNode.Format(); + } + } + + private static bool BuildQActionCode(QActionsQAction qa, Project project, uint? qaId) + { + bool hasChanges = false; + + string newCode = CombineProjectFiles(project); + if (!String.IsNullOrWhiteSpace(newCode)) + { + if (!String.IsNullOrWhiteSpace(qa.Code) && !String.Equals(qa.Code, newCode)) + { + throw new AssemblerException($"Cannot replace QAction {qaId}, because the target XML node is not empty!"); + } + + qa.Code = newCode; + hasChanges = true; + } + + return hasChanges; + } + + private static async Task BuildQActionDllImports(QActionsQAction qa, Project project, IQActions allQActions, PackageReferenceProcessor packageReferenceProcessor, BuildResultItems buildResultItems, ICompliancies compliancies) + { + bool hasChanges = false; + + var dllImports = new HashSet(StringComparer.OrdinalIgnoreCase); + + string dllsFolder = null; + if (project.Path != null) + { + dllsFolder = FileSystem.Instance.Path.Combine(FileSystem.Instance.Directory.GetParentDirectory(FileSystem.Instance.Path.GetDirectoryName(project.Path)), @"Dlls\"); + } + + NuGetPackageAssemblyData nugetAssemblyData = await ProcessPackageReferences(project, packageReferenceProcessor, buildResultItems, dllImports); + ProcessReferences(project, packageReferenceProcessor, compliancies, nugetAssemblyData, dllsFolder, dllImports, buildResultItems); + ProcessProjectReferences(project, allQActions, dllImports); + + // Edit QAction@dllImport + if (dllImports.Count > 0) + { + qa.DllImport = String.Join(";", dllImports); + hasChanges = true; + } + + return hasChanges; + } + + private static async Task ProcessPackageReferences(Project project, PackageReferenceProcessor packageReferenceProcessor, + BuildResultItems buildResultItems, HashSet dllImports) + { + if (project.PackageReferences == null) + { + return null; + } + + List packageIdentities = GetPackageIdentities(project); + + if (packageIdentities.Count <= 0) + { + return null; + } + + NuGetPackageAssemblyData nugetAssemblyData = await AssemblyFilter.FilterAsync(project.TargetFrameworkMoniker, packageReferenceProcessor, buildResultItems, dllImports, packageIdentities).ConfigureAwait(false); + + return nugetAssemblyData; + } + + private static List GetPackageIdentities(Project project) + { + var packageIdentities = new List(); + + foreach (var packageReference in project.PackageReferences) + { + var packageIdentity = new PackageIdentity(packageReference.Name, NuGetVersion.Parse(packageReference.Version)); + packageIdentities.Add(packageIdentity); + } + + return packageIdentities; + } + + private static void ProcessProjectReferences(Project project, IQActions allQActions, HashSet dllImports) + { + if (project.ProjectReferences != null) + { + foreach (var r in project.ProjectReferences) + { + if (r.Name == "QAction_ClassLibrary") + { + // Do nothing (no longer supported). + } + else if (r.Name == "QAction_Helper") + { + // Do nothing. + } + else if (Helper.TryGetQActionId(r, out int id)) + { + var refQA = allQActions.FirstOrDefault(q => q.Id?.Value == id); + if (refQA != null) + { + string dll; + + var options = refQA.GetOptions(); + if (!String.IsNullOrWhiteSpace(options?.CustomDllName)) + { + dll = $"[ProtocolName].[ProtocolVersion].{options.CustomDllName}"; + } + else + { + dll = $"[ProtocolName].[ProtocolVersion].QAction.{id}.dll"; + } + + dllImports.Add(dll); + } + } + else if (!String.IsNullOrWhiteSpace(r.Name)) + { + dllImports.Add($"{r.Name}.dll"); + } + } + } + } + + private static void ProcessReferences(Project project, PackageReferenceProcessor packageReferenceProcessor, ICompliancies compliancies, + NuGetPackageAssemblyData nugetAssemblyData, string dllsFolder, HashSet dllImports, BuildResultItems buildResultItems) + { + if (project.References == null) + { + return; + } + + foreach (Reference r in project.References) + { + string dllName = r.GetDllName(); + + if (IsDllDefaultInQAction(dllName, compliancies) || DevPackHelper.IsDevPackDllReference(r) || + (nugetAssemblyData != null && nugetAssemblyData.ProcessedAssemblies.Contains(dllName))) + { + continue; + } + + if (r.HintPath?.Contains(packageReferenceProcessor.NuGetRootPath) == true) + { + // DLL is from a NuGet but is transitive from precompile or other project reference. + // These can be ignored. + continue; + } + + if (r.HintPath != null && FileSystem.Instance.Path.IsPathRooted(r.HintPath)) + { + string absolutePath = r.HintPath; + + if (absolutePath.StartsWith(@"C:\Skyline DataMiner\ProtocolScripts\DllImport\")) + { + dllName = absolutePath.Substring(47); + } + else if (absolutePath.StartsWith(@"C:\Skyline DataMiner\ProtocolScripts\")) + { + dllName = absolutePath.Substring(37); + } + else if (absolutePath.StartsWith(@"C:\Skyline DataMiner\Files\")) + { + dllName = absolutePath.Substring(27); + } + else if (dllsFolder != null && absolutePath.StartsWith(dllsFolder)) + { + dllName = absolutePath.Substring(dllsFolder.Length); + } + } + + dllImports.Add(dllName); + + // If custom DLL + if (r.HintPath != null && project.ProjectStyle == ProjectStyle.Sdk) + { + string dllPath = FileSystem.Instance.Path.GetFullPath(FileSystem.Instance.Path.Combine(project.ProjectDirectory, r.HintPath)); + + buildResultItems.DllAssemblies.Add(new DllAssemblyReference(dllName, dllPath)); + } + } + } + + private static bool IsDllDefaultInQAction(string dllName, ICompliancies compliancies) + { + if (dllName.Equals("System.Xml.dll", StringComparison.OrdinalIgnoreCase)) + { + string minimumRequiredVersion = compliancies?.MinimumRequiredVersion?.Value ?? String.Empty; + string[] versionParts = minimumRequiredVersion.Split('.'); + + // See RN 19494. + if (!Int32.TryParse(versionParts[0], out int major) || major >= 10) + { + return true; + } + } + else if (Helper.QActionDefaultImportDLLs.Any(d => String.Equals(d, dllName, StringComparison.OrdinalIgnoreCase))) + { + return true; + } + + return false; + } + + private void BuildVersionHistoryComment(ProtocolDocumentEdit protocolEdit, IProtocolModel model) + { + logCollector?.ReportDebug("Building version history comment"); + var versionHistory = model.Protocol?.VersionHistory; + if (versionHistory == null) + { + return; + } + + var xmlEdit = protocolEdit.Document; + var xmlProtocol = xmlEdit.TryFindNode(model.Protocol.ReadNode); + + var firstXmlComment = xmlEdit.Children.OfType().FirstOrDefault(); + if (firstXmlComment == null || xmlEdit.Children.IndexOf(firstXmlComment) > xmlEdit.Children.IndexOf(xmlProtocol)) + { + firstXmlComment = new EditXml.XmlComment(""); + xmlEdit.Children.InsertBefore(xmlProtocol, firstXmlComment); + xmlEdit.Children.InsertBefore(xmlProtocol, new EditXml.XmlText("\r\n")); + } + + firstXmlComment.InnerText += "\r\n\r\n" + BuildVersionHistoryComment(versionHistory); + } + + private static string BuildVersionHistoryComment(IVersionHistory versionHistory) + { + if (versionHistory is null) + { + throw new ArgumentNullException(nameof(versionHistory)); + } + + AsciiTable table = new AsciiTable(); + + void appendComment(string datetime, string version, string author, string comment) + { + var commentLines = GetLines(comment).ToList(); + + table.AddRow(datetime, version, author, commentLines.Count > 0 ? commentLines[0] : ""); + + for (int i = 1; i < commentLines.Count; i++) + { + table.AddRow("", "", "", commentLines[i]); + } + } + + table.AddRow("DATE", "VERSION", "AUTHOR", "COMMENTS"); + table.AddRow(); + + foreach (var branch in versionHistory.Branches.OrEmptyIfNull().OrderBy(x => x.Id?.Value)) + { + foreach (var systemVersion in branch.SystemVersions.OrEmptyIfNull().OrderBy(x => x.Id?.Value)) + { + foreach (var majorVersion in systemVersion.MajorVersions.OrEmptyIfNull().OrderBy(x => x.Id?.Value)) + { + foreach (var minorVersion in majorVersion.MinorVersions.OrEmptyIfNull().OrderBy(x => x.Id?.Value)) + { + string date = minorVersion.Date?.Value?.ToString("dd/MM/yyyy"); + string version = String.Join(".", branch.Id?.Value, systemVersion.Id?.Value, majorVersion.Id?.Value, minorVersion.Id?.Value); + string author = $"{minorVersion.Provider?.Author?.Value}, {minorVersion.Provider?.Company?.Value}"; + + StringBuilder sbComment = new StringBuilder(); + + foreach (var change in minorVersion.Changes) + { + switch (change) + { + case IVersionHistoryBranchesBranchSystemVersionsSystemVersionMajorVersionsMajorVersionMinorVersionsMinorVersionChangesNewFeature nf: + sbComment.AppendLine("NF: " + nf.Value); + break; + case IVersionHistoryBranchesBranchSystemVersionsSystemVersionMajorVersionsMajorVersionMinorVersionsMinorVersionChangesFix f: + sbComment.AppendLine("Fix: " + f.Value); + break; + case IVersionHistoryBranchesBranchSystemVersionsSystemVersionMajorVersionsMajorVersionMinorVersionsMinorVersionChangesChange c: + sbComment.AppendLine("Change: " + c.Value); + break; + } + } + + string comment = sbComment.ToString().Trim(); + + appendComment(date, version, author, comment); + } + } + } + } + + return "Revision History (auto generated):\r\n\r\n" + table.ToString(); + } + + private static IEnumerable GetLines(string s) + { + StringReader sr = new StringReader(s); + + string line; + while ((line = sr.ReadLine()) != null) + { + yield return line; + } + } + } +} diff --git a/Assemblers.ProtocolTests/Assemblers.ProtocolTests.csproj b/Assemblers.ProtocolTests/Assemblers.ProtocolTests.csproj new file mode 100644 index 0000000..8e34d0d --- /dev/null +++ b/Assemblers.ProtocolTests/Assemblers.ProtocolTests.csproj @@ -0,0 +1,34 @@ + + + + net48;net8.0 + false + disable + disable + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + PreserveNewest + + + diff --git a/Assemblers.ProtocolTests/Logging.cs b/Assemblers.ProtocolTests/Logging.cs new file mode 100644 index 0000000..cb44970 --- /dev/null +++ b/Assemblers.ProtocolTests/Logging.cs @@ -0,0 +1,44 @@ +namespace Assemblers.ProtocolTests +{ + using System; + + using Skyline.DataMiner.CICD.Loggers; + + internal class Logging : ILogCollector + { + private readonly bool debug; + + public Logging(bool debug) + { + this.debug = debug; + } + + public void ReportError(string error) + { + ReportLog($"ERROR|{error}"); + } + + public void ReportStatus(string status) + { + ReportLog($"STATUS|{status}"); + } + + public void ReportWarning(string warning) + { + ReportLog($"WARNING|{warning}"); + } + + public void ReportDebug(string debug) + { + ReportLog($"DEBUG|{debug}"); + } + + public void ReportLog(string message) + { + if (debug) + { + Console.WriteLine(message); + } + } + } +} diff --git a/Assemblers.ProtocolTests/ProcessAssembliesTests.cs b/Assemblers.ProtocolTests/ProcessAssembliesTests.cs new file mode 100644 index 0000000..9a73549 --- /dev/null +++ b/Assemblers.ProtocolTests/ProcessAssembliesTests.cs @@ -0,0 +1,71 @@ +namespace Assemblers.ProtocolTests +{ + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + + using FluentAssertions; + + using Microsoft.VisualStudio.TestTools.UnitTesting; + + using NuGet.Packaging.Core; + using NuGet.Versioning; + + using Skyline.DataMiner.CICD.Assemblers.Common; + using Skyline.DataMiner.CICD.Assemblers.Protocol; + using Skyline.DataMiner.CICD.Loggers; + + [TestClass] + public class AssemblyFilterTests + { + [TestMethod] + public async Task ProcessAsyncTest_DuplicateFrameworkScenario() + { + // Arrange + var packageReferenceProcessor = new PackageReferenceProcessor(directoryForNuGetConfig: null); + + IList projectPackages = new List + { + new PackageIdentity("microsoft.extensions.http", new NuGetVersion("6.0.0")), + new PackageIdentity("nats.client", new NuGetVersion("1.1.0")), + }; + + const string targetFrameworkMoniker = ".NETFramework,Version=v4.6.2"; + + BuildResultItems buildResultItems = new BuildResultItems(); + HashSet dllImports = new HashSet(); + + // Act + var result = await AssemblyFilter.FilterAsync(targetFrameworkMoniker, packageReferenceProcessor, buildResultItems, dllImports, + projectPackages); + + // Assert + // Make sure there is only one System.Net.Http.dll + // NuGetAssemblies and NetFramework cannot both have System.Net.Http which causes incorrect behavior down the line. + // BuildResultItems + // AssemblyPath: c:\Users\{user}\.nuget\packages\system.net.http\4.3.4\lib\net46\System.Net.Http.dll + // dllImports: system.net.http\4.3.4\lib\net46\System.Net.Http.dll + // dllImports hashset: + // System.Net.Http.dll + + result.Should().NotBeNull(); + // dllImports needs priority + dllImports.Should().Contain("System.Net.Http.dll"); + // buildResultItems should not have system.net.http + // dllImports should not have duplicate system.net.http + dllImports.Should().NotContain(@"system.net.http\4.3.4\lib\net46\System.Net.Http.dll"); + + // dllImports should still have added the folder, in order to access other dll's from the same nuget + dllImports.Should().Contain(@"system.net.http\4.3.4\lib\net46\"); + + var unexpectedPackageReference = + new PackageAssemblyReference(@"system.net.http\4.3.4\lib\net46\System.Net.Http.dll", String.Empty, false); + buildResultItems.Assemblies.Should().NotContainEquivalentOf(unexpectedPackageReference, + options => options.Excluding(reference => reference.AssemblyPath)); + + // Best effort to save time. + dllImports.Count.Should().Be(26); + buildResultItems.Assemblies.Count.Should().Be(22); + } + } +} \ No newline at end of file diff --git a/Assemblers.ProtocolTests/ProtocolBuilderTests.cs b/Assemblers.ProtocolTests/ProtocolBuilderTests.cs new file mode 100644 index 0000000..b76d5b8 --- /dev/null +++ b/Assemblers.ProtocolTests/ProtocolBuilderTests.cs @@ -0,0 +1,832 @@ +namespace Assemblers.ProtocolTests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using System.Threading.Tasks; + + using FluentAssertions; + + using Microsoft.VisualStudio.TestTools.UnitTesting; + + using Org.XmlUnit.Builder; + using Org.XmlUnit.Diff; + + using Skyline.DataMiner.CICD.Assemblers.Common; + using Skyline.DataMiner.CICD.Assemblers.Protocol; + using Skyline.DataMiner.CICD.FileSystem; + using Skyline.DataMiner.CICD.Parsers.Common.VisualStudio.Projects; + using Skyline.DataMiner.CICD.Parsers.Common.Xml; + using Skyline.DataMiner.CICD.Parsers.Protocol.VisualStudio; + + [TestClass] + public class ProtocolBuilderTests + { + [TestMethod] + public async Task ProtocolBuilder_BuildAsync_IgnoreSatelliteAssemblies() + { + var logCollector = new Logging(true); + + var baseDir = FileSystem.Instance.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var dir = FileSystem.Instance.Path.GetFullPath(FileSystem.Instance.Path.Combine(baseDir, @"TestFiles\Solutions\Solution2")); + var solutionFilePath = FileSystem.Instance.Path.Combine(dir, "protocol.sln"); + + ProtocolSolution solution = ProtocolSolution.Load(solutionFilePath, logCollector); + ProtocolBuilder protocolBuilder = new ProtocolBuilder(solution, logCollector); + + var buildResultItems = await protocolBuilder.BuildAsync(); + + Assert.IsNotNull(buildResultItems.Assemblies); + Assert.HasCount(1, buildResultItems.Assemblies); + Assert.AreEqual(@"microsoft.visualstudio.validation\17.8.8\lib\netstandard2.0\Microsoft.VisualStudio.Validation.dll", buildResultItems.Assemblies.First().DllImport); + } + + [TestMethod] + public async Task ProtocolBuilder_BuildAsync_KeepReferenceAssemblies() + { + var logCollector = new Logging(true); + + var baseDir = FileSystem.Instance.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var dir = FileSystem.Instance.Path.GetFullPath(FileSystem.Instance.Path.Combine(baseDir, @"TestFiles\Solutions\Solution3")); + var solutionFilePath = FileSystem.Instance.Path.Combine(dir, "protocol.sln"); + + ProtocolSolution solution = ProtocolSolution.Load(solutionFilePath, logCollector); + ProtocolBuilder protocolBuilder = new ProtocolBuilder(solution, logCollector); + + var buildResultItems = await protocolBuilder.BuildAsync(); + + Assert.IsNotNull(buildResultItems.Assemblies); + Assert.HasCount(18, buildResultItems.Assemblies); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_BasicAsync() + { + string originalProtocol = @" + + + +"; + + string expected = @" + + + + + +"; + + var projects = new Dictionary() + { + { "QAction_1", new Project("QAction_1", new[]{ new ProjectFile("QAction_1.cs", "using System;") }) }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_MultipleQActionsAsync() + { + string originalProtocol = @" + + + + +"; + + string expected = @" + + + + + + + + +"; + + var projects = new Dictionary() + { + { "QAction_1", new Project("QAction_1", new[]{ new ProjectFile("QAction_1.cs", "using System;") }) }, + { "QAction_2", new Project("QAction_2", new[]{ new ProjectFile("QAction_2.cs", "using System.Xml;") }) }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_VersionHistoryAsync() + { + string originalProtocol = @" + + + + + + + + + + + + Change1 + Fix1 + NewFeature1 + + 2020-01-02 + + TWA + Skyline Communications + + + + + Change2 + + 2020-01-03 + + TWA + Skyline Communications + + + + + 2020-01-04 + + TWA + Skyline Communications + + + + + + + + + + +"; + + string expected = @" + + + + + + + + + + + + + Change1 + Fix1 + NewFeature1 + + 2020-01-02 + + TWA + Skyline Communications + + + + + Change2 + + 2020-01-03 + + TWA + Skyline Communications + + + + + 2020-01-04 + + TWA + Skyline Communications + + + + + + + + + + +"; + + var projects = new Dictionary(); + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_MultipleFilesAsync() + { + string originalProtocol = @" + + + +"; + + string expected = @" + + + + + +"; + + var projects = new Dictionary() + { + { "QAction_3", new Project("QAction_3", new[]{ + new ProjectFile("QAction_3.cs", "using System;"), + new ProjectFile("Class1.cs", "using System; class Class1 {}") + }) }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public void ProtocolCompiler_ProtocolBuilder_TargetNotEmpty() + { + string originalProtocol = @" + + + + + +"; + + var projects = new Dictionary() + { + { "QAction_1", new Project("QAction_1", new[]{ new ProjectFile("QAction_1.cs", "using System.Xml;") }) }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + var exception = Assert.Throws(() => builder.BuildAsync().Result); + + Assert.IsNotNull(exception.InnerException); + Assert.IsInstanceOfType(exception.InnerException, typeof(AssemblerException)); + Assert.AreEqual("Cannot replace QAction 1, because the target XML node is not empty!", exception.InnerException.Message); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_DllImportsAsync() + { + string originalProtocol = @" + + + +"; + + string expected = @" + + + + + +"; + + var projectFiles = new[] { new ProjectFile("QAction_1.cs", "using System;") }; + var references = new[] { new Reference("System.Data.dll"), new Reference("System.Xml.dll") }; + var project1 = new Project("QAction_1", projectFiles: projectFiles, references: references); + + var projects = new Dictionary() + { + { "QAction_1", project1 }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_DllImports_NoDuplicateAsync() + { + string originalProtocol = @" + + + +"; + + string expected = @" + + + + + +"; + + var projectFiles = new[] { new ProjectFile("QAction_1.cs", "using System;") }; + var references = new[] { new Reference("System.Data.dll"), new Reference("System.Xml.dll") }; + var project1 = new Project("QAction_1", projectFiles: projectFiles, references: references); + + var projects = new Dictionary() + { + { "QAction_1", project1 }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_DllImports_ProjectReference() + { + string originalProtocol = @" + + + +"; + + string expected = @" + + + + + +"; + + var projectFiles = new[] { new ProjectFile("QAction_1.cs", "using System;") }; + var projectReferences = new[] { new ProjectReference("MyLibrary") }; + var project1 = new Project("QAction_1", projectFiles: projectFiles, projectReferences: projectReferences); + + var projects = new Dictionary() + { + { "QAction_1", project1 }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_ClassLibraryAsync() + { + string originalProtocol = @" + + + + +"; + + string expected = @" + + + + + + + + +"; + + var project63000 = new Project("QAction_63000", new[] { new ProjectFile("QAction_63000.cs", "namespace Skyline.DataMiner.Library { }") }); + + var projectFiles = new[] { new ProjectFile("QAction_1.cs", "using System;") }; + var references = new[] { new Reference("System.Data.dll"), new Reference("System.Xml.dll") }; + var projectReferences = new[] { new ProjectReference("QAction_63000") }; + var project1 = new Project("QAction_1", projectFiles: projectFiles, projectReferences: projectReferences, references: references); + + var projects = new Dictionary() + { + { "QAction_63000", project63000 }, + { "QAction_1", project1 }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_ReferencedQActionAsync() + { + string originalProtocol = @" + + + + +"; + + string expected = @" + + + + + + + + +"; + + var project1 = new Project("QAction_1", new[] { new ProjectFile("QAction_1.cs", "using System;") }); + + var projectReferences = new[] { new ProjectReference("QAction_1") }; + var project2 = new Project("QAction_2", projectFiles: new[] { new ProjectFile("QAction_2.cs", "using System;") }, projectReferences: projectReferences); + + var projects = new Dictionary() + { + { "QAction_1", project1 }, + { "QAction_2", project2 }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_ReferencedQActionWithCustomNameAsync() + { + string originalProtocol = @" + + + + +"; + + string expected = @" + + + + + + + + +"; + + var project1 = new Project("QAction_1", new[] { new ProjectFile("QAction_1.cs", "using System;") }); + + var projectReferences = new[] { new ProjectReference("QAction_1") }; + var project2 = new Project("QAction_2", projectFiles: new[] { new ProjectFile("QAction_2.cs", "using System;") }, projectReferences: projectReferences); + + var projects = new Dictionary() + { + { "QAction_1", project1 }, + { "QAction_2", project2 }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public void ProtocolCompiler_ProtocolBuilder_MissingQAction() + { + string originalProtocol = @" + + + +"; + + var projects = new Dictionary(); + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + var exception = Assert.Throws(() => builder.BuildAsync().Result); + + Assert.IsNotNull(exception.InnerException); + Assert.IsInstanceOfType(exception.InnerException, typeof(AssemblerException)); + Assert.AreEqual("Project with name 'QAction_1' could not be found!", exception.InnerException.Message); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_MissingNameAsync() + { + string originalProtocol = @" + + + +"; + + string expected = @" + + + + + +"; + + var projects = new Dictionary() + { + { "QAction_1", new Project("QAction_1", new[]{ new ProjectFile("QAction_1.cs", "using System;") }) }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_JScriptQActionAsync() + { + string originalProtocol = @" + + + + + +"; + + string expected = @" + + + + + +"; + + var projects = new Dictionary(); + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_SpecialCharactersAsync() + { + string originalProtocol = @" + + + +"; + + string expected = @" + + + + + +"; + + var projects = new Dictionary() + { + { "QAction_1", new Project("QAction_1", new[]{ new ProjectFile("QAction_1.cs", "using Characterø;") }) }, + }; + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_Solution_Build() + { + // arrange + var baseDir = FileSystem.Instance.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var dir = FileSystem.Instance.Path.GetFullPath(FileSystem.Instance.Path.Combine(baseDir, @"TestFiles\Solutions\Solution1")); + var path = FileSystem.Instance.Path.Combine(dir, "Protocol.sln"); + + var solution = ProtocolSolution.Load(path); + + // act + ProtocolBuilder builder = new ProtocolBuilder(solution); + var buildResultItems = await builder.BuildAsync().ConfigureAwait(false); + + string result = buildResultItems.Document; + + // check + string expected = @" + + + + + + + + + + + + + + + + + +"; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public async Task ProtocolCompiler_ProtocolBuilder_OverrideVersion() + { + string originalProtocol = @" + 1.0.0.1 +"; + + string expected = @" + 1.0.0.1_DIS +"; + + var projects = new Dictionary(0); + + ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects, "1.0.0.1_DIS"); + + string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + + Diff d = DiffBuilder.Compare(Input.FromString(expected)) + .WithTest(Input.FromString(result)).Build(); + + Assert.IsFalse(d.HasDifferences(), d.ToString()); + } + + [TestMethod] + public void ProtocolCompiler_ProtocolBuilder_OverrideVersion_MissingVersionTag() + { + string originalProtocol = @" +"; + + var projects = new Dictionary(0); + + Assert.Throws(() => new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects, "1.0.0.1_DIS")); + } + + [TestMethod] + public async Task ProtocolSolution_BuildAsync_SolutionLibraries() + { + // Arrange + var baseDir = FileSystem.Instance.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var dir = FileSystem.Instance.Path.GetFullPath(FileSystem.Instance.Path.Combine(baseDir, @"TestFiles\Solutions\Solution4")); + var path = FileSystem.Instance.Path.Combine(dir, "Protocol.sln"); + + var solution = ProtocolSolution.Load(path); + + // Act + ProtocolBuilder builder = new ProtocolBuilder(solution); + var result = await builder.BuildAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeNull(); + result.Document.Should() + .ContainEquivalentOf( + "dllImport=\"SolutionLibraries\\ModSolutionLib\\Skyline.DataMiner.Dev.Utils.ModSolutionLib.dll\""); + + // Only needs to be referenced, shouldn't be part of the script itself + result.Assemblies.Should().BeEmpty(); + result.DllAssemblies.Should().BeEmpty(); + } + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/Protocol.sln b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/Protocol.sln new file mode 100644 index 0000000..5b9de86 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/Protocol.sln @@ -0,0 +1,65 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33414.496 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{13998E16-2F02-4D47-BEB1-4ED034DD72D8}" + ProjectSection(SolutionItems) = preProject + protocol.xml = protocol.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QActions", "QActions", "{F32C5E72-BF2C-45CF-AAB1-DADCC040E51C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QAction_1", "QAction_1\QAction_1.csproj", "{20481214-4655-4C51-97AA-5DA92296CBCF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QAction_2", "QAction_2\QAction_2.csproj", "{B5ED3E0A-72ED-42ED-8375-65925907F2D9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{07EA3993-AA2E-4C59-9110-BF25DB8450BE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QAction_Helper", "QAction_Helper\QAction_Helper.csproj", "{31B1EF6A-2E94-4F70-9B05-F297AB3B6C69}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QAction_63000", "QAction_63000\QAction_63000.csproj", "{113FC56A-2732-420E-B365-3915558AFD45}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QAction_3", "QAction_3\QAction_3.csproj", "{35F7A839-1F8D-4932-8850-D6B9FD17A2E8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {20481214-4655-4C51-97AA-5DA92296CBCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20481214-4655-4C51-97AA-5DA92296CBCF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20481214-4655-4C51-97AA-5DA92296CBCF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20481214-4655-4C51-97AA-5DA92296CBCF}.Release|Any CPU.Build.0 = Release|Any CPU + {B5ED3E0A-72ED-42ED-8375-65925907F2D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5ED3E0A-72ED-42ED-8375-65925907F2D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5ED3E0A-72ED-42ED-8375-65925907F2D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5ED3E0A-72ED-42ED-8375-65925907F2D9}.Release|Any CPU.Build.0 = Release|Any CPU + {31B1EF6A-2E94-4F70-9B05-F297AB3B6C69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {31B1EF6A-2E94-4F70-9B05-F297AB3B6C69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31B1EF6A-2E94-4F70-9B05-F297AB3B6C69}.Release|Any CPU.ActiveCfg = Release|Any CPU + {31B1EF6A-2E94-4F70-9B05-F297AB3B6C69}.Release|Any CPU.Build.0 = Release|Any CPU + {113FC56A-2732-420E-B365-3915558AFD45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {113FC56A-2732-420E-B365-3915558AFD45}.Debug|Any CPU.Build.0 = Debug|Any CPU + {113FC56A-2732-420E-B365-3915558AFD45}.Release|Any CPU.ActiveCfg = Release|Any CPU + {113FC56A-2732-420E-B365-3915558AFD45}.Release|Any CPU.Build.0 = Release|Any CPU + {35F7A839-1F8D-4932-8850-D6B9FD17A2E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35F7A839-1F8D-4932-8850-D6B9FD17A2E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35F7A839-1F8D-4932-8850-D6B9FD17A2E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35F7A839-1F8D-4932-8850-D6B9FD17A2E8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {20481214-4655-4C51-97AA-5DA92296CBCF} = {F32C5E72-BF2C-45CF-AAB1-DADCC040E51C} + {B5ED3E0A-72ED-42ED-8375-65925907F2D9} = {F32C5E72-BF2C-45CF-AAB1-DADCC040E51C} + {31B1EF6A-2E94-4F70-9B05-F297AB3B6C69} = {07EA3993-AA2E-4C59-9110-BF25DB8450BE} + {113FC56A-2732-420E-B365-3915558AFD45} = {F32C5E72-BF2C-45CF-AAB1-DADCC040E51C} + {35F7A839-1F8D-4932-8850-D6B9FD17A2E8} = {F32C5E72-BF2C-45CF-AAB1-DADCC040E51C} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {58942BE7-5A68-461B-8F90-E06699C84F5C} + EndGlobalSection +EndGlobal diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_1/Class1.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_1/Class1.cs new file mode 100644 index 0000000..e486b61 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_1/Class1.cs @@ -0,0 +1,6 @@ +namespace QAction_1 +{ + public class Class1 + { + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_1/Properties/AssemblyInfo.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1b24379 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_1/Properties/AssemblyInfo.cs @@ -0,0 +1,5 @@ +using System.Reflection; + + +[assembly: AssemblyTitle("QAction_1")] +[assembly: AssemblyDescription("")] diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_1/QAction_1.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_1/QAction_1.csproj new file mode 100644 index 0000000..7752adb --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_1/QAction_1.csproj @@ -0,0 +1,59 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {20481214-4655-4C51-97AA-5DA92296CBCF} + Library + Properties + QAction_1 + QAction_1 + v4.6 + 512 + 7.3 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + None + + + + ..\..\..\..\..\..\..\..\..\..\..\Skyline DataMiner\ProtocolScripts\Newtonsoft.Json.dll + + + + + + + + + + + {113fc56a-2732-420e-b365-3915558afd45} + QAction_63000 + + + {31b1ef6a-2e94-4f70-9b05-f297ab3b6c69} + QAction_Helper + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_2/QAction_2.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_2/QAction_2.cs new file mode 100644 index 0000000..b2bd68b --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_2/QAction_2.cs @@ -0,0 +1,6 @@ +namespace QAction_2 +{ + public class QAction_2 + { + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_2/QAction_2.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_2/QAction_2.csproj new file mode 100644 index 0000000..700ba66 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_2/QAction_2.csproj @@ -0,0 +1,58 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {B5ED3E0A-72ED-42ED-8375-65925907F2D9} + Library + Properties + QAction_2 + QAction_2 + v4.6 + 512 + 7.3 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + None + + + + + + + + + + {20481214-4655-4c51-97aa-5da92296cbcf} + QAction_1 + + + {113fc56a-2732-420e-b365-3915558afd45} + QAction_63000 + + + {31b1ef6a-2e94-4f70-9b05-f297ab3b6c69} + QAction_Helper + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/Class1.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/Class1.cs new file mode 100644 index 0000000..228673c --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/Class1.cs @@ -0,0 +1,6 @@ +namespace QAction_3 +{ + public class Class1 + { + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/QAction_3.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/QAction_3.cs new file mode 100644 index 0000000..e19b113 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/QAction_3.cs @@ -0,0 +1,6 @@ +namespace QAction_3 +{ + public class QAction_3 + { + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/QAction_3.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/QAction_3.csproj new file mode 100644 index 0000000..8b77711 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/QAction_3.csproj @@ -0,0 +1,58 @@ + + + + + Debug + AnyCPU + {35F7A839-1F8D-4932-8850-D6B9FD17A2E8} + Library + Properties + QAction_3 + QAction_3 + v4.6.2 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + {113fc56a-2732-420e-b365-3915558afd45} + QAction_63000 + + + {31b1ef6a-2e94-4f70-9b05-f297ab3b6c69} + QAction_Helper + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/SubDir/Class2.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/SubDir/Class2.cs new file mode 100644 index 0000000..1959565 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_3/SubDir/Class2.cs @@ -0,0 +1,6 @@ +namespace QAction_3 +{ + public class Class2 + { + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_63000/QAction_63000.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_63000/QAction_63000.cs new file mode 100644 index 0000000..0bb2afc --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_63000/QAction_63000.cs @@ -0,0 +1,6 @@ +namespace QAction_63000 +{ + public class QAction_63000 + { + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_63000/QAction_63000.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_63000/QAction_63000.csproj new file mode 100644 index 0000000..58a2e21 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_63000/QAction_63000.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + {113FC56A-2732-420E-B365-3915558AFD45} + Library + Properties + QAction_63000 + QAction_63000 + v4.6 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + {31b1ef6a-2e94-4f70-9b05-f297ab3b6c69} + QAction_Helper + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_ClassLibrary/QAction_ClassLibrary.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_ClassLibrary/QAction_ClassLibrary.cs new file mode 100644 index 0000000..b936d2f --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_ClassLibrary/QAction_ClassLibrary.cs @@ -0,0 +1,5 @@ +// This is auto-generated code by DIS. Do not modify. +namespace Skyline.DataMiner.Library +{ + +} \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_ClassLibrary/QAction_ClassLibrary.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_ClassLibrary/QAction_ClassLibrary.csproj new file mode 100644 index 0000000..312b0ed --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_ClassLibrary/QAction_ClassLibrary.csproj @@ -0,0 +1,42 @@ + + + + + Debug + AnyCPU + {08EC67C1-11E7-4BEC-B22B-63F115216912} + Library + Properties + QAction_ClassLibrary + QAction_ClassLibrary + v4.6 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_Helper/QAction_Helper.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_Helper/QAction_Helper.cs new file mode 100644 index 0000000..fd0ea5a --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_Helper/QAction_Helper.cs @@ -0,0 +1 @@ +// This is auto-generated code by DIS. Do not modify. \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_Helper/QAction_Helper.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_Helper/QAction_Helper.csproj new file mode 100644 index 0000000..a7eb9ac --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/QAction_Helper/QAction_Helper.csproj @@ -0,0 +1,42 @@ + + + + + Debug + AnyCPU + {31B1EF6A-2E94-4F70-9B05-F297AB3B6C69} + Library + Properties + QAction_Helper + QAction_Helper + v4.6 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/protocol.xml b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/protocol.xml new file mode 100644 index 0000000..2d254da --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution1/protocol.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/DefaultTemplates/ABOUT.md b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/DefaultTemplates/ABOUT.md new file mode 100644 index 0000000..8041bec --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/DefaultTemplates/ABOUT.md @@ -0,0 +1,5 @@ +This folder contains default templates to be used by the protocol. +Allowed names: +"Template_Alarm_Default.xml" +"Trending_Template_Default.xml" +"Information_Template_Default.xml" diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Directory.Build.props b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Directory.Build.props new file mode 100644 index 0000000..4cb446b --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Directory.Build.props @@ -0,0 +1,31 @@ + + + x86 + true + + + $(DefineConstants);DCFv1;DBInfo;ALARM_SQUASHING + + + full + ..\Internal\Code Analysis\qaction-debug.ruleset + + + pdbonly + ..\Internal\Code Analysis\qaction-release.ruleset + + + + Properties\stylecop.json + + + Properties\.editorconfig + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Directory.Build.targets b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Directory.Build.targets new file mode 100644 index 0000000..6de23bf --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Directory.Build.targets @@ -0,0 +1,5 @@ + + + $(AssemblySearchPaths);$(ReferencePath) + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Dlls/ABOUT.md b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Dlls/ABOUT.md new file mode 100644 index 0000000..a3170b3 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Dlls/ABOUT.md @@ -0,0 +1 @@ +This folder contains DLL files that should be placed under the ProtocolScripts folder of DataMiner for this solution to work correctly. \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Documentation/ABOUT.md b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Documentation/ABOUT.md new file mode 100644 index 0000000..a150545 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Documentation/ABOUT.md @@ -0,0 +1 @@ +Looking for README.md? Check your Solution Root folder. This folder can be used to add documentation related to this solution. \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/.editorconfig b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/Code Analysis/qaction-debug.ruleset b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/Code Analysis/qaction-debug.ruleset new file mode 100644 index 0000000..26e7d46 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/Code Analysis/qaction-debug.ruleset @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/Code Analysis/qaction-release.ruleset b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/Code Analysis/qaction-release.ruleset new file mode 100644 index 0000000..de0890a --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/Code Analysis/qaction-release.ruleset @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/Code Analysis/stylecop.json b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/Code Analysis/stylecop.json new file mode 100644 index 0000000..b2d519d --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/Internal/Code Analysis/stylecop.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "indentation": { + "useTabs": true, + "tabSize": 4 + }, + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_2/QAction_2.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_2/QAction_2.cs new file mode 100644 index 0000000..a25b12f --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_2/QAction_2.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +using Skyline.DataMiner.Scripting; + +/// +/// DataMiner QAction Class: After Startup. +/// +public static class QAction +{ + /// + /// The QAction entry point. + /// + /// Link with SLProtocol process. + public static void Run(SLProtocol protocol) + { + try + { + + } + catch (Exception ex) + { + protocol.Log($"QA{protocol.QActionID}|{protocol.GetTriggerParameter()}|Run|Exception thrown:{Environment.NewLine}{ex}", LogType.Error, LogLevel.NoLogging); + } + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_2/QAction_2.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_2/QAction_2.csproj new file mode 100644 index 0000000..28172a6 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_2/QAction_2.csproj @@ -0,0 +1,20 @@ + + + net48 + Skyline Communications + © Skyline Communications + True + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_Helper/Directory.Build.props b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_Helper/Directory.Build.props new file mode 100644 index 0000000..60bd6c1 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_Helper/Directory.Build.props @@ -0,0 +1,5 @@ + + + x86 + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_Helper/QAction_Helper.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_Helper/QAction_Helper.cs new file mode 100644 index 0000000..9f7efe0 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_Helper/QAction_Helper.cs @@ -0,0 +1,38 @@ +// This is auto-generated code by DIS. Do not modify. +using System.ComponentModel; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Skyline.DataMiner.Scripting +{ +public static class Parameter +{ + public class Write + { + } +} +public class WriteParameters +{ + public SLProtocolExt Protocol; + public WriteParameters(SLProtocolExt protocol) + { + Protocol = protocol; + } +} +public interface SLProtocolExt : SLProtocol +{ + object Afterstartup_dummy { get; set; } + WriteParameters Write { get; set; } +} +public class ConcreteSLProtocolExt : ConcreteSLProtocol, SLProtocolExt +{ + /// PID: 2 | Type: dummy + public System.Object Afterstartup_dummy {get { return GetParameter(2); }set { SetParameter(2, value); }} + public WriteParameters Write { get; set; } + public ConcreteSLProtocolExt() + { + Write = new WriteParameters(this); + } +} +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_Helper/QAction_Helper.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_Helper/QAction_Helper.csproj new file mode 100644 index 0000000..9e697ba --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/QAction_Helper/QAction_Helper.csproj @@ -0,0 +1,21 @@ + + + net48 + Skyline Communications + © Skyline Communications + 0 + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/protocol.sln b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/protocol.sln new file mode 100644 index 0000000..0dc095f --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/protocol.sln @@ -0,0 +1,72 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33502.453 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{AFFAB0B4-ADBE-4678-83A7-431B9D259E0D}" + ProjectSection(SolutionItems) = preProject + Internal\.editorconfig = Internal\.editorconfig + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QActions", "QActions", "{9DB1E2EC-F575-479D-AFDF-D9A72E22145A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{41343ECD-5C88-49A3-905D-FC1F24C3EFC6}" + ProjectSection(SolutionItems) = preProject + Dlls\ABOUT.md = Dlls\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DefaultTemplates", "DefaultTemplates", "{F2683535-3B81-4454-9E99-120E5016BBCE}" + ProjectSection(SolutionItems) = preProject + DefaultTemplates\ABOUT.md = DefaultTemplates\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{791FA0C3-E691-4665-B01C-BCC3E296E58D}" + ProjectSection(SolutionItems) = preProject + Documentation\ABOUT.md = Documentation\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ECB3E466-EA84-4A9B-80CF-2AAFD7C59525}" + ProjectSection(SolutionItems) = preProject + protocol.xml = protocol.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D9DACB40-405B-41C9-8AB9-035344C5485B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{C6502079-007F-40F4-B435-7395410F5D02}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\qaction-debug.ruleset = Internal\Code Analysis\qaction-debug.ruleset + Internal\Code Analysis\qaction-release.ruleset = Internal\Code Analysis\qaction-release.ruleset + Internal\Code Analysis\stylecop.json = Internal\Code Analysis\stylecop.json + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QAction_Helper", "QAction_Helper\QAction_Helper.csproj", "{46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QAction_2", "QAction_2\QAction_2.csproj", "{EC10A547-508B-44BD-8146-72A3BC06E0F6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Release|Any CPU.Build.0 = Release|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C6502079-007F-40F4-B435-7395410F5D02} = {AFFAB0B4-ADBE-4678-83A7-431B9D259E0D} + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C} = {AFFAB0B4-ADBE-4678-83A7-431B9D259E0D} + {EC10A547-508B-44BD-8146-72A3BC06E0F6} = {9DB1E2EC-F575-479D-AFDF-D9A72E22145A} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {25C201FA-8CE6-4789-B8EB-E99CC4EE1AA3} + EndGlobalSection +EndGlobal diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/protocol.xml b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/protocol.xml new file mode 100644 index 0000000..0aa6aba --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution2/protocol.xml @@ -0,0 +1,169 @@ + + + + + natsconnectortest + natsconnectortest DataMiner connector + 1.0.0.1 + DMS-DRV- + Skyline Communications + + 1.3.6.1.4.1.8813.2. + + auto + + virtual + + + + true + 10.2.0.0 - 12603 + + + + + AfterStartup + After Startup + dummy + + + + + + + + + + After Startup + After Startup + poll action + + 2 + + + + + + + After Startup + protocol + + action + + 1 + + + + + + + After Startup Group + group + execute next + + + After Startup QAction + parameter + run actions + + + + + + Fast Timer (10s) + + 75 + + + + + Medium Timer (1m) + + 75 + + + + + Slow Timer (1h) + + 75 + + + + + + + + + + + + Main Branch + + + + + + + 2025-01-03 + + XXX + Skyline Communications + + + Initial version + + + + + + + + + + + + diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/DefaultTemplates/ABOUT.md b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/DefaultTemplates/ABOUT.md new file mode 100644 index 0000000..8041bec --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/DefaultTemplates/ABOUT.md @@ -0,0 +1,5 @@ +This folder contains default templates to be used by the protocol. +Allowed names: +"Template_Alarm_Default.xml" +"Trending_Template_Default.xml" +"Information_Template_Default.xml" diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Directory.Build.props b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Directory.Build.props new file mode 100644 index 0000000..4cb446b --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Directory.Build.props @@ -0,0 +1,31 @@ + + + x86 + true + + + $(DefineConstants);DCFv1;DBInfo;ALARM_SQUASHING + + + full + ..\Internal\Code Analysis\qaction-debug.ruleset + + + pdbonly + ..\Internal\Code Analysis\qaction-release.ruleset + + + + Properties\stylecop.json + + + Properties\.editorconfig + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Directory.Build.targets b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Directory.Build.targets new file mode 100644 index 0000000..6de23bf --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Directory.Build.targets @@ -0,0 +1,5 @@ + + + $(AssemblySearchPaths);$(ReferencePath) + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Dlls/ABOUT.md b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Dlls/ABOUT.md new file mode 100644 index 0000000..a3170b3 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Dlls/ABOUT.md @@ -0,0 +1 @@ +This folder contains DLL files that should be placed under the ProtocolScripts folder of DataMiner for this solution to work correctly. \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Documentation/ABOUT.md b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Documentation/ABOUT.md new file mode 100644 index 0000000..a150545 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Documentation/ABOUT.md @@ -0,0 +1 @@ +Looking for README.md? Check your Solution Root folder. This folder can be used to add documentation related to this solution. \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/.editorconfig b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/Code Analysis/qaction-debug.ruleset b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/Code Analysis/qaction-debug.ruleset new file mode 100644 index 0000000..26e7d46 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/Code Analysis/qaction-debug.ruleset @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/Code Analysis/qaction-release.ruleset b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/Code Analysis/qaction-release.ruleset new file mode 100644 index 0000000..de0890a --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/Code Analysis/qaction-release.ruleset @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/Code Analysis/stylecop.json b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/Code Analysis/stylecop.json new file mode 100644 index 0000000..b2d519d --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/Internal/Code Analysis/stylecop.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "indentation": { + "useTabs": true, + "tabSize": 4 + }, + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_2/QAction_2.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_2/QAction_2.cs new file mode 100644 index 0000000..a25b12f --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_2/QAction_2.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +using Skyline.DataMiner.Scripting; + +/// +/// DataMiner QAction Class: After Startup. +/// +public static class QAction +{ + /// + /// The QAction entry point. + /// + /// Link with SLProtocol process. + public static void Run(SLProtocol protocol) + { + try + { + + } + catch (Exception ex) + { + protocol.Log($"QA{protocol.QActionID}|{protocol.GetTriggerParameter()}|Run|Exception thrown:{Environment.NewLine}{ex}", LogType.Error, LogLevel.NoLogging); + } + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_2/QAction_2.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_2/QAction_2.csproj new file mode 100644 index 0000000..2af835e --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_2/QAction_2.csproj @@ -0,0 +1,20 @@ + + + net48 + Skyline Communications + © Skyline Communications + True + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_Helper/Directory.Build.props b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_Helper/Directory.Build.props new file mode 100644 index 0000000..60bd6c1 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_Helper/Directory.Build.props @@ -0,0 +1,5 @@ + + + x86 + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_Helper/QAction_Helper.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_Helper/QAction_Helper.cs new file mode 100644 index 0000000..9f7efe0 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_Helper/QAction_Helper.cs @@ -0,0 +1,38 @@ +// This is auto-generated code by DIS. Do not modify. +using System.ComponentModel; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Skyline.DataMiner.Scripting +{ +public static class Parameter +{ + public class Write + { + } +} +public class WriteParameters +{ + public SLProtocolExt Protocol; + public WriteParameters(SLProtocolExt protocol) + { + Protocol = protocol; + } +} +public interface SLProtocolExt : SLProtocol +{ + object Afterstartup_dummy { get; set; } + WriteParameters Write { get; set; } +} +public class ConcreteSLProtocolExt : ConcreteSLProtocol, SLProtocolExt +{ + /// PID: 2 | Type: dummy + public System.Object Afterstartup_dummy {get { return GetParameter(2); }set { SetParameter(2, value); }} + public WriteParameters Write { get; set; } + public ConcreteSLProtocolExt() + { + Write = new WriteParameters(this); + } +} +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_Helper/QAction_Helper.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_Helper/QAction_Helper.csproj new file mode 100644 index 0000000..9e697ba --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/QAction_Helper/QAction_Helper.csproj @@ -0,0 +1,21 @@ + + + net48 + Skyline Communications + © Skyline Communications + 0 + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/protocol.sln b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/protocol.sln new file mode 100644 index 0000000..0dc095f --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/protocol.sln @@ -0,0 +1,72 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33502.453 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{AFFAB0B4-ADBE-4678-83A7-431B9D259E0D}" + ProjectSection(SolutionItems) = preProject + Internal\.editorconfig = Internal\.editorconfig + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QActions", "QActions", "{9DB1E2EC-F575-479D-AFDF-D9A72E22145A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{41343ECD-5C88-49A3-905D-FC1F24C3EFC6}" + ProjectSection(SolutionItems) = preProject + Dlls\ABOUT.md = Dlls\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DefaultTemplates", "DefaultTemplates", "{F2683535-3B81-4454-9E99-120E5016BBCE}" + ProjectSection(SolutionItems) = preProject + DefaultTemplates\ABOUT.md = DefaultTemplates\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{791FA0C3-E691-4665-B01C-BCC3E296E58D}" + ProjectSection(SolutionItems) = preProject + Documentation\ABOUT.md = Documentation\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ECB3E466-EA84-4A9B-80CF-2AAFD7C59525}" + ProjectSection(SolutionItems) = preProject + protocol.xml = protocol.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D9DACB40-405B-41C9-8AB9-035344C5485B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{C6502079-007F-40F4-B435-7395410F5D02}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\qaction-debug.ruleset = Internal\Code Analysis\qaction-debug.ruleset + Internal\Code Analysis\qaction-release.ruleset = Internal\Code Analysis\qaction-release.ruleset + Internal\Code Analysis\stylecop.json = Internal\Code Analysis\stylecop.json + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QAction_Helper", "QAction_Helper\QAction_Helper.csproj", "{46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QAction_2", "QAction_2\QAction_2.csproj", "{EC10A547-508B-44BD-8146-72A3BC06E0F6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Release|Any CPU.Build.0 = Release|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C6502079-007F-40F4-B435-7395410F5D02} = {AFFAB0B4-ADBE-4678-83A7-431B9D259E0D} + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C} = {AFFAB0B4-ADBE-4678-83A7-431B9D259E0D} + {EC10A547-508B-44BD-8146-72A3BC06E0F6} = {9DB1E2EC-F575-479D-AFDF-D9A72E22145A} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {25C201FA-8CE6-4789-B8EB-E99CC4EE1AA3} + EndGlobalSection +EndGlobal diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/protocol.xml b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/protocol.xml new file mode 100644 index 0000000..0aa6aba --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution3/protocol.xml @@ -0,0 +1,169 @@ + + + + + natsconnectortest + natsconnectortest DataMiner connector + 1.0.0.1 + DMS-DRV- + Skyline Communications + + 1.3.6.1.4.1.8813.2. + + auto + + virtual + + + + true + 10.2.0.0 - 12603 + + + + + AfterStartup + After Startup + dummy + + + + + + + + + + After Startup + After Startup + poll action + + 2 + + + + + + + After Startup + protocol + + action + + 1 + + + + + + + After Startup Group + group + execute next + + + After Startup QAction + parameter + run actions + + + + + + Fast Timer (10s) + + 75 + + + + + Medium Timer (1m) + + 75 + + + + + Slow Timer (1h) + + 75 + + + + + + + + + + + + Main Branch + + + + + + + 2025-01-03 + + XXX + Skyline Communications + + + Initial version + + + + + + + + + + + + diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/DefaultTemplates/ABOUT.md b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/DefaultTemplates/ABOUT.md new file mode 100644 index 0000000..8041bec --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/DefaultTemplates/ABOUT.md @@ -0,0 +1,5 @@ +This folder contains default templates to be used by the protocol. +Allowed names: +"Template_Alarm_Default.xml" +"Trending_Template_Default.xml" +"Information_Template_Default.xml" diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Directory.Build.props b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Directory.Build.props new file mode 100644 index 0000000..4cb446b --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Directory.Build.props @@ -0,0 +1,31 @@ + + + x86 + true + + + $(DefineConstants);DCFv1;DBInfo;ALARM_SQUASHING + + + full + ..\Internal\Code Analysis\qaction-debug.ruleset + + + pdbonly + ..\Internal\Code Analysis\qaction-release.ruleset + + + + Properties\stylecop.json + + + Properties\.editorconfig + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Directory.Build.targets b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Directory.Build.targets new file mode 100644 index 0000000..6de23bf --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Directory.Build.targets @@ -0,0 +1,5 @@ + + + $(AssemblySearchPaths);$(ReferencePath) + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Dlls/ABOUT.md b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Dlls/ABOUT.md new file mode 100644 index 0000000..a3170b3 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Dlls/ABOUT.md @@ -0,0 +1 @@ +This folder contains DLL files that should be placed under the ProtocolScripts folder of DataMiner for this solution to work correctly. \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Documentation/ABOUT.md b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Documentation/ABOUT.md new file mode 100644 index 0000000..a150545 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Documentation/ABOUT.md @@ -0,0 +1 @@ +Looking for README.md? Check your Solution Root folder. This folder can be used to add documentation related to this solution. \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/.editorconfig b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/Code Analysis/qaction-debug.ruleset b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/Code Analysis/qaction-debug.ruleset new file mode 100644 index 0000000..26e7d46 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/Code Analysis/qaction-debug.ruleset @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/Code Analysis/qaction-release.ruleset b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/Code Analysis/qaction-release.ruleset new file mode 100644 index 0000000..de0890a --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/Code Analysis/qaction-release.ruleset @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/Code Analysis/stylecop.json b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/Code Analysis/stylecop.json new file mode 100644 index 0000000..b2d519d --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/Internal/Code Analysis/stylecop.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "indentation": { + "useTabs": true, + "tabSize": 4 + }, + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_2/QAction_2.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_2/QAction_2.cs new file mode 100644 index 0000000..a25b12f --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_2/QAction_2.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +using Skyline.DataMiner.Scripting; + +/// +/// DataMiner QAction Class: After Startup. +/// +public static class QAction +{ + /// + /// The QAction entry point. + /// + /// Link with SLProtocol process. + public static void Run(SLProtocol protocol) + { + try + { + + } + catch (Exception ex) + { + protocol.Log($"QA{protocol.QActionID}|{protocol.GetTriggerParameter()}|Run|Exception thrown:{Environment.NewLine}{ex}", LogType.Error, LogLevel.NoLogging); + } + } +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_2/QAction_2.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_2/QAction_2.csproj new file mode 100644 index 0000000..17b6fa2 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_2/QAction_2.csproj @@ -0,0 +1,20 @@ + + + net48 + Skyline Communications + © Skyline Communications + True + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_Helper/Directory.Build.props b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_Helper/Directory.Build.props new file mode 100644 index 0000000..60bd6c1 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_Helper/Directory.Build.props @@ -0,0 +1,5 @@ + + + x86 + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_Helper/QAction_Helper.cs b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_Helper/QAction_Helper.cs new file mode 100644 index 0000000..9f7efe0 --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_Helper/QAction_Helper.cs @@ -0,0 +1,38 @@ +// This is auto-generated code by DIS. Do not modify. +using System.ComponentModel; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Skyline.DataMiner.Scripting +{ +public static class Parameter +{ + public class Write + { + } +} +public class WriteParameters +{ + public SLProtocolExt Protocol; + public WriteParameters(SLProtocolExt protocol) + { + Protocol = protocol; + } +} +public interface SLProtocolExt : SLProtocol +{ + object Afterstartup_dummy { get; set; } + WriteParameters Write { get; set; } +} +public class ConcreteSLProtocolExt : ConcreteSLProtocol, SLProtocolExt +{ + /// PID: 2 | Type: dummy + public System.Object Afterstartup_dummy {get { return GetParameter(2); }set { SetParameter(2, value); }} + public WriteParameters Write { get; set; } + public ConcreteSLProtocolExt() + { + Write = new WriteParameters(this); + } +} +} diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_Helper/QAction_Helper.csproj b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_Helper/QAction_Helper.csproj new file mode 100644 index 0000000..9e697ba --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/QAction_Helper/QAction_Helper.csproj @@ -0,0 +1,21 @@ + + + net48 + Skyline Communications + © Skyline Communications + 0 + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + \ No newline at end of file diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/protocol.sln b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/protocol.sln new file mode 100644 index 0000000..0dc095f --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/protocol.sln @@ -0,0 +1,72 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33502.453 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{AFFAB0B4-ADBE-4678-83A7-431B9D259E0D}" + ProjectSection(SolutionItems) = preProject + Internal\.editorconfig = Internal\.editorconfig + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QActions", "QActions", "{9DB1E2EC-F575-479D-AFDF-D9A72E22145A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{41343ECD-5C88-49A3-905D-FC1F24C3EFC6}" + ProjectSection(SolutionItems) = preProject + Dlls\ABOUT.md = Dlls\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DefaultTemplates", "DefaultTemplates", "{F2683535-3B81-4454-9E99-120E5016BBCE}" + ProjectSection(SolutionItems) = preProject + DefaultTemplates\ABOUT.md = DefaultTemplates\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{791FA0C3-E691-4665-B01C-BCC3E296E58D}" + ProjectSection(SolutionItems) = preProject + Documentation\ABOUT.md = Documentation\ABOUT.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ECB3E466-EA84-4A9B-80CF-2AAFD7C59525}" + ProjectSection(SolutionItems) = preProject + protocol.xml = protocol.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D9DACB40-405B-41C9-8AB9-035344C5485B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{C6502079-007F-40F4-B435-7395410F5D02}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\qaction-debug.ruleset = Internal\Code Analysis\qaction-debug.ruleset + Internal\Code Analysis\qaction-release.ruleset = Internal\Code Analysis\qaction-release.ruleset + Internal\Code Analysis\stylecop.json = Internal\Code Analysis\stylecop.json + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QAction_Helper", "QAction_Helper\QAction_Helper.csproj", "{46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QAction_2", "QAction_2\QAction_2.csproj", "{EC10A547-508B-44BD-8146-72A3BC06E0F6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C}.Release|Any CPU.Build.0 = Release|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EC10A547-508B-44BD-8146-72A3BC06E0F6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C6502079-007F-40F4-B435-7395410F5D02} = {AFFAB0B4-ADBE-4678-83A7-431B9D259E0D} + {46E09E96-CAAD-43DC-A5ED-1E2FDB4C217C} = {AFFAB0B4-ADBE-4678-83A7-431B9D259E0D} + {EC10A547-508B-44BD-8146-72A3BC06E0F6} = {9DB1E2EC-F575-479D-AFDF-D9A72E22145A} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {25C201FA-8CE6-4789-B8EB-E99CC4EE1AA3} + EndGlobalSection +EndGlobal diff --git a/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/protocol.xml b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/protocol.xml new file mode 100644 index 0000000..0aa6aba --- /dev/null +++ b/Assemblers.ProtocolTests/TestFiles/Solutions/Solution4/protocol.xml @@ -0,0 +1,169 @@ + + + + + natsconnectortest + natsconnectortest DataMiner connector + 1.0.0.1 + DMS-DRV- + Skyline Communications + + 1.3.6.1.4.1.8813.2. + + auto + + virtual + + + + true + 10.2.0.0 - 12603 + + + + + AfterStartup + After Startup + dummy + + + + + + + + + + After Startup + After Startup + poll action + + 2 + + + + + + + After Startup + protocol + + action + + 1 + + + + + + + After Startup Group + group + execute next + + + After Startup QAction + parameter + run actions + + + + + + Fast Timer (10s) + + 75 + + + + + Medium Timer (1m) + + 75 + + + + + Slow Timer (1h) + + 75 + + + + + + + + + + + + Main Branch + + + + + + + 2025-01-03 + + XXX + Skyline Communications + + + Initial version + + + + + + + + + + + + diff --git a/DMApp.Automation/AppPackageCreatorForAutomation.cs b/DMApp.Automation/AppPackageCreatorForAutomation.cs index e2aabe9..33924be 100644 --- a/DMApp.Automation/AppPackageCreatorForAutomation.cs +++ b/DMApp.Automation/AppPackageCreatorForAutomation.cs @@ -35,7 +35,7 @@ private AppPackageCreatorForAutomation(IFileSystem fileSystem, ILogCollector log /// The package builder to which the items should be added to. /// The package creator. /// is . - /// No solution (.sln) file was detected or multiple solutions were detected. + /// No solution (.sln or .slnx) file was detected or multiple solutions were detected. public override async Task AddItemsAsync(AppPackage.AppPackageBuilder appPackageBuilder) { if (appPackageBuilder == null) @@ -44,12 +44,14 @@ public override async Task AddItemsAsync(AppPackage.AppPackageBuilder appPackage } LogCollector.ReportStatus("Using Workspace: " + RepositoryPath); - string[] files = FileSystem.Directory.GetFiles(RepositoryPath, "*.sln", SearchOption.TopDirectoryOnly); + string[] files = FileSystem.Directory.GetFiles(RepositoryPath, "*.sln", SearchOption.TopDirectoryOnly) + .Concat(FileSystem.Directory.GetFiles(RepositoryPath, "*.slnx", SearchOption.AllDirectories)) + .ToArray(); if (files.Length == 0) - throw new InvalidOperationException("No solution file (.sln) detected in " + RepositoryPath + "."); + throw new InvalidOperationException("No solution file (.sln or .slnx) detected in " + RepositoryPath + "."); if (files.Length > 1) - throw new InvalidOperationException("More than one solution file (.sln) detected in " + RepositoryPath + "."); + throw new InvalidOperationException("More than one solution file (.sln or .slnx) detected in " + RepositoryPath + "."); HashSet namesOfScriptsToInclude = null; diff --git a/DMApp.Automation/DMApp.Automation.csproj b/DMApp.Automation/DMApp.Automation.csproj index 034078e..ffc2b9c 100644 --- a/DMApp.Automation/DMApp.Automation.csproj +++ b/DMApp.Automation/DMApp.Automation.csproj @@ -29,10 +29,7 @@ - - - - + diff --git a/DMApp.AutomationTests/AppPackageCreatorForAutomationTests.cs b/DMApp.AutomationTests/AppPackageCreatorForAutomationTests.cs index 2e1e176..6f32e55 100644 --- a/DMApp.AutomationTests/AppPackageCreatorForAutomationTests.cs +++ b/DMApp.AutomationTests/AppPackageCreatorForAutomationTests.cs @@ -30,7 +30,7 @@ public async Task AddItemsAsync_ExpectedArgumentNullException() Task Act() => creator.AddItemsAsync(null); // Assert - await Assert.ThrowsExceptionAsync(Act); + await Assert.ThrowsAsync(Act); } } } \ No newline at end of file diff --git a/DMApp.AutomationTests/AssemblyInitialize.cs b/DMApp.AutomationTests/AssemblyInitialize.cs deleted file mode 100644 index 655549f..0000000 --- a/DMApp.AutomationTests/AssemblyInitialize.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace DMApp.AutomationTests -{ - using System.IO; - using System.IO.Compression; - using System.Reflection; - - using Microsoft.VisualStudio.TestTools.UnitTesting; - - [TestClass] - public class AssemblyInitialize - { - [AssemblyInitialize] - public static void AssemblyInit(TestContext context) - { - // This is needed because certain tools will look at all csproj files in the entire repository. - - var baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - - foreach (var zipFile in Directory.GetFiles(baseDir, "*.zip", SearchOption.AllDirectories)) - { - string dir = Path.Combine(Path.GetDirectoryName(zipFile), "TestFiles"); - - ZipFile.ExtractToDirectory(zipFile, dir); - } - } - - [AssemblyCleanup] - public static void AssemblyCleanup() - { - var baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - - foreach (var testFilesDirectories in Directory.GetDirectories(baseDir, "TestFiles", SearchOption.AllDirectories)) - { - Directory.Delete(testFilesDirectories, true); - } - } - } -} \ No newline at end of file diff --git a/DMApp.AutomationTests/DMApp.AutomationTests.csproj b/DMApp.AutomationTests/DMApp.AutomationTests.csproj index 11658e0..e23f151 100644 --- a/DMApp.AutomationTests/DMApp.AutomationTests.csproj +++ b/DMApp.AutomationTests/DMApp.AutomationTests.csproj @@ -1,4 +1,4 @@ - + net48;net8.0 @@ -8,7 +8,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -21,9 +21,13 @@ - - Always - + + + + + + PreserveNewest + diff --git a/DMApp.AutomationTests/FactoryTests.cs b/DMApp.AutomationTests/FactoryTests.cs index d490460..e11184b 100644 --- a/DMApp.AutomationTests/FactoryTests.cs +++ b/DMApp.AutomationTests/FactoryTests.cs @@ -75,7 +75,7 @@ public async Task FromRepositorySolution1ReturnsPackageWith2Scripts() var package = await creator.BuildPackageAsync(); // Assert. - Assert.AreEqual(2, package.AutomationScripts.Count); + Assert.HasCount(2, package.AutomationScripts); var scriptNames = package.AutomationScripts.Select(s => s.Name).ToList(); scriptNames.Should().BeEquivalentTo(new List { "Script_1", "Script_2" }); } @@ -93,7 +93,7 @@ public async Task FromRepositorySolution1WithSelectedScriptReturnsPackageWithSin var package = await creator.BuildPackageAsync(); // Assert. - Assert.AreEqual(1, package.AutomationScripts.Count); + Assert.HasCount(1, package.AutomationScripts); var scriptNames = package.AutomationScripts.Select(s => s.Name).ToList(); scriptNames.Should().Equal(new List { "Script_1" }); } @@ -144,7 +144,7 @@ public async Task FromRepositorySolution3WithSharedProject() string scriptContent = Encoding.UTF8.GetString(automationScript.ScriptContent); - Assert.IsTrue(scriptContent.Contains("public bool TestSharedCall()")); + Assert.Contains("public bool TestSharedCall()", scriptContent); } [TestMethod] @@ -162,7 +162,7 @@ public async Task FromRepositorySolution2WithCustomDllResultsInPackageWithCustom // Assert. var automationScript = package.AutomationScripts.FirstOrDefault(a => a.Name == "Script_1"); Assert.IsNotNull(automationScript); - Assert.AreEqual(1, automationScript.Assemblies.Count); + Assert.HasCount(1, automationScript.Assemblies); var includedAssembly = automationScript.Assemblies.FirstOrDefault(); Assert.IsNotNull(includedAssembly); diff --git a/DMApp.AutomationTests/TestFiles.zip b/DMApp.AutomationTests/TestFiles.zip deleted file mode 100644 index 04f37da..0000000 Binary files a/DMApp.AutomationTests/TestFiles.zip and /dev/null differ diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent.xml new file mode 100644 index 0000000..f1d1224 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent.xml @@ -0,0 +1,24 @@ + + + AddEvent + Script 1.0.1.77 + Automation + SKYLINE2\ThomasRE + FALSE + YLE/Customer UI + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate.xml new file mode 100644 index 0000000..eba8d50 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate.xml @@ -0,0 +1,28 @@ + + + AddEventFromTemplate + Script 1.0.1.77 + Automation + SKYLINE2\thomasre + FALSE + YLE/Customer UI + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/AddEventFromTemplate_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/AddEventFromTemplate_1.csproj new file mode 100644 index 0000000..97e815a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/AddEventFromTemplate_1.csproj @@ -0,0 +1,102 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {880203DF-F9E6-4888-9978-A2FBE22BD25A} + Library + Properties + AddEventFromTemplate_1 + AddEventFromTemplate_1 + v4.7.2 + 512 + + + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\AddEventFromTemplate_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\AddEventFromTemplate_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + 1.0.1.12 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7f2402d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("AddEventFromTemplate_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("AddEventFromTemplate_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("20BF2FA4-97FD-46BA-AAA4-9181E06A423C")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/Script.cs new file mode 100644 index 0000000..5dcfaf7 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/Script.cs @@ -0,0 +1,400 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +16/07/2021 1.0.0.1 TRE, Skyline Initial version +**************************************************************************** +*/ + +namespace AddEventFromTemplate_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Events; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.YLE.Integrations.Ceiton; + using Status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Status; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + public class Script : IDisposable + { + private InteractiveController app; + + private UserInfo userInfo; + private UseEventTemplateDialog useEventTemplateDialog; + private AddOrUpdateEventDialog eventDialog; + private EditTemplateDialog editTemplateDialog; + private AddEventTemplateDialog addEventTemplateDialog; + private Helpers helpers; + + private System.Threading.Tasks.Task scriptTask; + private int timeOutResult; + private bool disposedValue; + + /// + /// The Script entry point. + /// Engine.ShowUI(); + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + scriptTask = System.Threading.Tasks.Task.Factory.StartNew(() => + { + try + { + Initialize(engine); + + userInfo = helpers.ContractManager.GetUserInfo(engine.UserLoginName); + Dialog dialog; + if (userInfo.GetEventTemplates().Any()) + { + dialog = InitUseEventTemplateDialog(); + } + else + { + MessageDialog messageDialog = new MessageDialog(engine, "You don't have access to any Event Templates.") { Title = "No Templates Available" }; + messageDialog.OkButton.Pressed += (s, a) => engine.ExitSuccess("No Event Templates"); + + dialog = messageDialog; + } + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + catch (ScriptAbortException) + { + // Do nothing + } + catch (InteractiveUserDetachedException) + { + // Do nothing + } + catch (Exception e) + { + if (timeOutResult != -1) + { + helpers.Log(nameof(Script), nameof(Run), "Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + } + finally + { + Dispose(); + } + }); + + timeOutResult = System.Threading.Tasks.Task.WaitAny(new[] { scriptTask }, new TimeSpan(9, 59, 40)); + } + + private Dialog InitUseEventTemplateDialog() + { + var eventTemplates = new List(); + foreach (string templateName in userInfo.GetEventTemplates()) + { + if (!helpers.ContractManager.TryGetEventTemplate(templateName, out EventTemplate template)) + { + helpers.Log(nameof(Script), nameof(InitUseEventTemplateDialog), $"Unable to retrieve Event Template: {templateName}"); + continue; + } + + eventTemplates.Add(template); + } + + useEventTemplateDialog = new UseEventTemplateDialog(helpers, eventTemplates, userInfo); + useEventTemplateDialog.ContinueButton.Pressed += UseEventTemplateButton_Pressed; + useEventTemplateDialog.EditSelectedTemplateButton.Pressed += (o, e) => EditTemplate(); + + return useEventTemplateDialog; + } + + private void Initialize(Engine engine) + { + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.SetFlag(RunTimeFlags.NoInformationEvents); + engine.Timeout = TimeSpan.FromHours(10); + + helpers = new Helpers(engine, Scripts.AddEventFromTemplate); + + app = new InteractiveController(engine); + } + + private void UseEventTemplateButton_Pressed(object sender, EventArgs e) + { + if (!useEventTemplateDialog.IsValid) return; + + try + { + if (useEventTemplateDialog.EventSubType == EventSubType.Normal) + { + var @event = useEventTemplateDialog.SelectedEvent; + @event.Start = new[] { useEventTemplateDialog.StartTime, @event.Start }.Min(); + @event.End = new[] { useEventTemplateDialog.EndTime, @event.End }.Max(); + + LockInfo lockInfo = new LockInfo(true, String.Empty, Guid.Empty.ToString(), TimeSpan.Zero); + eventDialog = new AddOrUpdateEventDialog(helpers, userInfo, @event, lockInfo); + eventDialog.SaveAsTemplateButton.Text = "Edit Template"; + eventDialog.SavePreliminaryEventButton.Pressed += (s, a) => SaveEvent(Status.Preliminary); + eventDialog.SavePlannedEventButton.Pressed += (s, a) => SaveEvent(Status.Planned); + eventDialog.SaveButton.Pressed += (s, a) => SaveEvent(Status.Confirmed); + eventDialog.SaveAsTemplateButton.Pressed += (s, a) => EditTemplate(); + + app.ShowDialog(eventDialog); + } + else + { + SaveEvent(Status.Planned); + } + } + catch(Exception ex) + { + helpers.Log(nameof(Script), nameof(UseEventTemplateButton_Pressed), $"Exception occurred: {ex}"); + throw; + } + } + + private void SaveEvent(Status status) + { + try + { + Event eventInfo = null; + + if (eventDialog != null) + { + if (!eventDialog.IsValid()) return; + + eventInfo = eventDialog.GetUpdatedEvent(); + } + else if (useEventTemplateDialog != null) + { + if (!useEventTemplateDialog.IsValid) return; + + eventInfo = useEventTemplateDialog.SelectedEvent; + } + else + { + return; + } + + var progressDialog = new ProgressDialog(helpers.Engine) { Title = "Saving New Event" }; + progressDialog.OkButton.Pressed += (send, args) => helpers.Engine.ExitSuccess(eventInfo.Id.ToString()); + + app.ShowDialog(progressDialog); + + eventInfo.Status = status; + helpers.EventManager.AddOrUpdateEvent(eventInfo); + + // If a project number is defined, the project should be polled from Ceiton. + // If Ceiton has any information, the Ceiton Integration will update this Event. + if (!string.IsNullOrWhiteSpace(eventInfo.ProjectNumber)) + { + var orderManagerElement = new OrderManagerElement(helpers); + var ceiton = new CeitonElement(orderManagerElement.CeitonElement); + ceiton.PollProject(eventInfo.ProjectNumber); + } + + AddOrUpdateLinkedOrders(status, eventInfo, progressDialog); + + progressDialog.Finish(); + app.ShowDialog(progressDialog); + } + catch (Exception exception) + { + ShowExceptionDialog((Engine)helpers.Engine, exception); + } + } + + private void AddOrUpdateLinkedOrders(Status status, Event eventInfo, ProgressDialog progressDialog) + { + var linkedOrders = useEventTemplateDialog.SelectedTemplateLinkedOrders.Any() ? useEventTemplateDialog.SelectedTemplateLinkedOrders : useEventTemplateDialog.CreateLinkedOrders(eventInfo); + foreach (var order in linkedOrders) + { + helpers.ProgressReported += (send, args) => progressDialog.AddProgressLine(args.Progress); + + order.Event = eventInfo; + order.Company = eventInfo.Company; + order.Contract = eventInfo.Contract; + order.IsInternal = eventInfo.IsInternal; + order.Status = useEventTemplateDialog.DetermineOrderStatus(order, status); + order.AddOrUpdate(helpers, userInfo.IsMcrUser); + } + } + + private void EditTemplate() + { + Event @event = null; + Dialog dialogLinkToBackButton = null; + if (useEventTemplateDialog.EventSubType == EventSubType.Normal) + { + if (!eventDialog.IsValid()) return; + + @event = eventDialog.GetUpdatedEvent(); + dialogLinkToBackButton = eventDialog; + } + else + { + @event = useEventTemplateDialog.SelectedEvent; + dialogLinkToBackButton = useEventTemplateDialog; + } + + editTemplateDialog = new EditTemplateDialog((Engine)helpers.Engine); + editTemplateDialog.BackButton.Pressed += (s, a) => app.ShowDialog(dialogLinkToBackButton); + editTemplateDialog.CreateNewTemplateButton.Pressed += (s, a) => CreateNewTemplate(@event); + editTemplateDialog.UpdateTemplateButton.Pressed += (s, a) => UpdateTemplate(@event, useEventTemplateDialog.SelectedTemplate); + editTemplateDialog.DeleteTemplateButton.Pressed += (s, a) => DeleteTemplate(useEventTemplateDialog.SelectedTemplate); + + app.ShowDialog(editTemplateDialog); + } + + private void CreateNewTemplate(Event @event) + { + addEventTemplateDialog = new AddEventTemplateDialog(helpers, @event, userInfo); + addEventTemplateDialog.BackButton.Pressed += (s, args) => app.ShowDialog(editTemplateDialog); + addEventTemplateDialog.SaveTemplateButton.Pressed += (s, args) => SaveNewEventTemplate(@event, addEventTemplateDialog.TemplateName, addEventTemplateDialog.SelectedUserGroups.ToArray()); + + app.ShowDialog(addEventTemplateDialog); + } + + private void SaveNewEventTemplate(Event @event, string templateName, string[] userGroups) + { + if (!addEventTemplateDialog.IsValid) return; + + MessageDialog messageDialog; + if (helpers.ContractManager.TryAddEventTemplate(templateName, userGroups, @event, new Order[0])) + { + messageDialog = new MessageDialog(helpers.Engine, "The template was successfully saved"); + } + else + { + messageDialog = new MessageDialog(helpers.Engine, "Unable to save the template"); + } + + messageDialog.OkButton.Pressed += (s, args) => helpers.Engine.ExitSuccess("OK"); + app.ShowDialog(messageDialog); + } + + private void UpdateTemplate(Event @event, EventTemplate selectedTemplate) + { + addEventTemplateDialog = new AddEventTemplateDialog(helpers, @event, userInfo); + List linkedOrderTemplates = helpers.ContractManager.GetLinkedOrderTemplates(selectedTemplate.Id); + addEventTemplateDialog.Init(selectedTemplate, linkedOrderTemplates, userInfo); + + addEventTemplateDialog.BackButton.Pressed += (s, args) => app.ShowDialog(editTemplateDialog); + addEventTemplateDialog.SaveTemplateButton.Pressed += (s, args) => SaveUpdatedEventTemplate(@event, selectedTemplate, addEventTemplateDialog.TemplateName, addEventTemplateDialog.SelectedUserGroups.ToArray(), addEventTemplateDialog.GetLinkedOrderTemplatesToKeep(), addEventTemplateDialog.NewOrderTemplates, addEventTemplateDialog.NewOrderTemplateOffsets); + + app.ShowDialog(addEventTemplateDialog); + } + + private void SaveUpdatedEventTemplate(Event @event, EventTemplate selectedTemplate, string templateName, string[] userGroups, IReadOnlyList linkedOrderTemplatesToKeep, IReadOnlyList newOrderTemplates, Dictionary newOrderTemplateOffsets) + { + if (!addEventTemplateDialog.IsValid) return; + + MessageDialog messageDialog; + if (helpers.ContractManager.TryEditEventTemplate(@event, selectedTemplate, templateName, userGroups, linkedOrderTemplatesToKeep, newOrderTemplates, newOrderTemplateOffsets)) + { + messageDialog = new MessageDialog(helpers.Engine, "The template was successfully saved"); + } + else + { + messageDialog = new MessageDialog(helpers.Engine, "Unable to save the template"); + } + + messageDialog.OkButton.Pressed += (s, args) => helpers.Engine.ExitSuccess("OK"); + app.ShowDialog(messageDialog); + } + + private void DeleteTemplate(EventTemplate selectedTemplate) + { + MessageDialog messageDialog; + if (helpers.ContractManager.TryDeleteEventTemplate(selectedTemplate.Name)) + { + messageDialog = new MessageDialog(helpers.Engine, "The template was successfully removed"); + } + else + { + messageDialog = new MessageDialog(helpers.Engine, "Unable to remove the template"); + } + + messageDialog.OkButton.Pressed += (s, args) => helpers.Engine.ExitSuccess("OK"); + app.ShowDialog(messageDialog); + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong during the creation of the new event."); + if (app.IsRunning) app.ShowDialog(dialog); else app.Run(dialog); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/app.config new file mode 100644 index 0000000..a5d0f75 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/app.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEventFromTemplate_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/.editorconfig new file mode 100644 index 0000000..de5a35c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/.editorconfig @@ -0,0 +1,83 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true +csharp_indent_labels = one_less_than_current +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/AddEvent_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/AddEvent_2.csproj new file mode 100644 index 0000000..c9b5619 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/AddEvent_2.csproj @@ -0,0 +1,85 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {8EBFE2CE-07A1-45F6-85AC-8023014A0A8A} + Library + Properties + AddEvent_2 + AddEvent_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\AddEvent_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\AddEvent_2.xml + + + None + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + 1.0.1.12 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..51e9d17 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("AddEvent_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("AddEvent_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("9BD33446-3515-4DD2-9406-F4856BCCC669")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/Script.cs new file mode 100644 index 0000000..4bfc135 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/Script.cs @@ -0,0 +1,210 @@ +/* +**************************************************************************** +* Copyright (c) 2019, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2019 1.0.0.1 XXX, Skyline Initial Version +**************************************************************************** +*/ + +namespace AddEvent_2 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Timers; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.EventTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Events; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.LoadingScreens; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.Utils.YLE.Integrations.Ceiton; + using Status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Status; + using Task = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.Task; + + /// + /// DataMiner Script Class. + /// + public class Script : YleInteractiveScript + { + private LoadAddOrUpdateEventDialog loadAddOrUpdateEventDialog; + private AddOrUpdateEventDialog eventDialog; + private AddEventTemplateDialog addEventTemplateDialog; + + private readonly Timer extendLocksTimer = new Timer(); + + protected override Scripts ScriptName => Scripts.AddEvent; + + protected override TimeSpan? TimeOut => TimeSpan.FromHours(9); + + protected override void InternalRun() + { + loadAddOrUpdateEventDialog = new LoadAddOrUpdateEventDialog(helpers, extendLocksTimer); + + if (loadAddOrUpdateEventDialog.Execute()) ShowAddEventDialog(); + else app.Run(loadAddOrUpdateEventDialog); + } + + protected override void EngineShowUiInComments() + { + //engine.ShowUI() + } + + private void ShowAddEventDialog() + { + eventDialog = loadAddOrUpdateEventDialog.AddOrUpdateEventDialog; + eventDialog.SavePreliminaryEventButton.Pressed += (sender, args) => SaveEvent(Status.Preliminary); + eventDialog.SavePlannedEventButton.Pressed += (sender, args) => SaveEvent(Status.Planned); + eventDialog.SaveAsTemplateButton.Pressed += (sender, args) => ShowAddEventTemplateDialog(); + + if (app.IsRunning) app.ShowDialog(eventDialog); + else app.Run(eventDialog); + } + + private void SaveEvent(Status status) + { + try + { + if (!eventDialog.IsValid()) return; + + var eventInfo = eventDialog.GetUpdatedEvent(); + + var reportDialog = new AddOrUpdateReportDialog(helpers); + reportDialog.OkButton.Pressed += (o, args) => { helpers.LockManager.ReleaseLocks(); helpers.Engine.ExitSuccess("Successfully updated the service"); }; + app.ShowDialog(reportDialog); + + eventInfo.Status = status; + + List tasks = new List(); + var addOrUpdateEventTask = new AddOrUpdateEventTask(helpers, eventInfo); + tasks.Add(addOrUpdateEventTask); + + if (!addOrUpdateEventTask.Execute()) + { + helpers.Log(nameof(AddEvent_2.Script), nameof(SaveEvent), $"Add or update event task failed for event: {eventInfo.Name}"); + } + + // If a project number is defined, the project should be polled from Ceiton. + // If Ceiton has any information, the Ceiton Integration will update this Event. + if (!string.IsNullOrWhiteSpace(eventInfo.ProjectNumber)) + { + OrderManagerElement orderManagerElement = new OrderManagerElement(helpers); + var ceiton = new CeitonElement(orderManagerElement.CeitonElement); + ceiton.PollProject(eventInfo.ProjectNumber); + } + + reportDialog.Finish(tasks); + app.ShowDialog(reportDialog); + } + catch (Exception exception) + { + ShowExceptionDialog(exception); + } + } + + protected override void HandleException(Exception e) + { + ShowExceptionDialog(e); + } + + private void ShowAddEventTemplateDialog() + { + var @event = eventDialog.GetUpdatedEvent(); + var userInfo = loadAddOrUpdateEventDialog.UserInfo; + + addEventTemplateDialog = new AddEventTemplateDialog(helpers, @event, userInfo); + addEventTemplateDialog.BackButton.Pressed += (s, args) => app.ShowDialog(eventDialog); + addEventTemplateDialog.SaveTemplateButton.Pressed += (s, args) => SaveEventTemplate(); + + app.ShowDialog(addEventTemplateDialog); + } + + private void SaveEventTemplate() + { + if (!addEventTemplateDialog.IsValid) return; + + string templateName = addEventTemplateDialog.TemplateName; + string[] userGroups = addEventTemplateDialog.SelectedUserGroups.ToArray(); + Event @event = addEventTemplateDialog.Event; + + MessageDialog messageDialog; + if (helpers.ContractManager.TryAddEventTemplate(templateName, userGroups, @event, new Order[0])) + { + messageDialog = new MessageDialog(helpers.Engine, "The template was successfully saved"); + } + else + { + messageDialog = new MessageDialog(helpers.Engine, "Unable to save the template"); + } + + messageDialog.OkButton.Pressed += (s, args) => helpers.Engine.ExitSuccess("OK"); + app.ShowDialog(messageDialog); + } + + #region IDisposable Support + private bool isDisposed; + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (!isDisposed) + { + if (disposing) + { + extendLocksTimer.Dispose(); + } + + isDisposed = true; + } + } + #endregion + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddEvent_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote.xml new file mode 100644 index 0000000..d5a8b76 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote.xml @@ -0,0 +1,30 @@ + + AddNote + Script 1.0.1.77 + Automation + SKYLINE2\VSC + FALSE + YLE/Customer UI + + + + + + + + + + Page + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/AddNote_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/AddNote_2.csproj new file mode 100644 index 0000000..2b9e5b5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/AddNote_2.csproj @@ -0,0 +1,102 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {E5C344F3-4239-4F98-BF5B-642646B0A68A} + Library + Properties + AddNote_2 + AddNote_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\AddNote_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\AddNote_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1168f94 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("AddNote_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("AddNote_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("8CB3E2CB-7D6C-44B2-9F55-5E3B076B41C7")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/Script.cs new file mode 100644 index 0000000..73aaa55 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/Script.cs @@ -0,0 +1,168 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +03/02/2020 1.0.0.1 JVT, Skyline Initial version +**************************************************************************** +*/ + +namespace AddNote_2 +{ + using System; + using System.Threading.Tasks; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notes; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Notes; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + internal class Script : IDisposable + { + private Helpers helpers; + private InteractiveController app; + private AddOrUpdateNoteDialog dialog; + + private Task scriptTask; + private int timeOutResult; + private bool disposedValue; + + public void Run(Engine engine) + { + scriptTask = Task.Factory.StartNew(() => + { + try + { + string paramValue = engine.GetScriptParam(1).Value; + + var page = EnumExtensions.GetEnumValueFromDescription(paramValue); + + //engine.ShowUI(); + engine.Timeout = TimeSpan.FromHours(10); + helpers = new Helpers(engine, Scripts.AddNote); + this.app = new InteractiveController(engine); + + dialog = new AddOrUpdateNoteDialog(engine, page); + dialog.ConfirmButton.Pressed += Dialog_ConfirmButton_Pressed; + + app.Run(dialog); + } + catch (ScriptAbortException) + { + throw; + } + catch (Exception e) + { + if (timeOutResult != -1) + { + engine.Log("Run|Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + } + finally + { + helpers?.Dispose(); + } + }); + + timeOutResult = Task.WaitAny(new[] { scriptTask }, new TimeSpan(9, 59, 40)); + } + + private void Dialog_ConfirmButton_Pressed(object sender, EventArgs e) + { + var updatedNote = dialog.Note; + if (!TryCheckValidityAndUpdateNote(updatedNote)) return; + + ShowMessageDialog((Engine)helpers.Engine, "Successfully added note", "Add Note"); + } + + private bool TryCheckValidityAndUpdateNote(Note updatedNote) + { + if (!dialog.IsValid()) return false; + + helpers.NoteManager.AddOrUpdateNote(updatedNote, out string fullTicketId); + + return true; + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog exceptionDialog = new ExceptionDialog(engine, exception); + exceptionDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong during adding the Note."); + app.ShowDialog(exceptionDialog); + } + + private void ShowMessageDialog(Engine engine, string message, string title) + { + MessageDialog messageDialog = new MessageDialog(engine, message) { Title = title }; + messageDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess(message); + + if (app.IsRunning) app.ShowDialog(messageDialog); + else app.Run(messageDialog); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddNote_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder.xml new file mode 100644 index 0000000..6df676b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder.xml @@ -0,0 +1,30 @@ + + AddOrUpdateNonLiveOrder + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/Customer UI + + + + + + + + + + ticketId + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/AddOrUpdateNonLiveOrder_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/AddOrUpdateNonLiveOrder_2.csproj new file mode 100644 index 0000000..f1f1b39 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/AddOrUpdateNonLiveOrder_2.csproj @@ -0,0 +1,102 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {CD8CA3A7-2D4D-416A-BB82-76279B1843C2} + Library + Properties + AddOrUpdateNonLiveOrder_2 + AddOrUpdateNonLiveOrder_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\AddOrUpdateNonLiveOrder_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\AddOrUpdateNonLiveOrder_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3f6c9b6 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("AddOrUpdateNonLiveOrder_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("AddOrUpdateNonLiveOrder_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("87B4351F-CAE3-4BE2-82F4-97D9C3EDA5CA")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/Script.cs new file mode 100644 index 0000000..982a825 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/Script.cs @@ -0,0 +1,208 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +18/03/2021 1.0.0.1 TRE, Skyline Updated edit rights for Non-MCR users +06/04/2021 1.0.0.2 TRE, Skyline Allow multiple file selection. +**************************************************************************** +*/ + +namespace AddOrUpdateNonLiveOrder_2 +{ + using System; + using System.Threading.Tasks; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.LoadingScreens; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.NonLive; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + + internal class Script : IDisposable + { + private InteractiveController app; + + private LoadNonLiveOrderFormDialog loadNonLiveOrderFormDialog; + private MainDialog nonLiveOrderForm; + private NonLiveRejectionDialog rejectionDialog; + private Helpers helpers; + + private int timeOutResult; + private bool disposedValue; + + public void Run(Engine engine) + { + var scriptTask = Task.Factory.StartNew(() => + { + try + { + Initialize(engine); + + loadNonLiveOrderFormDialog = new LoadNonLiveOrderFormDialog(helpers, LoadNonLiveOrderFormDialog.ScriptAction.AddOrUpdate); + + if (loadNonLiveOrderFormDialog.Execute()) ShowNonLiveOrderForm(); + else app.Run(loadNonLiveOrderFormDialog); + } + catch (InteractiveUserDetachedException) + { + // Do Nothing + } + catch (ScriptAbortException) + { + // Do Nothing + } + catch (Exception e) + { + if (timeOutResult != -1) + { + helpers.Log(nameof(Script), nameof(Run), "Something went wrong: " + e); + ShowExceptionDialog(e); + } + } + finally + { + Dispose(); + } + }); + + timeOutResult = Task.WaitAny(new[] { scriptTask }, new TimeSpan(9, 59, 40)); + } + + private void Initialize(Engine engine) + { + engine.Timeout = TimeSpan.FromHours(10); + //engine.ShowUI(); + + helpers = new Helpers(engine, Scripts.AddOrUpdateNonLiveOrder); + app = new InteractiveController(engine); + } + + private void ShowNonLiveOrderForm() + { + nonLiveOrderForm = loadNonLiveOrderFormDialog.NonLiveOrderFormDialog; + nonLiveOrderForm.CancelButton.Pressed += Dialog_CancelButton_Pressed; + nonLiveOrderForm.BookOrSaveFinished += NonLiveOrderForm_BookOrSaveFinished; + nonLiveOrderForm.RejectOrderButton.Pressed += Dialog_RejectOrderButton_Pressed; + + if (app.IsRunning) app.ShowDialog(nonLiveOrderForm); + else app.Run(nonLiveOrderForm); + } + + private void NonLiveOrderForm_BookOrSaveFinished(object sender, Library_1.EventArguments.StringEventArgs e) + { + ShowMessageDialog(e.Value, "Add or Update Non-Live Order finished"); + } + + private void ShowExceptionDialog(Exception exception) + { + ExceptionDialog exceptionDialog = new ExceptionDialog((Engine)helpers.Engine, exception); + exceptionDialog.OkButton.Pressed += (sender, args) => helpers.Engine.ExitSuccess("Something went wrong during the creation of the new Order."); + if (app.IsRunning) app.ShowDialog(exceptionDialog); else app.Run(exceptionDialog); + } + + private void ShowMessageDialog(string message, string title) + { + MessageDialog dialog = new MessageDialog(helpers.Engine, message) { Title = title }; + dialog.OkButton.Pressed += (sender, args) => helpers.Engine.ExitSuccess(message); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + private void Dialog_CancelButton_Pressed(object sender, EventArgs e) + { + helpers.NonLiveOrderManager.CancelNonLiveOrder(nonLiveOrderForm.NonLiveOrder, loadNonLiveOrderFormDialog.UserInfo.User); + + ShowMessageDialog("Order successfully canceled", "Cancel Non Live Order"); + } + + private void Dialog_RejectOrderButton_Pressed(object sender, EventArgs e) + { + rejectionDialog = new NonLiveRejectionDialog(helpers.Engine); + rejectionDialog.CancelButton.Pressed += RejectionDialog_CancelButton_Pressed; + rejectionDialog.RejectButton.Pressed += RejectionDialog_RejectButton_Pressed; + + app.ShowDialog(rejectionDialog); + } + + private void RejectionDialog_RejectButton_Pressed(object sender, EventArgs e) + { + if (!rejectionDialog.IsValid()) return; + + rejectionDialog.UpdateNonLiveOrder(nonLiveOrderForm.NonLiveOrder); + + helpers.NonLiveOrderManager.SetNonLiveOrderToChangeRequested(nonLiveOrderForm.NonLiveOrder, loadNonLiveOrderFormDialog.UserInfo.User); + + ShowMessageDialog("Order successfully rejected", "Reject Non Live Order"); + } + + private void RejectionDialog_CancelButton_Pressed(object sender, EventArgs e) + { + app.ShowDialog(nonLiveOrderForm); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddOrUpdateNonLiveOrder_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService.xml new file mode 100644 index 0000000..0782020 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService.xml @@ -0,0 +1,32 @@ + + + AddService + Script 1.0.1.77 + Automation + SKYLINE2\VictorSC + FALSE + YLE/Customer UI + + + + + + + + + + ServiceId + + + Action + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/AddService_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/AddService_1.cs new file mode 100644 index 0000000..183c80d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/AddService_1.cs @@ -0,0 +1,308 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace AddService_1 +{ + + + using System; + using System.Linq; + using System.Timers; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Order.Dialogs; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + using TaskStatus = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.Status; + + /// + /// DataMiner Script Class. + /// + internal class Script : IDisposable + { + private readonly Timer extendLocksTimer = new Timer(); + + private Helpers helpers; + private InteractiveController app; + + private ReportDialog rollbackReportDialog; + private LoadAddServiceDialog loadEditOrderDialog; + private LiveOrderFormDialog editOrderDialog; + private ReportDialog reportDialog; + + private LiveOrderFormAction scriptAction; + private readonly string selectedOrderIdForExiting = Guid.Empty.ToString(); + private UserInfo userInfo; + + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + int timeOutResult = 0; + var scriptTask = System.Threading.Tasks.Task.Factory.StartNew(() => + { + try + { + Initialize(engine); + + loadEditOrderDialog = new LoadAddServiceDialog(helpers, extendLocksTimer); + + if (loadEditOrderDialog.Execute()) ShowDialog(); + else app.Run(loadEditOrderDialog); + } + catch (InteractiveUserDetachedException) + { + Dispose(); + } + catch (ScriptAbortException) + { + Dispose(); + throw; + } + catch (Exception e) + { + if (timeOutResult != -1) + { + helpers.Log(nameof(Script), nameof(Run), $"Something went wrong: {e}"); + + Dispose(); + + ShowExceptionDialog(engine, e); + } + } + }); + + timeOutResult = System.Threading.Tasks.Task.WaitAny(new System.Threading.Tasks.Task[] { scriptTask }, new TimeSpan(9, 59, 40)); + if (timeOutResult == -1) Dispose(); + } + + private void ShowDialog() + { + scriptAction = loadEditOrderDialog.ScriptAction; + userInfo = loadEditOrderDialog.UserInfo; + + editOrderDialog = loadEditOrderDialog.EditOrderDialog; + + editOrderDialog.BookOrderButton.Pressed += OrderForm_BookButton_Pressed; + editOrderDialog.ExitButton.Pressed += (s, e) => helpers.Engine.ExitSuccess("no changes"); + + app.Run(editOrderDialog); + } + + private void Initialize(Engine engine) + { + engine.SetFlag(RunTimeFlags.NoInformationEvents); + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.SetFlag(RunTimeFlags.NoCheckingSets); + engine.Timeout = TimeSpan.FromHours(10); + //engine.ShowUI(); + + helpers = new Helpers(engine, Scripts.AddService); + + app = new InteractiveController(engine); + } + + private void OrderForm_BookButton_Pressed(object sender, YleValueWidgetChangedEventArgs e) + { + helpers.LogMethodStart(nameof(Script), nameof(OrderForm_BookButton_Pressed), out var stopwatch); + + try + { + if (!editOrderDialog.IsValid(saveOrder: false, confirmOrder: false, requestEventLock: true)) + { + helpers.LogMethodCompleted(nameof(Script), nameof(OrderForm_BookButton_Pressed), null, stopwatch); + return; + } + + AddOrUpdateOrder(OrderAction.Book); + } + catch (Exception exception) + { + ShowExceptionDialog(helpers.Engine, exception); + } + + helpers.LogMethodCompleted(nameof(Script), nameof(OrderForm_BookButton_Pressed), null, stopwatch); + } + + private void AddOrUpdateOrder(OrderAction orderAction) + { + reportDialog = new AddOrUpdateReportDialog(helpers, userInfo.IsMcrUser) { Title = "Updating Order" }; + + reportDialog.OkButton.Pressed += ReportDialog_OkButton_Pressed; + reportDialog.RollBackButton.Pressed += ReportDialog_RollbackButton_Pressed; + app.ShowDialog(reportDialog); + + var tasks = editOrderDialog.Finish(orderAction).Tasks; + + if (tasks.Any()) + { + reportDialog.Finish(tasks); + + // release the locks if all tasks were successful + if (tasks.All(t => t.Status == TaskStatus.Ok)) helpers.LockManager.ReleaseLocks(); + + app.ShowDialog(reportDialog); + } + else ShowMessageDialog(helpers.Engine, "No changes made", "No Changes made"); + + helpers.Log(nameof(Script), nameof(AddOrUpdateOrder), $"Order Updated"); + } + + private void ReportDialog_RollbackButton_Pressed(object sender, EventArgs e) + { + RollBackTasks(); + + helpers.LockManager.ReleaseLocks(); + } + + private void ReportDialog_OkButton_Pressed(object sender, EventArgs e) + { + helpers.LockManager.ReleaseLocks(); + + if (reportDialog.TasksWereSuccessful) + { + helpers.Engine.ExitSuccess(selectedOrderIdForExiting); + } + else if (reportDialog.ShouldRollback) + { + RollBackTasks(); + } + else + { + // Exit script when the user chooses to ignore the failed tasks + helpers.Engine.ExitSuccess(scriptAction == LiveOrderFormAction.Add ? "Unable to create the new Order." : "Unable to update the existing Order."); + } + } + + private void RollBackTasks() + { + // Roll back tasks - Only roll back tasks that were successful + rollbackReportDialog = new RollBackReportDialog(helpers) { Title = scriptAction == LiveOrderFormAction.Edit ? "Roll back Order update" : "Roll back Order creation" }; + rollbackReportDialog.OkButton.Pressed += (s, e) => helpers.Engine.ExitSuccess(rollbackReportDialog.TasksWereSuccessful ? "Successfully rolled back " : "Failed to roll back"); + + + app.ShowDialog(rollbackReportDialog); + + // Only roll back tasks that were successful + var rollbackTasks = reportDialog.UpdateResults.SelectMany(ur => ur.Tasks).Where(t => t.Status == TaskStatus.Ok).Select(t => t.CreateRollbackTask()).Where(t => t != null).Reverse().ToList(); + + foreach (var rollbackTask in rollbackTasks) + { + if (!rollbackTask.Execute()) + { + helpers.Log(nameof(Script), nameof(RollBackTasks), "Rolling back " + rollbackTask.Description + "failed: " + rollbackTask.Exception); + break; + } + } + + rollbackReportDialog.Finish(rollbackTasks); + app.ShowDialog(rollbackReportDialog); + } + + + private void ShowMessageDialog(IEngine engine, string message, string title) + { + var dialog = new MessageDialog((Engine)engine, message) { Title = title }; + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess(message); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + private void ShowExceptionDialog(IEngine engine, Exception exception) + { + ExceptionDialog exceptionDialog = new ExceptionDialog(engine, exception); + exceptionDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong during adding a new service."); + + if (app.IsRunning) app.ShowDialog(exceptionDialog); + else app.Run(exceptionDialog); + } + + #region IDisposable Support + private bool disposedValue; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue && disposing) + { + helpers.Dispose(); + + helpers.LockManager.ReleaseLocks(); + + extendLocksTimer.Stop(); + extendLocksTimer.Dispose(); + } + + disposedValue = true; + } + + ~Script() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + #endregion + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/AddService_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/AddService_1.csproj new file mode 100644 index 0000000..5812351 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/AddService_1.csproj @@ -0,0 +1,104 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {CB5B8A98-2204-4F53-A8A8-B6BB32E85F64} + Library + Properties + AddService_1 + AddService_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\AddService_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\AddService_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + False + ..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Net.Http.dll + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/LoadAddServiceDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/LoadAddServiceDialog.cs new file mode 100644 index 0000000..630802f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/LoadAddServiceDialog.cs @@ -0,0 +1,166 @@ +namespace AddService_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Timers; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notifications; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.LoadingScreenTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.OrderTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.ServiceTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.LoadingScreens; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Order.Dialogs; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class LoadAddServiceDialog : LoadingDialog + { + private string serviceId; + private Service service; + + private readonly Timer extendLocksTimer; + private int attemptsExtendLocking = 1; + + public LoadAddServiceDialog(Helpers helpers, Timer extendLocksTimer) : base(helpers) + { + this.extendLocksTimer = extendLocksTimer; + } + + public Order Order { get; private set; } + + public LiveOrderFormDialog EditOrderDialog { get; private set; } + + public EditSharedSourceDialog EditSharedSourceDialog { get; private set; } + + public LiveOrderFormAction ScriptAction { get; private set; } + + protected override void GetScriptInput() + { + serviceId = Helpers.Engine.GetScriptParam("ServiceId").Value; + ScriptAction = Helpers.Engine.GetScriptParam("Action").Value.GetEnumValue(); + } + + protected override void CollectActions() + { + methodsToExecute.Add(GetService); + methodsToExecute.Add(InitializeOrderLogger); + methodsToExecute.Add(GetOrder); + methodsToExecute.Add(GetLockInfo); + methodsToExecute.Add(GetUserInfo); + methodsToExecute.Add(ConstructForm); + } + + protected override void SendReportButton_Pressed(object sender, EventArgs e) + { + string title = "Exception while loading Update Service [" + DateTime.Now + "]"; + + string message = $"Order(s): '{Order.Name}'
Order ID(s): {Order.Id}
Service: '{service?.Name}'
Service ID: {serviceId}
User: {Helpers.Engine.UserLoginName}
Timestamp: {DateTime.Now}
Exception: {informationMessageLabel.Text.Replace(" at ", "
at ")}"; + + NotificationManager.SendMailToSkylineDevelopers(Helpers, title, message); + + reportSuccessfullySentLabel.IsVisible = true; + } + + private void GetService() + { + var getServiceTask = new GetServiceTask(Helpers, serviceId); + Tasks.Add(getServiceTask); + + IsSuccessful &= getServiceTask.Execute(); + + if (!IsSuccessful) return; + + service = getServiceTask.Service; + } + + private void InitializeOrderLogger() + { + Helpers.AddOrderReferencesForLogging(service.OrderReferences.ToArray()); + } + + private void GetOrder() + { + if (service.TryGetLinkedOrders(Helpers, out List linkedOrders) && linkedOrders.Count == 1) + { + // there can only be 1 order linked to a Destination or Transmission + Order = linkedOrders.Single(); + + Order.AcceptChanges(); + } + else + { + IsSuccessful &= false; + } + + if (Order.Subtype == OrderSubType.Vizrem) + { + PrepareUiForManualMessage("Editing Vizrem orders is currently not supported."); + IsSuccessful = false; + } + } + + private void GetLockInfo() + { + var getLockInfoTask = new GetOrderLockTask(Helpers, Order.Id); + Tasks.Add(getLockInfoTask); + + IsSuccessful &= getLockInfoTask.Execute(); + + if (!IsSuccessful) return; + + LockInfos.Add(getLockInfoTask.LockInfo); + + if (LockInfos.Single().IsLockGranted) + { + extendLocksTimer.Elapsed += ExtendLocksTimer_Elapsed; + extendLocksTimer.Interval = LockInfos.Single().ReleaseLocksAfter.TotalMilliseconds; + extendLocksTimer.AutoReset = true; + extendLocksTimer.Enabled = true; + } + } + + private void GetUserInfo() + { + var getUserInfoTask = new GetUserInfoTask(Helpers); + Tasks.Add(getUserInfoTask); + + IsSuccessful &= getUserInfoTask.Execute(); + + if (!IsSuccessful) return; + + UserInfo = getUserInfoTask.UserInfo; + } + + private void ConstructForm() + { + var constructAddServiceDialogTask = new ConstructLiveOrderFormTask(Helpers, Order, null, LockInfos.Single(), UserInfo, ScriptAction); + Tasks.Add(constructAddServiceDialogTask); + + IsSuccessful &= constructAddServiceDialogTask.Execute(); + if (!IsSuccessful) return; + + EditOrderDialog = constructAddServiceDialogTask.EditOrderDialog; + } + + private void ExtendLocksTimer_Elapsed(object sender, ElapsedEventArgs e) + { + if (attemptsExtendLocking >= 10) + { + extendLocksTimer.Stop(); + extendLocksTimer.Dispose(); + return; + } + + var orderLockInfo = Helpers.LockManager.RequestOrderLock(Order.Id, extendLock: true); + if (orderLockInfo.LockUsername.Contains("error")) + { + Helpers.Log(nameof(LoadAddServiceDialog), nameof(ExtendLocksTimer_Elapsed), $"Something went wrong when extending the order lock: {Order.Id}", Order.Name); + } + + attemptsExtendLocking++; + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..79272e2 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("AddService_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("AddService_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("A9896034-2C14-41E6-A4B0-D064F2ACE9B8")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/app.config new file mode 100644 index 0000000..b8ffc0f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AddService_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics.xml new file mode 100644 index 0000000..ce2bc52 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics.xml @@ -0,0 +1,32 @@ + + + AggregateMetrics + Script 1.0.1.77 + Automation + SKYLINE2\VictorSC + FALSE + YLE/Tools + + + + + + + + + + pushToQaPortal + + + DaysToRemainMetricFiles + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/AggregateMetrics_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/AggregateMetrics_1.cs new file mode 100644 index 0000000..c3b2aff --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/AggregateMetrics_1.cs @@ -0,0 +1,281 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace AggregateMetrics_1 +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Metrics; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Metrics.Files; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Automation; + using Skyline.DataMiner.Net.Messages; + + /// + /// DataMiner Script Class. + /// + public class Script : IDisposable + { + private const string MetricLoggingDirectory = @"C:\Skyline_Data\MetricLogging"; + + private Helpers helpers; + private MetricAggregator aggregator; + private bool pushToQaPortal; + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + try + { + Initialize(engine); + + var summary = aggregator.GetMetricsSummary(MetricLoggingDirectory, out var filesToRemove, out var amountOfProcessedFiles, DateTime.Now.AddDays(-1)); + RemoveProcessedFiles(filesToRemove); + + if (pushToQaPortal) + { + MergeMetricsSummariesFromOtherAgents(summary); + PushMetricsToQaPortal(summary); + } + else + { + AddSummaryToScriptOutput(engine, summary); + } + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Exception occurred: {e}"); + throw; + } + finally + { + Dispose(); + } + } + + private static void RemoveProcessedFiles(List files) + { + foreach (var processedFile in files) + { + File.Delete(processedFile); + } + } + + private static void AddSummaryToScriptOutput(Engine engine, MetricsSummary summary) + { + //var settings = new JsonSerializerSettings(); + //settings.TypeNameHandling = TypeNameHandling.All; + //var serializedSummary = JsonConvert.SerializeObject(summary, Formatting.None, settings); + + var serializedSummary = JsonConvert.SerializeObject(summary, Formatting.None); + + engine.AddOrUpdateScriptOutput("summary", serializedSummary); + } + + private void Initialize(Engine engine) + { + engine.Timeout = TimeSpan.FromHours(10); + engine.SetFlag(RunTimeFlags.NoInformationEvents); + + pushToQaPortal = Convert.ToBoolean(engine.GetScriptParam("pushToQaPortal").Value); + int daysToRemainMetricFiles = Convert.ToInt32(engine.GetScriptParam("DaysToRemainMetricFiles").Value); + + helpers = new Helpers(engine, Scripts.AggregateMetrics); + aggregator = new MetricAggregator(helpers, daysToRemainMetricFiles); + } + + private void MergeMetricsSummariesFromOtherAgents(MetricsSummary summary) + { + var thisAgentId = Engine.SLNetRaw.ServerDetails.AgentID; + + var dms = Engine.SLNetRaw.GetDms(); + foreach (var agentId in dms.GetAgents().Where(a => a.State == Skyline.DataMiner.Core.DataMinerSystem.Common.AgentState.Running).Select(a => a.Id)) + { + if (agentId == thisAgentId) continue; + + var summaryForAgent = GetMetricsSummaryFromAgent(agentId); + if (summaryForAgent != null) + { + summary.Merge(summaryForAgent); + } + } + } + + private MetricsSummary GetMetricsSummaryFromAgent(int agentId) + { + var executeScriptMessage = new ExecuteScriptMessage + { + ScriptName = "AggregateMetrics", + DataMinerID = agentId, + HostingDataMinerID = agentId, + Options = new SA(new[] + { + "DEFER:FALSE", + "PARAMETERBYNAME:pushToQaPortal:False", + $"PARAMETERBYNAME:DaysToRemainMetricFiles:{aggregator.DaysToRemainMetricFiles}" + }) + }; + + try + { + var response = (ExecuteScriptResponseMessage)helpers.Engine.SendSLNetSingleResponseMessage(executeScriptMessage); + + var output = response.ScriptOutput; + return GetSummaryFromScriptOutput(output, agentId); + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(GetMetricsSummaryFromAgent), $"Exception retrieving metrics summary from agent {agentId}: {e}"); + return null; + } + } + + private MetricsSummary GetSummaryFromScriptOutput(Dictionary output, int agentId) + { + if (output == null || !output.TryGetValue("summary", out var summary)) + { + helpers.Log(nameof(Script), nameof(GetSummaryFromScriptOutput), $"No metrics summary results received from agent {agentId}"); + return null; + } + + if (String.IsNullOrEmpty(summary)) + { + helpers.Log(nameof(Script), nameof(GetSummaryFromScriptOutput), $"Empty metrics summary results received from agent {agentId}"); + return null; + } + + helpers.Log(nameof(Script), nameof(GetSummaryFromScriptOutput), $"Summary from {agentId}: {summary}"); + + //var settings = new JsonSerializerSettings(); + //settings.TypeNameHandling = TypeNameHandling.All; + //return JsonConvert.DeserializeObject(summary, settings); + + return JsonConvert.DeserializeObject(summary); + } + + private void PushMetricsToQaPortal(MetricsSummary summary) + { + //var allStartTimes = summary.ScriptExecutionMetricSummaries.Values.SelectMany(s => s).Select(x => x.StartTime).Where(s => s != null).ToList(); + + var allStartTimes = summary.ScriptMetricSummaries.SelectMany(s => s.GetStartTimes()).Where(s => s != null).ToList(); + + var earliestStartTime = allStartTimes.Min(); + var latestEndTime = allStartTimes.Max(); + + // Temporary method additions, goal is to make something generic to gather and push method results. + var fixedMethodNameList = new[] { "GetEvent", "Event", "GetEventByName", "AddOrUpdateOrderReservation", "AddOrUpdateServiceReservation" }; + var methodSummeriesToPush = summary.MethodCallSummaries.Where(mcs => fixedMethodNameList.Contains(mcs.MethodName)).ToList(); + + foreach (var methodSummary in methodSummeriesToPush) + { + if (methodSummary is null) continue; + + string extraInfo = $"Value aggregated from {methodSummary.AmountOfExecutions} executions from {earliestStartTime} until {latestEndTime}"; + + helpers.QAPortalHelper.PublishPerformanceTestResult(methodSummary.QaPortalTestNameForAverage, methodSummary.AverageExecutionTime, extraInfo); + helpers.QAPortalHelper.PublishPerformanceTestResult(methodSummary.QaPortalTestNameForHighest, methodSummary.HighestExecutionTime, extraInfo); + } + + foreach (var scriptSummary in summary.ScriptMetricSummaries) + { + if (String.IsNullOrWhiteSpace(scriptSummary.ScriptName)) continue; + if (!scriptSummary.ScriptExecutionMetricSummaries.Any()) continue; + + string extraInfo = $"Value aggregated from {scriptSummary.AmountOfExecutions} executions from {earliestStartTime} until {latestEndTime}"; + + helpers.QAPortalHelper.PublishPerformanceTestResult(scriptSummary.QaPortalTestNameForAverage, scriptSummary.AverageExecutionTime, extraInfo); + helpers.QAPortalHelper.PublishPerformanceTestResult(scriptSummary.QaPortalTestNameForHighest, scriptSummary.HighestExecutionTime, extraInfo); + } + + foreach (var dataMinerInterfaceMethodSummary in summary.DataMinerInterfaceMethodCallSummaries) + { + if (String.IsNullOrWhiteSpace(dataMinerInterfaceMethodSummary.ClassName) || + String.IsNullOrWhiteSpace(dataMinerInterfaceMethodSummary.MethodName)) continue; + if (!dataMinerInterfaceMethodSummary.ExecutionTimes.Any()) continue; + + string extraInfo = $"Value aggregated from {dataMinerInterfaceMethodSummary.AmountOfExecutions} executions from {earliestStartTime} until {latestEndTime}"; + + helpers.QAPortalHelper.PublishPerformanceTestResult(dataMinerInterfaceMethodSummary.QaPortalTestNameForAverage, dataMinerInterfaceMethodSummary.AverageExecutionTime, extraInfo); + helpers.QAPortalHelper.PublishPerformanceTestResult(dataMinerInterfaceMethodSummary.QaPortalTestNameForHighest, dataMinerInterfaceMethodSummary.HighestExecutionTime, extraInfo); + } + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/AggregateMetrics_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/AggregateMetrics_1.csproj new file mode 100644 index 0000000..a63f601 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/AggregateMetrics_1.csproj @@ -0,0 +1,101 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {8F19C132-61E2-4351-AC47-4653E86D7456} + Library + Properties + AggregateMetrics_1 + AggregateMetrics_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\AggregateMetrics_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\AggregateMetrics_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + 1.1.0.5 + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a125c62 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("AggregateMetrics_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("AggregateMetrics_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("38656200-E291-4E4E-B6E8-4A7A6BD11F5B")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AggregateMetrics_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources.xml new file mode 100644 index 0000000..edff934 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources.xml @@ -0,0 +1,31 @@ + + + AssignRecordingResources + Script 1.0.1.77 + Automation + SKYLINE2\GillesVH + FALSE + YLE/SRM + + + + + + + + + + BookingID + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/AssignRecordingResources_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/AssignRecordingResources_2.csproj new file mode 100644 index 0000000..ab98c5b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/AssignRecordingResources_2.csproj @@ -0,0 +1,101 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {61FCF96E-F3D6-4609-9D75-78D9582E692D} + Library + Properties + AssignRecordingResources_2 + AssignRecordingResources_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\AssignRecordingResources_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\AssignRecordingResources_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/ConfirmAssignDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/ConfirmAssignDialog.cs new file mode 100644 index 0000000..6d17acb --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/ConfirmAssignDialog.cs @@ -0,0 +1,36 @@ +namespace AssignRecordingResources_2 +{ + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class ConfirmAssignDialog : Dialog + { + private readonly Label messageLabel = new Label("Are you sure that you want to assign the resource of this service reservation?"); + + public ConfirmAssignDialog(Engine engine) : base(engine) + { + this.Title = "Confirm Assign"; + + YesButton = new Button("Yes") { Width = 200 }; + NoButton = new Button("No") { Width = 200 }; + + GenerateUi(); + } + + public Button YesButton { get; private set; } + + public Button NoButton { get; private set; } + + private void GenerateUi() + { + int row = -1; + + AddWidget(messageLabel, ++row, 0, 1, 2); + + AddWidget(new WhiteSpace(), new WidgetLayout(++row, 0)); + + AddWidget(YesButton, ++row, 0, 1, 1); + AddWidget(NoButton, row, 1, 1, 1); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..19f7581 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("AssignRecordingResources_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("AssignRecordingResources_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("A09BD0C0-047F-4253-818B-FB8BB5D1A624")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/Script.cs new file mode 100644 index 0000000..e73f88a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/Script.cs @@ -0,0 +1,239 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +13/04/2021 1.0.0.1 GVH, Skyline Initial version +**************************************************************************** +*/ + +namespace AssignRecordingResources_2 +{ + using System; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Functions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.LoadingScreens; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + /// + /// DataMiner Script Class. + /// + public class Script : IDisposable + { + private Helpers helpers; + private InteractiveController app; + + private LoadAssignReleaseResourceDialog loadAssignRecordingResourceDialog; + private AssignReleaseResourceDialog assignResourceDialog; + private ReportDialog reportDialog; + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + try + { + Initialize(engine); + + loadAssignRecordingResourceDialog = new LoadAssignReleaseResourceDialog(helpers, ResourceScriptAction.Assign); + + if (loadAssignRecordingResourceDialog.Execute()) ShowAssignResourceDialog(); + else app.Run(loadAssignRecordingResourceDialog); + } + catch (InteractiveUserDetachedException) + { + helpers.Log(nameof(Script), "STOP SCRIPT", "Assign Recording Resource"); + helpers.LockManager.ReleaseLocks(); + } + catch (ScriptAbortException) + { + helpers.Log(nameof(Script), "STOP SCRIPT", "Assign Recording Resource"); + helpers.LockManager.ReleaseLocks(); + throw; + } + catch (Exception e) + { + helpers.Log(nameof(Script), "STOP SCRIPT", "Assign Recording Resource"); + engine.Log("Run|Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + finally + { + Dispose(); + } + } + + private void Initialize(Engine engine) + { + // engine.ShowUI(); + engine.Timeout = TimeSpan.FromHours(10); + engine.SetFlag(RunTimeFlags.NoInformationEvents); + + helpers = new Helpers(engine, Scripts.AssignRecordingResources); + + app = new InteractiveController(engine); + } + + private void ShowAssignResourceDialog() + { + assignResourceDialog = loadAssignRecordingResourceDialog.AssignReleaseResourceDialog; + assignResourceDialog.AssignButton.Pressed += AssignButton_Pressed; + + if (app.IsRunning) app.ShowDialog(assignResourceDialog); + else app.Run(assignResourceDialog); + } + + private void AssignButton_Pressed(object sender, EventArgs e) + { + ConfirmAssignDialog confirmAssignDialog = new ConfirmAssignDialog((Engine)helpers.Engine); + confirmAssignDialog.NoButton.Pressed += (o, args) => app.ShowDialog(assignResourceDialog); + confirmAssignDialog.YesButton.Pressed += ConfirmAssignDialog_YesButton_Pressed; + + app.ShowDialog(confirmAssignDialog); + } + + private void ConfirmAssignDialog_YesButton_Pressed(object sender, EventArgs e) + { + try + { + reportDialog = new AddOrUpdateReportDialog(helpers); + reportDialog.OkButton.Pressed += (o, args) => { helpers.LockManager.ReleaseLocks(); helpers.Engine.ExitSuccess("Successfully updated the recording service"); }; + reportDialog.RollBackButton.Pressed += (o, args) => RollBackTasks(); + app.ShowDialog(reportDialog); + + var tasks = assignResourceDialog.Finish().Tasks.ToList(); + + if (tasks.Any()) + { + reportDialog.Finish(tasks); + + // release the locks if all tasks were successful + if (tasks.All(t => t.Status == Status.Ok)) helpers.LockManager.ReleaseLocks(); + + app.ShowDialog(reportDialog); + } + else ShowMessageDialog((Engine)helpers.Engine, "No changes made", "No Changes made"); + + } + catch (Exception ex) + { + ShowExceptionDialog((Engine)helpers.Engine, ex); + } + } + + private void RollBackTasks() + { + // Roll back tasks - Only roll back tasks that were successful + var rollbackReportDialog = new RollBackReportDialog(helpers) { Title = "Roll back service update" }; + rollbackReportDialog.OkButton.Pressed += (o, e) => helpers.Engine.ExitSuccess("Successfully rolled back the service update"); + + app.ShowDialog(rollbackReportDialog); + + // Only roll back tasks that were successful + var rollbackTasks = reportDialog.UpdateResults.SelectMany(ur => ur.Tasks).Where(t => t.Status == Status.Ok).Select(t => t.CreateRollbackTask()).Where(t => t != null).Reverse().ToList(); + + foreach (var rollbackTask in rollbackTasks) + { + if (!rollbackTask.Execute()) + { + helpers.Log(nameof(Script), nameof(RollBackTasks), "Rolling back " + rollbackTask.Description + "failed: " + rollbackTask.Exception); + break; + } + } + + rollbackReportDialog.Finish(rollbackTasks); + + helpers.LockManager.ReleaseLocks(); + + app.ShowDialog(rollbackReportDialog); + } + + private void ShowMessageDialog(Engine engine, string message, string title) + { + MessageDialog dialog = new MessageDialog(engine, message) { Title = title }; + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess(message); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitFail("Something went wrong during the handling of resource assigning"); + if (!app.IsRunning) app.Run(dialog); + else app.ShowDialog(dialog); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignRecordingResources_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe.xml new file mode 100644 index 0000000..5668443 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe.xml @@ -0,0 +1,31 @@ + + + AssignTicketToMe + Script 1.0.1.77 + Automation + SKYLINE2\VictorSC + FALSE + YLE/Customer UI + + + + + + + + + + TicketId + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/AssignTicketToMe_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/AssignTicketToMe_2.csproj new file mode 100644 index 0000000..98a9bc3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/AssignTicketToMe_2.csproj @@ -0,0 +1,100 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {6846E9D4-264E-4FFD-876D-88BFBDAFE69F} + Library + Properties + AssignTicketToMe_2 + AssignTicketToMe_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\AssignTicketToMe_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\AssignTicketToMe_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..71682f3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("AssignTicketToMe_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("AssignTicketToMe_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("6B970F92-99A9-455F-951B-3298412F6FB3")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/Script.cs new file mode 100644 index 0000000..bb1ae7b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/Script.cs @@ -0,0 +1,178 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version + +22/03/2021 1.0.0.2 GVH, Skyline Linking between user tasks and non live orders +**************************************************************************** +*/ + +namespace AssignTicketToMe_2 +{ + using System; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.NonLiveUserTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + /// + /// DataMiner Script Class. + /// + class Script : IDisposable + { + private Helpers helpers; + private InteractiveController app; + private User user; + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + try + { + Initialize(engine); + + string scriptParameter = engine.GetScriptParam(1).Value; + + int[] dmaAndTicketId = Array.ConvertAll(scriptParameter.Split(new[] { '/' }).Select(item => item.Trim('"', '[', ']')).ToArray(), Convert.ToInt32); + + if (helpers.NonLiveOrderManager.TryGetNonLiveOrder(dmaAndTicketId[0], dmaAndTicketId[1], out var nonLiveOrder)) + { + helpers.NonLiveOrderManager.AssignNonLiveOrderTo(nonLiveOrder, user); + } + else if (helpers.UserTaskManager.TryGetUserTask(scriptParameter, out var userTask)) + { + userTask.Owner = engine.UserDisplayName; + userTask.AddOrUpdate(helpers); + + bool assignToMe = true; + if (userTask is NonLiveUserTask nonLiveUserTask && !helpers.NonLiveOrderManager.TryUpdateNonLiveOrderStatusBasedOnUserTask(helpers.NonLiveUserTaskManager, nonLiveUserTask, user, assignToMe)) + { + helpers.Log(nameof(Script), nameof(Run), $"Non live order failed while updating the status"); + } + } + else + { + helpers.Log(nameof(Script), nameof(Run), $"Ticket with ID {scriptParameter} is not a non-live order nor a user task."); + + ShowMessageDialog(engine, $"Assigning the ticket to you failed because the system was unable to convert the ticket with ID {scriptParameter} to a non-live order or user task.", "Error"); + } + } + catch (ScriptAbortException) + { + // ignore + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Something went wrong: {e}"); + ShowExceptionDialog(engine, e); + } + finally + { + helpers.Log(nameof(Script), "STOP SCRIPT", "AssignTicketToMe"); + Dispose(); + } + } + + private void Initialize(Engine engine) + { + //engine.ShowUI(); + helpers = new Helpers(engine, Scripts.AssignTicketToMe); + + app = new InteractiveController(engine); + + user = helpers.ContractManager.GetBaseUserInfo(engine.UserLoginName).User; + } + + private void ShowMessageDialog(Engine engine, string message, string title) + { + MessageDialog dialog = new MessageDialog(engine, message) { Title = title }; + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess(message); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog exceptionDialog = new ExceptionDialog(engine, exception); + exceptionDialog.OkButton.Pressed += (o, e) => engine.ExitSuccess("Something went wrong during the execution of Assign Ticket to me"); + + if (app.IsRunning) app.ShowDialog(exceptionDialog); + else app.Run(exceptionDialog); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AssignTicketToMe_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AutomationScript.sln b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AutomationScript.sln new file mode 100644 index 0000000..1423722 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/AutomationScript.sln @@ -0,0 +1,1457 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32407.343 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{B8F1F599-6153-4506-BA3A-C68123D23987}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dlls", "Dlls", "{EC5443D2-2D8E-411C-A52D-1F5E14895874}" + ProjectSection(SolutionItems) = preProject + Dlls\readme.txt = Dlls\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{8162A277-32E5-4B70-981B-16BD1FBC49C0}" + ProjectSection(SolutionItems) = preProject + Documentation\readme.txt = Documentation\readme.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddEvent", "AddEvent", "{0A0FBC87-CC98-42F9-9A0A-8E9BA7BFFCD5}" + ProjectSection(SolutionItems) = preProject + AddEvent.xml = AddEvent.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{ACC68C00-F79A-4901-AD56-56608A4ED459}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddEvent_2", "AddEvent_2\AddEvent_2.csproj", "{8EBFE2CE-07A1-45F6-85AC-8023014A0A8A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddEventFromTemplate", "AddEventFromTemplate", "{AAAB9A5A-635B-436F-8C37-EC7AEC4E2CD6}" + ProjectSection(SolutionItems) = preProject + AddEventFromTemplate.xml = AddEventFromTemplate.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{021CDAC2-FA64-47D4-B135-BE88307070F3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddEventFromTemplate_1", "AddEventFromTemplate_1\AddEventFromTemplate_1.csproj", "{880203DF-F9E6-4888-9978-A2FBE22BD25A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddNote", "AddNote", "{8CA3AB2F-92C6-4C50-8D9E-CA2B47C2C3D8}" + ProjectSection(SolutionItems) = preProject + AddNote.xml = AddNote.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{E538F135-D7F1-4D06-B4FA-42CC9B2045C0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddNote_2", "AddNote_2\AddNote_2.csproj", "{E5C344F3-4239-4F98-BF5B-642646B0A68A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddOrUpdateNonLiveOrder", "AddOrUpdateNonLiveOrder", "{F2457324-04D1-4703-91D4-30CB9046C94F}" + ProjectSection(SolutionItems) = preProject + AddOrUpdateNonLiveOrder.xml = AddOrUpdateNonLiveOrder.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D54F9F07-8ED9-4511-A572-57AA57D7ABEE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddOrUpdateNonLiveOrder_2", "AddOrUpdateNonLiveOrder_2\AddOrUpdateNonLiveOrder_2.csproj", "{CD8CA3A7-2D4D-416A-BB82-76279B1843C2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AssignTicketToMe", "AssignTicketToMe", "{D6AA01DF-D60F-497E-A29D-28268B164B8D}" + ProjectSection(SolutionItems) = preProject + AssignTicketToMe.xml = AssignTicketToMe.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{E20DDD90-B221-4873-A9F9-7F831F17FF95}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssignTicketToMe_2", "AssignTicketToMe_2\AssignTicketToMe_2.csproj", "{6846E9D4-264E-4FFD-876D-88BFBDAFE69F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BookMultipleOrders", "BookMultipleOrders", "{42DE3F58-875F-49A2-8BB3-AE9ABB6ABD98}" + ProjectSection(SolutionItems) = preProject + BookMultipleOrders.xml = BookMultipleOrders.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{EB2D434B-1053-42C1-95B0-3A1C8112DA49}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookMultipleOrders_2", "BookMultipleOrders_2\BookMultipleOrders_2.csproj", "{E10BD658-9B0E-4A95-97B7-C288C429C094}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CancelMultipleOrders", "CancelMultipleOrders", "{5A7E4CE3-E5F2-46FB-80F8-AAF2EA16D5E4}" + ProjectSection(SolutionItems) = preProject + CancelMultipleOrders.xml = CancelMultipleOrders.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{FAA052F2-328B-41A2-9A2B-CCD32A7517A3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CancelMultipleOrders_2", "CancelMultipleOrders_2\CancelMultipleOrders_2.csproj", "{CFA4A2CE-A230-4303-83B1-677B23B66266}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ConfirmOrders", "ConfirmOrders", "{2FCA2E8E-D20D-421A-8F6B-4641DF47CF84}" + ProjectSection(SolutionItems) = preProject + ConfirmOrders.xml = ConfirmOrders.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{7BBC9237-2D49-4C6F-BDC6-0B495FD43FB6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfirmOrders_5", "ConfirmOrders_5\ConfirmOrders_5.csproj", "{7F6A3EC0-1B12-4F2A-B0F8-1EBA1C113460}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DeleteEvent", "DeleteEvent", "{96FD05B9-272B-4AC4-81AB-A8D411823A37}" + ProjectSection(SolutionItems) = preProject + DeleteEvent.xml = DeleteEvent.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D5E91541-FE1E-48BB-BCA2-EF80BF0F4381}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeleteEvent_2", "DeleteEvent_2\DeleteEvent_2.csproj", "{E69808C1-8776-4055-8385-05CCE596C4E5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DeleteNonLiveOrder", "DeleteNonLiveOrder", "{5C85A61A-EED6-4A1D-9BA0-245900C0B493}" + ProjectSection(SolutionItems) = preProject + DeleteNonLiveOrder.xml = DeleteNonLiveOrder.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{91324E15-E4A3-4C49-9385-7F311012AB3D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeleteNonLiveOrder_2", "DeleteNonLiveOrder_2\DeleteNonLiveOrder_2.csproj", "{98F1FA3D-7B10-4178-A6A4-41F6958CCBE5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DuplicateNonLiveOrder", "DuplicateNonLiveOrder", "{985ED6EE-AC9D-4BD4-88D7-06CC4740ACD1}" + ProjectSection(SolutionItems) = preProject + DuplicateNonLiveOrder.xml = DuplicateNonLiveOrder.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D9C0DE7D-885D-4CB3-80FA-2A653026A28E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DuplicateNonLiveOrder_2", "DuplicateNonLiveOrder_2\DuplicateNonLiveOrder_2.csproj", "{A90B225A-0F85-416B-9CE8-EEBDF2929BC4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LiveOrderForm", "LiveOrderForm", "{2A8BDC9C-C864-46B7-98A0-ECC9BA0ECDFF}" + ProjectSection(SolutionItems) = preProject + LiveOrderForm.xml = LiveOrderForm.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{5B9A381F-95C5-4879-BB11-67E7FE333C45}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveOrderForm_6", "LiveOrderForm_6\LiveOrderForm_6.csproj", "{48F1B70D-8C96-49BA-B4A2-957377393EEF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MergeEvents", "MergeEvents", "{F2100C68-99AA-437E-8B6F-569CFF60319A}" + ProjectSection(SolutionItems) = preProject + MergeEvents.xml = MergeEvents.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D277FFE9-E342-4D8F-9EEA-ACB984B3F20E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MergeEvents_2", "MergeEvents_2\MergeEvents_2.csproj", "{C11D6283-7A34-4CDD-8C27-65F8499E5CFE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SendOrderDebugReport", "SendOrderDebugReport", "{E3A38228-9D83-4287-BB40-3B37105327C3}" + ProjectSection(SolutionItems) = preProject + SendOrderDebugReport.xml = SendOrderDebugReport.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{0A6E4D7B-7E46-4428-B8A2-04670F4AE4E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SendOrderDebugReport_2", "SendOrderDebugReport_2\SendOrderDebugReport_2.csproj", "{C37BA915-33E8-48C6-9098-6681EE54884D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateComments", "UpdateComments", "{263ABDC6-0FF9-4CEF-BADE-AF910A4CD06E}" + ProjectSection(SolutionItems) = preProject + UpdateComments.xml = UpdateComments.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{55BA7DED-599D-4518-BE9A-EF537FF15FD5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateComments_2", "UpdateComments_2\UpdateComments_2.csproj", "{2C70A6EE-70B7-42C0-8C0B-66C690AB8C87}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateEvent", "UpdateEvent", "{4FBDE444-8013-449D-829B-1A10E5C84ED2}" + ProjectSection(SolutionItems) = preProject + UpdateEvent.xml = UpdateEvent.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{81C41B64-01DB-4B74-ACC0-E3FC9EBCC8F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateEvent_2", "UpdateEvent_2\UpdateEvent_2.csproj", "{F44EB030-BD0E-42AB-82BD-5E7E0F530A24}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateNote", "UpdateNote", "{3C7B03EF-F829-4183-8447-5FFAAB41736D}" + ProjectSection(SolutionItems) = preProject + UpdateNote.xml = UpdateNote.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{504632B3-C3E0-4AEE-BB19-4B83AB67EE98}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateNote_2", "UpdateNote_2\UpdateNote_2.csproj", "{96C98AA8-D5D5-4F3D-AC36-DFB044A10283}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateService", "UpdateService", "{CF5E9E32-F322-427D-9282-75D9241B01A9}" + ProjectSection(SolutionItems) = preProject + UpdateService.xml = UpdateService.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{36D4B481-06AB-4B67-8794-E9CFB5502973}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateService_4", "UpdateService_4\UpdateService_4.csproj", "{D3966891-3616-427F-BC24-CEBAD4B3B6BE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateTicketStatus", "UpdateTicketStatus", "{F15D5FFF-2C08-4EB8-B2D7-A1DD8162F5AF}" + ProjectSection(SolutionItems) = preProject + UpdateTicketStatus.xml = UpdateTicketStatus.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{BBB2D930-94EA-4246-8455-237671065539}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateTicketStatus_4", "UpdateTicketStatus_4\UpdateTicketStatus_4.csproj", "{FAFEE1DA-438D-4D7F-91B1-9BB2444DB30E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExecuteFeenixStopCommand", "ExecuteFeenixStopCommand", "{6E2CC07F-56CA-40F3-B3F3-3DA8AE603896}" + ProjectSection(SolutionItems) = preProject + ExecuteFeenixStopCommand.xml = ExecuteFeenixStopCommand.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{C6A58830-B745-41A4-90D2-DA163CF2BB67}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecuteFeenixStopCommand_2", "ExecuteFeenixStopCommand_2\ExecuteFeenixStopCommand_2.csproj", "{DA97B418-6D04-4FA2-8214-6FE3113E02C7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PollCeitonResources", "PollCeitonResources", "{A3BE5D15-F8AA-4EDB-8E75-E1F37924CEF6}" + ProjectSection(SolutionItems) = preProject + PollCeitonResources.xml = PollCeitonResources.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{8E528AAF-4A6F-4829-B806-EDBD5C30F355}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PollCeitonResources_1", "PollCeitonResources_1\PollCeitonResources_1.csproj", "{DD92F97D-EA78-4377-8DB7-63D1C6048670}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ShowCeitonDetails", "ShowCeitonDetails", "{4D2D22C2-B933-495B-9846-811D5907A57D}" + ProjectSection(SolutionItems) = preProject + ShowCeitonDetails.xml = ShowCeitonDetails.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{929BA453-227D-46A5-BDD7-0A19825BE5E5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowCeitonDetails_2", "ShowCeitonDetails_2\ShowCeitonDetails_2.csproj", "{891D09C7-E16C-4467-BDEE-BDAAB5552B7A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ShowEBUDetails", "ShowEBUDetails", "{269FF747-D5E0-40D8-B049-6E4C4964ADA6}" + ProjectSection(SolutionItems) = preProject + ShowEBUDetails.xml = ShowEBUDetails.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{2E90B124-81A7-4537-927F-8DB160C1FE80}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowEBUDetails_2", "ShowEBUDetails_2\ShowEBUDetails_2.csproj", "{A3B23699-5387-4266-B784-C7AE207E6923}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ShowFeenixDetails", "ShowFeenixDetails", "{9101C64B-D96D-473D-B675-3774012104DA}" + ProjectSection(SolutionItems) = preProject + ShowFeenixDetails.xml = ShowFeenixDetails.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{35EB5074-E17E-414B-9057-2E26E4C43D5B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowFeenixDetails_2", "ShowFeenixDetails_2\ShowFeenixDetails_2.csproj", "{BA41DE74-F49C-4C07-A83D-2317566E7808}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ShowPebbleBeachDetails", "ShowPebbleBeachDetails", "{3F4A40BF-90D0-4F0B-A8E7-4353FAC34D4C}" + ProjectSection(SolutionItems) = preProject + ShowPebbleBeachDetails.xml = ShowPebbleBeachDetails.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{E78D409D-0A8E-4A95-9E03-165B01A953BF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowPebbleBeachDetails_2", "ShowPebbleBeachDetails_2\ShowPebbleBeachDetails_2.csproj", "{80B82340-D9C3-431F-9B22-947F6DDAE0F6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ShowPlasmaDetails", "ShowPlasmaDetails", "{044CF8A5-7174-45AD-A429-BFAE3DC59B3B}" + ProjectSection(SolutionItems) = preProject + ShowPlasmaDetails.xml = ShowPlasmaDetails.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{2924AEED-876E-4AFA-A233-B34229F73BE4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowPlasmaDetails_2", "ShowPlasmaDetails_2\ShowPlasmaDetails_2.csproj", "{74B56470-25B2-4846-810D-53560F6EB5F1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TriggerPebbleBeachIntegrationUpdate", "TriggerPebbleBeachIntegrationUpdate", "{DB05923D-5D5E-4630-AF81-386E8FD267A6}" + ProjectSection(SolutionItems) = preProject + TriggerPebbleBeachIntegrationUpdate.xml = TriggerPebbleBeachIntegrationUpdate.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{AABB6D87-3D71-4E9B-964C-C2327BE60CFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TriggerPebbleBeachIntegrationUpdate_2", "TriggerPebbleBeachIntegrationUpdate_2\TriggerPebbleBeachIntegrationUpdate_2.csproj", "{5C73EE37-B28D-476A-825E-4EF73D0F6D80}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AssignRecordingResources", "AssignRecordingResources", "{25A7010F-FAAF-47FB-85F4-CBA5803D29FB}" + ProjectSection(SolutionItems) = preProject + AssignRecordingResources.xml = AssignRecordingResources.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{C430C499-9B05-46D5-A3F8-5BA3FB0FEC97}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssignRecordingResources_2", "AssignRecordingResources_2\AssignRecordingResources_2.csproj", "{61FCF96E-F3D6-4609-9D75-78D9582E692D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ClearReservations", "ClearReservations", "{7856E480-B1CB-4658-A2FB-ABA0C201A41F}" + ProjectSection(SolutionItems) = preProject + ClearReservations.xml = ClearReservations.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{0819B57C-7DC1-4766-88DE-2E6EE93100B8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClearReservations_2", "ClearReservations_2\ClearReservations_2.csproj", "{BF317DEB-2946-49C4-A6D2-3A0B4175AF64}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ClearExpiredServices", "ClearExpiredServices", "{8A254CA8-A07F-4729-9D33-0494853B734B}" + ProjectSection(SolutionItems) = preProject + ClearExpiredServices.xml = ClearExpiredServices.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{48443654-8823-499D-9FDA-B95460C5307C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClearExpiredServices_1", "ClearExpiredServices_1\ClearExpiredServices_1.csproj", "{951F433D-47BB-46CD-9577-38DC2EEF38F1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debug", "Debug", "{0EE07F7A-DE9B-4C55-A697-3A17B5D3E0B4}" + ProjectSection(SolutionItems) = preProject + Debug.xml = Debug.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{92896FB4-C0F8-4387-858D-A290CD242622}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debug_2", "Debug_2\Debug_2.csproj", "{92B8FAFF-3EBC-4C12-91AB-71A8B6E0EC1C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DecodingResourceCapabilityUpdates", "DecodingResourceCapabilityUpdates", "{2EBD7821-313E-4099-B11E-A64208AF5828}" + ProjectSection(SolutionItems) = preProject + DecodingResourceCapabilityUpdates.xml = DecodingResourceCapabilityUpdates.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D7AF3953-4C0F-4D48-9B9B-41CC9030C3CC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DecodingResourceCapabilityUpdates_1", "DecodingResourceCapabilityUpdates_1\DecodingResourceCapabilityUpdates_1.csproj", "{6C8B2D4E-6B4E-4F71-AA72-BF0BB37D6DAD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DeleteIntegrationOrders", "DeleteIntegrationOrders", "{916C4EA8-832B-4A46-87E0-B7E791370E40}" + ProjectSection(SolutionItems) = preProject + DeleteIntegrationOrders.xml = DeleteIntegrationOrders.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{59C0DA6D-19D4-4558-99E4-214E303A4577}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeleteIntegrationOrders_1", "DeleteIntegrationOrders_1\DeleteIntegrationOrders_1.csproj", "{66B48A43-2EA8-4463-81B5-D842A49DBD73}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DeleteReservationsForCertainResource", "DeleteReservationsForCertainResource", "{B980A4D6-935E-4EBC-B2EA-6CCA456F7A58}" + ProjectSection(SolutionItems) = preProject + DeleteReservationsForCertainResource.xml = DeleteReservationsForCertainResource.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{5D0E2857-73F0-4629-8E2E-AE0697AD80D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeleteReservationsForCertainResource_1", "DeleteReservationsForCertainResource_1\DeleteReservationsForCertainResource_1.csproj", "{30536342-FF9E-4B4E-8679-55DDF1583BCE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DeleteUnusedReservations", "DeleteUnusedReservations", "{BE0926CC-9242-4907-B7D9-DD44FA3DB846}" + ProjectSection(SolutionItems) = preProject + DeleteUnusedReservations.xml = DeleteUnusedReservations.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{483EBECF-595C-41E1-9133-F6823CAEAD21}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeleteUnusedReservations_1", "DeleteUnusedReservations_1\DeleteUnusedReservations_1.csproj", "{1A694B8E-C1E4-4BC2-A5F3-F658EB733EDB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ForceDeleteOrder", "ForceDeleteOrder", "{2C0EA586-4767-4FD7-B994-7FD140C88410}" + ProjectSection(SolutionItems) = preProject + ForceDeleteOrder.xml = ForceDeleteOrder.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{921533E6-BAEC-4661-81D4-93379BC098C5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ForceDeleteOrder_1", "ForceDeleteOrder_1\ForceDeleteOrder_1.csproj", "{86177A39-B69B-40BC-AAA4-E5DDDCE80B54}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HandleEventAction", "HandleEventAction", "{6FE112DA-68F4-4478-B3D4-0998C796B069}" + ProjectSection(SolutionItems) = preProject + HandleEventAction.xml = HandleEventAction.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{9A6E6002-400C-4E20-B720-98E4C6C08C91}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandleEventAction_3", "HandleEventAction_3\HandleEventAction_3.csproj", "{3FF581CD-E646-48CE-8611-159999784EDB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HandleOrderAction", "HandleOrderAction", "{E08F12C4-FC31-46E7-8929-D588E0516D1E}" + ProjectSection(SolutionItems) = preProject + HandleOrderAction.xml = HandleOrderAction.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{A6FAE91B-BC05-4231-9B18-B77861456554}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandleOrderAction_1", "HandleOrderAction_1\HandleOrderAction_1.csproj", "{6BDE17DC-A368-4EB8-9BA5-222E2E8469D1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HandleOrderStartFailure", "HandleOrderStartFailure", "{FB1CC579-E541-4CB9-B1B8-4F5DF7E9AC14}" + ProjectSection(SolutionItems) = preProject + HandleOrderStartFailure.xml = HandleOrderStartFailure.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{78A1EE8A-2B3C-48C5-B604-A769436714D6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandleOrderStartFailure_1", "HandleOrderStartFailure_1\HandleOrderStartFailure_1.csproj", "{24C6898B-ACF8-4406-8767-4EB388950D3B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HandleRecurringOrderAction", "HandleRecurringOrderAction", "{B3B19CA3-CA80-4010-98E6-C175AA88B8CC}" + ProjectSection(SolutionItems) = preProject + HandleRecurringOrderAction.xml = HandleRecurringOrderAction.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{99767C82-2DC7-41C7-92F8-C92C28985A87}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandleRecurringOrderAction_2", "HandleRecurringOrderAction_2\HandleRecurringOrderAction_2.csproj", "{2F80BDCE-7606-4F23-99CE-B980E1E8C70E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HandleServiceAction", "HandleServiceAction", "{3085F22A-78A0-4BF2-AF0D-5E2A0EC3B1FD}" + ProjectSection(SolutionItems) = preProject + HandleServiceAction.xml = HandleServiceAction.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{805B67FD-07D3-4B16-85E6-EA8039FE0C51}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandleServiceAction_1", "HandleServiceAction_1\HandleServiceAction_1.csproj", "{C5A5B136-224B-43B4-B220-C677BF4D8294}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HandleServiceStartFailure", "HandleServiceStartFailure", "{1DC7633F-5218-4A44-963F-730CA81B66E2}" + ProjectSection(SolutionItems) = preProject + HandleServiceStartFailure.xml = HandleServiceStartFailure.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{E4806DB9-88E3-4192-8077-90047B8DD2A1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandleServiceStartFailure_1", "HandleServiceStartFailure_1\HandleServiceStartFailure_1.csproj", "{DB1D40BF-6C1B-4565-B629-4647834B8F40}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LocalBackup", "LocalBackup", "{CF2C3F58-8A1E-48C4-ACA7-7D540DBEDD80}" + ProjectSection(SolutionItems) = preProject + LocalBackup.xml = LocalBackup.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{B34807AE-1728-48FE-8B3A-4FCC4DD8D40C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalBackup_1", "LocalBackup_1\LocalBackup_1.csproj", "{316025D1-B4C1-4053-87E4-34DC46FF7B23}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MatrixOutputLbandResourceCapabilityUpdates", "MatrixOutputLbandResourceCapabilityUpdates", "{CACFA014-FC77-4B94-827C-2B59DE04BE16}" + ProjectSection(SolutionItems) = preProject + MatrixOutputLbandResourceCapabilityUpdates.xml = MatrixOutputLbandResourceCapabilityUpdates.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{96787B73-62AA-4C09-B688-823A4E4FB6E2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MatrixOutputLbandResourceCapabilityUpdates_1", "MatrixOutputLbandResourceCapabilityUpdates_1\MatrixOutputLbandResourceCapabilityUpdates_1.csproj", "{7808E16E-87A9-4D8C-82A5-BFBABBDD2C3C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReleaseRecordingResources", "ReleaseRecordingResources", "{C6AEDC14-DF11-4B52-BB08-6FF557237010}" + ProjectSection(SolutionItems) = preProject + ReleaseRecordingResources.xml = ReleaseRecordingResources.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{F425D415-34EF-4A22-B010-F250131034F6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReleaseRecordingResources_2", "ReleaseRecordingResources_2\ReleaseRecordingResources_2.csproj", "{DD1FEF33-10CA-4DF2-872A-D8879A8302DA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ResourceProvisioning", "ResourceProvisioning", "{C5965E3E-F9B7-457D-976B-FF198E971AEE}" + ProjectSection(SolutionItems) = preProject + ResourceProvisioning.xml = ResourceProvisioning.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{BC476C0E-2947-47EE-B395-69D71D46C179}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceProvisioning_1", "ResourceProvisioning_1\ResourceProvisioning_1.csproj", "{1098672C-C215-4912-AB71-906E6176A4AA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateOrdersAfterUserTaskStatusChange", "UpdateOrdersAfterUserTaskStatusChange", "{4254A869-193E-4AD5-B403-AA628B30E75D}" + ProjectSection(SolutionItems) = preProject + UpdateOrdersAfterUserTaskStatusChange.xml = UpdateOrdersAfterUserTaskStatusChange.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{5C8BC972-E212-4ACD-BF34-AC11F29372F2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateOrdersAfterUserTaskStatusChange_4", "UpdateOrdersAfterUserTaskStatusChange_4\UpdateOrdersAfterUserTaskStatusChange_4.csproj", "{F932902B-7C87-4E8A-B43D-FEAABBB1AB2A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateVisibilityRights", "UpdateVisibilityRights", "{AEA3EB59-34FB-455C-AD80-C93186A5BE8D}" + ProjectSection(SolutionItems) = preProject + UpdateVisibilityRights.xml = UpdateVisibilityRights.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{7E3CABB1-B098-486F-BBF9-93138E58E1B6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateVisibilityRights_1", "UpdateVisibilityRights_1\UpdateVisibilityRights_1.csproj", "{21DD38E0-3B0C-4F3E-B7B2-77869FB5471D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NonLiveLocalBackup", "NonLiveLocalBackup", "{EEA6E326-AAF9-4772-B4C1-AECF9FADAA19}" + ProjectSection(SolutionItems) = preProject + NonLiveLocalBackup.xml = NonLiveLocalBackup.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{BAA404DB-39D2-41E4-AC87-4DE55BE7B346}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NonLiveLocalBackup_1", "NonLiveLocalBackup_1\NonLiveLocalBackup_1.csproj", "{096D90EF-4ABC-40B4-85D1-E813969C40D1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{E1863B9A-556C-4B02-A74D-E47F6EFCCC5E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Integrations", "Integrations", "{000361F4-B47A-430A-A0C2-0A7086A31436}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SRM", "SRM", "{1387AD44-A709-427B-8B95-2262C0284BE5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{67FCA1BE-D816-4972-9138-F74F39F3A158}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HandleIntegrationUpdate", "HandleIntegrationUpdate", "{50BD1A91-4AE4-4595-A3E5-C3CCB29C222A}" + ProjectSection(SolutionItems) = preProject + HandleIntegrationUpdate.xml = HandleIntegrationUpdate.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{6BFD42BE-5AB6-484B-9751-18184B4602A1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandleIntegrationUpdate_4", "HandleIntegrationUpdate_4\HandleIntegrationUpdate_4.csproj", "{10DE679A-E842-4227-8120-AB0D91F02C3B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Configure Ticketing Colors", "Configure Ticketing Colors", "{08A830E5-212D-4BB4-8ABA-0C22368496AC}" + ProjectSection(SolutionItems) = preProject + Configure Ticketing Colors.xml = Configure Ticketing Colors.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{0485686F-900D-4D21-9ED6-60CB21E3F0D4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Configure Ticketing Colors_1", "Configure Ticketing Colors_1\Configure Ticketing Colors_1.csproj", "{161D23AA-B910-4826-984E-5F71E6115F3C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AggregateMetrics", "AggregateMetrics", "{704C4816-BDEA-47B7-94A7-00F3E19BD47E}" + ProjectSection(SolutionItems) = preProject + AggregateMetrics.xml = AggregateMetrics.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{7467768D-4858-4847-9A5B-97ECB096EFE8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AggregateMetrics_1", "AggregateMetrics_1\AggregateMetrics_1.csproj", "{8F19C132-61E2-4351-AC47-4653E86D7456}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RunLogCollector", "RunLogCollector", "{8E9348FF-4214-4BFE-953F-E564A2C01DFD}" + ProjectSection(SolutionItems) = preProject + RunLogCollector.xml = RunLogCollector.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{7D0320C0-C6C2-45F5-8F14-EA15BB063A90}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RunLogCollector_1", "RunLogCollector_1\RunLogCollector_1.csproj", "{CE704EE3-FC1E-48D5-A9FF-13ACB9C2E529}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateServiceStatus", "UpdateServiceStatus", "{01B3171D-AF96-4796-8388-8649053CF04E}" + ProjectSection(SolutionItems) = preProject + UpdateServiceStatus.xml = UpdateServiceStatus.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{313BAE04-DBEC-4EE2-ACF3-D85D8C8798C5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateServiceStatus_1", "UpdateServiceStatus_1\UpdateServiceStatus_1.csproj", "{15344920-AE73-4C0A-AEB2-7D75748B791E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateOrderStatus", "UpdateOrderStatus", "{DE565C75-358D-43AF-82FA-0A70925FFFB4}" + ProjectSection(SolutionItems) = preProject + UpdateOrderStatus.xml = UpdateOrderStatus.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{1CDBE1A6-3E5B-4FBE-B98F-5705633BFE9C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateOrderStatus_1", "UpdateOrderStatus_1\UpdateOrderStatus_1.csproj", "{39664900-A87E-4A6D-8BFA-EAC97F5892ED}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateOrderServiceDefinitionActions", "UpdateOrderServiceDefinitionActions", "{F9D1F2B5-1B82-4B5F-A65A-18EA75F38457}" + ProjectSection(SolutionItems) = preProject + UpdateOrderServiceDefinitionActions.xml = UpdateOrderServiceDefinitionActions.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{93D303A0-945B-403E-82D4-AC8E2CA4463F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateOrderServiceDefinitionActions_1", "UpdateOrderServiceDefinitionActions_1\UpdateOrderServiceDefinitionActions_1.csproj", "{EBDF3AD9-BE1C-43B3-ADE4-2336DE09355E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExportServiceDefinitions", "ExportServiceDefinitions", "{471F09E3-9BA6-43AB-A8F1-359D797FD136}" + ProjectSection(SolutionItems) = preProject + ExportServiceDefinitions.xml = ExportServiceDefinitions.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{DCB5C4A9-9AA5-413D-A4AA-CBBB66A0262E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExportServiceDefinitions_1", "ExportServiceDefinitions_1\ExportServiceDefinitions_1.csproj", "{54B5632D-C113-4383-913E-2701501D951D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExportProfileDefinitions", "ExportProfileDefinitions", "{1DC34F9A-8397-4B6D-8B13-175A850DECFB}" + ProjectSection(SolutionItems) = preProject + ExportProfileDefinitions.xml = ExportProfileDefinitions.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{E98FBEDE-0103-4D38-8A72-92FAE634C67E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExportProfileDefinitions_1", "ExportProfileDefinitions_1\ExportProfileDefinitions_1.csproj", "{54742C48-894C-4B28-B0D6-BF4F6CE7E76B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExportResourcePools", "ExportResourcePools", "{6D68EB04-A8B4-4843-A20E-5BFC4F07923B}" + ProjectSection(SolutionItems) = preProject + ExportResourcePools.xml = ExportResourcePools.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{477D4BB3-CA8F-4CB3-AD08-CD84CBF4215E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExportResourcePools_1", "ExportResourcePools_1\ExportResourcePools_1.csproj", "{60637559-5F48-44A1-B1F6-16AEA6B1BA01}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LoggingCleanup", "LoggingCleanup", "{4EB973CF-9705-442F-AA83-7DBE73B010D0}" + ProjectSection(SolutionItems) = preProject + LoggingCleanup.xml = LoggingCleanup.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{86C29745-85F2-4F63-9CBB-EF0F364E3633}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoggingCleanup_1", "LoggingCleanup_1\LoggingCleanup_1.csproj", "{A4619E76-5B45-4B85-B305-FD99A80EAAFF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RemoveOldServices", "RemoveOldServices", "{E12EF30F-3FD3-4A97-8BBD-FC008108298D}" + ProjectSection(SolutionItems) = preProject + RemoveOldServices.xml = RemoveOldServices.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{77EB4E23-F3B6-4259-8A37-68ADDEC79FA3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemoveOldServices_1", "RemoveOldServices_1\RemoveOldServices_1.csproj", "{A0D587EC-3860-41A7-A648-ABDE1DBB2B01}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ViewTicket", "ViewTicket", "{FA0D3054-CC09-4B44-BE75-A4BBA43CF568}" + ProjectSection(SolutionItems) = preProject + ViewTicket.xml = ViewTicket.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{FE9B754D-0964-43E7-B284-E5BFCE219339}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViewTicket_1", "ViewTicket_1\ViewTicket_1.csproj", "{AEDA5B3F-0DD4-4F00-AD27-9C74E7B58E4A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MigrateResourcesYLE", "MigrateResourcesYLE", "{761F0B1D-C5E2-4B7F-9757-2569DE22242C}" + ProjectSection(SolutionItems) = preProject + MigrateResourcesYLE.xml = MigrateResourcesYLE.xml + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MigrateResourcesYLE_1", "MigrateResourcesYLE_1\MigrateResourcesYLE_1.csproj", "{1346E39C-2A3C-45F3-B3F1-7BC486BC6C3F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{7CE65D69-9B3F-4CA8-9837-75BCB4E3F083}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RemoveIntegrationOrders", "RemoveIntegrationOrders", "{44497CF8-959A-44C6-A40B-E517BC2376A6}" + ProjectSection(SolutionItems) = preProject + RemoveIntegrationOrders.xml = RemoveIntegrationOrders.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{9357F636-7980-46DF-8AE1-967D9B52D4C7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemoveIntegrationOrders_1", "RemoveIntegrationOrders_1\RemoveIntegrationOrders_1.csproj", "{136DFCD0-EEC3-4856-88FC-875549E69567}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ForceDeleteResource", "ForceDeleteResource", "{AA4DF06F-0801-4132-8993-A5BED221A9F2}" + ProjectSection(SolutionItems) = preProject + ForceDeleteResource.xml = ForceDeleteResource.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D73D3AA8-4D8A-4820-B62C-9BB9F0C0CB3A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ForceDeleteResource_1", "ForceDeleteResource_1\ForceDeleteResource_1.csproj", "{BB6E867B-D3C5-4EB8-8A08-919A8E530753}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SendNonLiveDeletionReminders", "SendNonLiveDeletionReminders", "{8564D43C-9FD5-4B61-86F6-5F1DE20B072E}" + ProjectSection(SolutionItems) = preProject + SendNonLiveDeletionReminders.xml = SendNonLiveDeletionReminders.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{CC2F9BCC-C904-4EC8-A7D6-B45B3FC6946E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SendNonLiveDeletionReminders_1", "SendNonLiveDeletionReminders_1\SendNonLiveDeletionReminders_1.csproj", "{1BE80F2C-F652-4E36-8DA3-EFFD46BEC8AA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HandleNonLiveFolderDeletion", "HandleNonLiveFolderDeletion", "{21586975-5E83-42BD-BDB0-B34FCD5B734A}" + ProjectSection(SolutionItems) = preProject + HandleNonLiveFolderDeletion.xml = HandleNonLiveFolderDeletion.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{0B90312C-7E10-4C6F-B3EC-C580BAD0FFE9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandleNonLiveFolderDeletion_1", "HandleNonLiveFolderDeletion_1\HandleNonLiveFolderDeletion_1.csproj", "{650813DD-F043-4C38-B235-4F2986B96DF4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UpdateNonLiveUserTask", "UpdateNonLiveUserTask", "{653A4FE9-34F5-4248-AD24-2113A58731B4}" + ProjectSection(SolutionItems) = preProject + UpdateNonLiveUserTask.xml = UpdateNonLiveUserTask.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{6E66E383-08AD-49AD-AE98-062EF74A2D0A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateNonLiveUserTask_1", "UpdateNonLiveUserTask_1\UpdateNonLiveUserTask_1.csproj", "{E064C30A-5B7D-4253-B3F2-A2172F4DBF7D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibraryTests", "UnitTestProject\LibraryTests.csproj", "{F4511D97-994D-4393-BE3D-178C0DC1301A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ShowOrderHistory", "ShowOrderHistory", "{83AD0011-B9F9-41CE-993A-C82BEC443354}" + ProjectSection(SolutionItems) = preProject + ShowOrderHistory.xml = ShowOrderHistory.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{B16C0689-BE91-4470-867C-29CD41BECBE3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowOrderHistory_1", "ShowOrderHistory_1\ShowOrderHistory_1.csproj", "{E340800D-3FCB-4389-8E95-39454110F40A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CustomerUiLauncher", "CustomerUiLauncher", "{5658AB3B-3A50-4586-B407-D028CA678ADE}" + ProjectSection(SolutionItems) = preProject + CustomerUiLauncher.xml = CustomerUiLauncher.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{FB7BBE6E-9121-415B-ACAC-FE412DF3CE41}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CreateInvoiceReport", "CreateInvoiceReport", "{450B0EA2-2AFF-4CBF-9ED0-B3F230C33621}" + ProjectSection(SolutionItems) = preProject + CreateInvoiceReport.xml = CreateInvoiceReport.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{AD67A5A6-BA20-4F9E-83C7-1D0AFB9091C2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateInvoiceReport_1", "CreateInvoiceReport_1\CreateInvoiceReport_1.csproj", "{8262B019-389D-4E9A-9EE4-606D3F2023FC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddService", "AddService", "{FA87E4AC-AFBE-4811-848E-EF6AED874F59}" + ProjectSection(SolutionItems) = preProject + AddService.xml = AddService.xml + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddService_1", "AddService_1\AddService_1.csproj", "{CB5B8A98-2204-4F53-A8A8-B6BB32E85F64}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{AA75ECB6-3554-4CD6-A240-53637B392904}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{ED714ADB-432F-456C-B767-06576666A43B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Code Analysis", "Code Analysis", "{B572C23F-1A8A-4514-A785-CF1C717691EB}" + ProjectSection(SolutionItems) = preProject + Internal\Code Analysis\qaction-debug.ruleset = Internal\Code Analysis\qaction-debug.ruleset + Internal\Code Analysis\qaction-release.ruleset = Internal\Code Analysis\qaction-release.ruleset + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReprocessOrders", "ReprocessOrders", "{31293883-B73F-4DA8-9BA2-4A9930B44AA2}" + ProjectSection(SolutionItems) = preProject + ReprocessOrders.xml = ReprocessOrders.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{35CDF4F0-89D5-463D-B3BA-628F032DDCDC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReprocessOrders_1", "ReprocessOrders_1\ReprocessOrders_1.csproj", "{C99CFF53-B1BD-4FAA-A285-3C149CACE44F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StopOrder", "StopOrder", "{06C10087-A052-40BD-8101-18DB37909B14}" + ProjectSection(SolutionItems) = preProject + StopOrder.xml = StopOrder.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{19D8C4FC-AE55-436B-BC9A-EDBB80B27822}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomerUI_Launcher_2", "CustomerUI_Launcher_2\CustomerUI_Launcher_2.csproj", "{AE455D02-0572-43BA-B213-4D6BF8EDD37B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MigrateResourcesInBulkYLE", "MigrateResourcesInBulkYLE", "{83888528-487F-4071-8605-151E4F586C78}" + ProjectSection(SolutionItems) = preProject + MigrateResourcesInBulkYLE.xml = MigrateResourcesInBulkYLE.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{5A8BECBC-089B-4425-BE29-AB6F2750DAC6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MigrateResourcesInBulkYLE_1", "MigrateResourcesInBulkYLE_1\MigrateResourcesInBulkYLE_1.csproj", "{CE011088-8685-47FC-8274-2141025946D2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ProfileLoadScripts", "ProfileLoadScripts", "{2D9E833E-0229-4DA6-BC6C-2A039E925176}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PLS_EricssonRX8200_Decoding", "PLS_EricssonRX8200_Decoding", "{7E38EF2C-F2CD-40A4-9052-F5472E30CBDC}" + ProjectSection(SolutionItems) = preProject + PLS_EricssonRX8200_Decoding.xml = PLS_EricssonRX8200_Decoding.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{F85E1F14-3D62-4F7A-BEB2-B73AA16BB2F8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PLS_EricssonRX8200_Decoding_1", "PLS_EricssonRX8200_Decoding_1\PLS_EricssonRX8200_Decoding_1.csproj", "{40244095-2B04-407C-AF92-CED881D0429D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PLS_EricssonRX8200_Demodulating", "PLS_EricssonRX8200_Demodulating", "{197C8362-EB09-4F2C-A70B-2D29E5F04D21}" + ProjectSection(SolutionItems) = preProject + PLS_EricssonRX8200_Demodulating.xml = PLS_EricssonRX8200_Demodulating.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{4B4DE002-28B5-4E4A-AD2F-837DF34D5F2F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PLS_EricssonRX8200_Demodulating_1", "PLS_EricssonRX8200_Demodulating_1\PLS_EricssonRX8200_Demodulating_1.csproj", "{BAB2ACB4-1914-48FB-B141-A52C85FBDDC1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExportSrm", "ExportSrm", "{CA1F8B6F-2EA4-4A7C-B468-190B7C76E97B}" + ProjectSection(SolutionItems) = preProject + ExportSrm.xml = ExportSrm.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{F623050B-10E1-407E-91F4-0AE24EE144FB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExportSrm_1", "ExportSrm_1\ExportSrm_1.csproj", "{E6720C0D-274D-4AEF-A45E-897EBDCE0911}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StopOrder", "StopOrder_1\StopOrder.csproj", "{CEBDD8CA-8AC5-41B2-95CE-21EDA9D38AFF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{57375AE4-BFE0-4D8A-8D76-27AF0FA5479E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EditOrderTemplate", "EditOrderTemplate", "{644EE9B7-3883-4C1A-900C-0A3217CD5122}" + ProjectSection(SolutionItems) = preProject + EditOrderTemplate.xml = EditOrderTemplate.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{5EF9AA74-6CD0-4FC4-8D8F-19BECE6D5041}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EditOrderTemplate_1", "EditOrderTemplate_1\EditOrderTemplate_1.csproj", "{3BCB9CBC-A3EE-4493-B605-6EBE559F295A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ConfigureContractManager", "ConfigureContractManager", "{C66C3B0F-2B02-414E-A02C-20E40E4323CA}" + ProjectSection(SolutionItems) = preProject + ConfigureContractManager.xml = ConfigureContractManager.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{38F41597-6448-4CB2-A73B-457C53354FD6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfigureContractManager_1", "ConfigureContractManager_1\ConfigureContractManager_1.csproj", "{5D786C6B-2A75-440B-A1FB-C077E8B8B898}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SetElementCustomProperty", "SetElementCustomProperty", "{BBF714D6-0319-4D28-B531-BD06728F5E4F}" + ProjectSection(SolutionItems) = preProject + SetElementCustomProperty.xml = SetElementCustomProperty.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{09CDBAFA-14B3-4C0D-A604-56AB25627D75}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetElementCustomProperty_1", "SetElementCustomProperty_1\SetElementCustomProperty_1.csproj", "{9F5AFB87-3F4F-40A9-A76F-BFC6C78BD59B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NonLiveOrderAndNotesCleanup", "NonLiveOrderAndNotesCleanup", "{ECD7B20D-BB60-447D-9379-CB231CED783D}" + ProjectSection(SolutionItems) = preProject + NonLiveOrderAndNotesCleanup.xml = NonLiveOrderAndNotesCleanup.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{99DE7371-2C7F-49CB-BE2D-03C2C6DB4ABB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NonLiveOrderAndNotesCleanup_1", "NonLiveOrderAndNotesCleanup_1\NonLiveOrderAndNotesCleanup_1.csproj", "{394C3304-3228-4F16-AD8A-06D7B32A3D46}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library", "Library", "{6337C220-C88D-40F6-8430-5D587AAAA6E1}" + ProjectSection(SolutionItems) = preProject + Library.xml = Library.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{1A8EC1C6-6712-4C84-9495-1E6B9C7C0695}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Library_1", "Library_1\Library_1.csproj", "{121DD302-DF4B-4F49-B6F9-B3AD358BD842}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnassignTicket", "UnassignTicket", "{9184AD19-8580-4A8F-8220-8A679639C57F}" + ProjectSection(SolutionItems) = preProject + UnassignTicket.xml = UnassignTicket.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{D1E71180-9B7B-40BB-831D-48BB98F0A834}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnassignTicket_1", "UnassignTicket_1\UnassignTicket_1.csproj", "{033DCC6B-9081-4119-8F9E-F51B834992CC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NonLiveUserTasksBulkUpdate", "NonLiveUserTasksBulkUpdate", "{A1466055-9F55-4B87-8D6F-323E4F0EA85C}" + ProjectSection(SolutionItems) = preProject + NonLiveUserTasksBulkUpdate.xml = NonLiveUserTasksBulkUpdate.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{06F7B8FB-7357-4F31-93CF-E76050F07224}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NonLiveUserTasksBulkUpdate_1", "NonLiveUserTasksBulkUpdate_1\NonLiveUserTasksBulkUpdate_1.csproj", "{4AC66D72-FD8B-40B3-9236-C76F97FFD487}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PLS_NovelsatNS2000_Demodulating", "PLS_NovelsatNS2000_Demodulating", "{72128F4D-352C-4DEF-BA5A-DAB4A2A7CC93}" + ProjectSection(SolutionItems) = preProject + PLS_NovelsatNS2000_Demodulating.xml = PLS_NovelsatNS2000_Demodulating.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{B257C040-9707-4DF4-93BB-F7151D0C0702}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PLS_NovelsatNS2000_Demodulating_1", "PLS_NovelsatNS2000_Demodulating_1\PLS_NovelsatNS2000_Demodulating_1.csproj", "{130FBF70-7031-4F7C-92AC-2C616442F18D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FileRetrieval", "FileRetrieval", "{50494B33-0532-42E6-AF1F-05BA2F7B8D81}" + ProjectSection(SolutionItems) = preProject + FileRetrieval.xml = FileRetrieval.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{B7B98608-DFC0-47A9-AA5A-760D948D7DE1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileRetrieval_1", "FileRetrieval_1\FileRetrieval_1.csproj", "{56BC6E17-FC0B-4AB5-BFB2-B92344E707FA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8EBFE2CE-07A1-45F6-85AC-8023014A0A8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EBFE2CE-07A1-45F6-85AC-8023014A0A8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EBFE2CE-07A1-45F6-85AC-8023014A0A8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EBFE2CE-07A1-45F6-85AC-8023014A0A8A}.Release|Any CPU.Build.0 = Release|Any CPU + {880203DF-F9E6-4888-9978-A2FBE22BD25A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {880203DF-F9E6-4888-9978-A2FBE22BD25A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {880203DF-F9E6-4888-9978-A2FBE22BD25A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {880203DF-F9E6-4888-9978-A2FBE22BD25A}.Release|Any CPU.Build.0 = Release|Any CPU + {E5C344F3-4239-4F98-BF5B-642646B0A68A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5C344F3-4239-4F98-BF5B-642646B0A68A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5C344F3-4239-4F98-BF5B-642646B0A68A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5C344F3-4239-4F98-BF5B-642646B0A68A}.Release|Any CPU.Build.0 = Release|Any CPU + {CD8CA3A7-2D4D-416A-BB82-76279B1843C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD8CA3A7-2D4D-416A-BB82-76279B1843C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD8CA3A7-2D4D-416A-BB82-76279B1843C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD8CA3A7-2D4D-416A-BB82-76279B1843C2}.Release|Any CPU.Build.0 = Release|Any CPU + {6846E9D4-264E-4FFD-876D-88BFBDAFE69F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6846E9D4-264E-4FFD-876D-88BFBDAFE69F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6846E9D4-264E-4FFD-876D-88BFBDAFE69F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6846E9D4-264E-4FFD-876D-88BFBDAFE69F}.Release|Any CPU.Build.0 = Release|Any CPU + {E10BD658-9B0E-4A95-97B7-C288C429C094}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E10BD658-9B0E-4A95-97B7-C288C429C094}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E10BD658-9B0E-4A95-97B7-C288C429C094}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E10BD658-9B0E-4A95-97B7-C288C429C094}.Release|Any CPU.Build.0 = Release|Any CPU + {CFA4A2CE-A230-4303-83B1-677B23B66266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CFA4A2CE-A230-4303-83B1-677B23B66266}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFA4A2CE-A230-4303-83B1-677B23B66266}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CFA4A2CE-A230-4303-83B1-677B23B66266}.Release|Any CPU.Build.0 = Release|Any CPU + {7F6A3EC0-1B12-4F2A-B0F8-1EBA1C113460}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F6A3EC0-1B12-4F2A-B0F8-1EBA1C113460}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F6A3EC0-1B12-4F2A-B0F8-1EBA1C113460}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F6A3EC0-1B12-4F2A-B0F8-1EBA1C113460}.Release|Any CPU.Build.0 = Release|Any CPU + {E69808C1-8776-4055-8385-05CCE596C4E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E69808C1-8776-4055-8385-05CCE596C4E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E69808C1-8776-4055-8385-05CCE596C4E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E69808C1-8776-4055-8385-05CCE596C4E5}.Release|Any CPU.Build.0 = Release|Any CPU + {98F1FA3D-7B10-4178-A6A4-41F6958CCBE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {98F1FA3D-7B10-4178-A6A4-41F6958CCBE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {98F1FA3D-7B10-4178-A6A4-41F6958CCBE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {98F1FA3D-7B10-4178-A6A4-41F6958CCBE5}.Release|Any CPU.Build.0 = Release|Any CPU + {A90B225A-0F85-416B-9CE8-EEBDF2929BC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A90B225A-0F85-416B-9CE8-EEBDF2929BC4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A90B225A-0F85-416B-9CE8-EEBDF2929BC4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A90B225A-0F85-416B-9CE8-EEBDF2929BC4}.Release|Any CPU.Build.0 = Release|Any CPU + {48F1B70D-8C96-49BA-B4A2-957377393EEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48F1B70D-8C96-49BA-B4A2-957377393EEF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48F1B70D-8C96-49BA-B4A2-957377393EEF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48F1B70D-8C96-49BA-B4A2-957377393EEF}.Release|Any CPU.Build.0 = Release|Any CPU + {C11D6283-7A34-4CDD-8C27-65F8499E5CFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C11D6283-7A34-4CDD-8C27-65F8499E5CFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C11D6283-7A34-4CDD-8C27-65F8499E5CFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C11D6283-7A34-4CDD-8C27-65F8499E5CFE}.Release|Any CPU.Build.0 = Release|Any CPU + {C37BA915-33E8-48C6-9098-6681EE54884D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C37BA915-33E8-48C6-9098-6681EE54884D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C37BA915-33E8-48C6-9098-6681EE54884D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C37BA915-33E8-48C6-9098-6681EE54884D}.Release|Any CPU.Build.0 = Release|Any CPU + {2C70A6EE-70B7-42C0-8C0B-66C690AB8C87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C70A6EE-70B7-42C0-8C0B-66C690AB8C87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C70A6EE-70B7-42C0-8C0B-66C690AB8C87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C70A6EE-70B7-42C0-8C0B-66C690AB8C87}.Release|Any CPU.Build.0 = Release|Any CPU + {F44EB030-BD0E-42AB-82BD-5E7E0F530A24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F44EB030-BD0E-42AB-82BD-5E7E0F530A24}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F44EB030-BD0E-42AB-82BD-5E7E0F530A24}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F44EB030-BD0E-42AB-82BD-5E7E0F530A24}.Release|Any CPU.Build.0 = Release|Any CPU + {96C98AA8-D5D5-4F3D-AC36-DFB044A10283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96C98AA8-D5D5-4F3D-AC36-DFB044A10283}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96C98AA8-D5D5-4F3D-AC36-DFB044A10283}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96C98AA8-D5D5-4F3D-AC36-DFB044A10283}.Release|Any CPU.Build.0 = Release|Any CPU + {D3966891-3616-427F-BC24-CEBAD4B3B6BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3966891-3616-427F-BC24-CEBAD4B3B6BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3966891-3616-427F-BC24-CEBAD4B3B6BE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3966891-3616-427F-BC24-CEBAD4B3B6BE}.Release|Any CPU.Build.0 = Release|Any CPU + {FAFEE1DA-438D-4D7F-91B1-9BB2444DB30E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FAFEE1DA-438D-4D7F-91B1-9BB2444DB30E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FAFEE1DA-438D-4D7F-91B1-9BB2444DB30E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FAFEE1DA-438D-4D7F-91B1-9BB2444DB30E}.Release|Any CPU.Build.0 = Release|Any CPU + {DA97B418-6D04-4FA2-8214-6FE3113E02C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA97B418-6D04-4FA2-8214-6FE3113E02C7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA97B418-6D04-4FA2-8214-6FE3113E02C7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA97B418-6D04-4FA2-8214-6FE3113E02C7}.Release|Any CPU.Build.0 = Release|Any CPU + {DD92F97D-EA78-4377-8DB7-63D1C6048670}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD92F97D-EA78-4377-8DB7-63D1C6048670}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD92F97D-EA78-4377-8DB7-63D1C6048670}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD92F97D-EA78-4377-8DB7-63D1C6048670}.Release|Any CPU.Build.0 = Release|Any CPU + {891D09C7-E16C-4467-BDEE-BDAAB5552B7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {891D09C7-E16C-4467-BDEE-BDAAB5552B7A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {891D09C7-E16C-4467-BDEE-BDAAB5552B7A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {891D09C7-E16C-4467-BDEE-BDAAB5552B7A}.Release|Any CPU.Build.0 = Release|Any CPU + {A3B23699-5387-4266-B784-C7AE207E6923}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3B23699-5387-4266-B784-C7AE207E6923}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3B23699-5387-4266-B784-C7AE207E6923}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3B23699-5387-4266-B784-C7AE207E6923}.Release|Any CPU.Build.0 = Release|Any CPU + {BA41DE74-F49C-4C07-A83D-2317566E7808}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA41DE74-F49C-4C07-A83D-2317566E7808}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA41DE74-F49C-4C07-A83D-2317566E7808}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA41DE74-F49C-4C07-A83D-2317566E7808}.Release|Any CPU.Build.0 = Release|Any CPU + {80B82340-D9C3-431F-9B22-947F6DDAE0F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80B82340-D9C3-431F-9B22-947F6DDAE0F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80B82340-D9C3-431F-9B22-947F6DDAE0F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80B82340-D9C3-431F-9B22-947F6DDAE0F6}.Release|Any CPU.Build.0 = Release|Any CPU + {74B56470-25B2-4846-810D-53560F6EB5F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74B56470-25B2-4846-810D-53560F6EB5F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74B56470-25B2-4846-810D-53560F6EB5F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74B56470-25B2-4846-810D-53560F6EB5F1}.Release|Any CPU.Build.0 = Release|Any CPU + {5C73EE37-B28D-476A-825E-4EF73D0F6D80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C73EE37-B28D-476A-825E-4EF73D0F6D80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C73EE37-B28D-476A-825E-4EF73D0F6D80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C73EE37-B28D-476A-825E-4EF73D0F6D80}.Release|Any CPU.Build.0 = Release|Any CPU + {61FCF96E-F3D6-4609-9D75-78D9582E692D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61FCF96E-F3D6-4609-9D75-78D9582E692D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61FCF96E-F3D6-4609-9D75-78D9582E692D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61FCF96E-F3D6-4609-9D75-78D9582E692D}.Release|Any CPU.Build.0 = Release|Any CPU + {BF317DEB-2946-49C4-A6D2-3A0B4175AF64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF317DEB-2946-49C4-A6D2-3A0B4175AF64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF317DEB-2946-49C4-A6D2-3A0B4175AF64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF317DEB-2946-49C4-A6D2-3A0B4175AF64}.Release|Any CPU.Build.0 = Release|Any CPU + {951F433D-47BB-46CD-9577-38DC2EEF38F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {951F433D-47BB-46CD-9577-38DC2EEF38F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {951F433D-47BB-46CD-9577-38DC2EEF38F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {951F433D-47BB-46CD-9577-38DC2EEF38F1}.Release|Any CPU.Build.0 = Release|Any CPU + {92B8FAFF-3EBC-4C12-91AB-71A8B6E0EC1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {92B8FAFF-3EBC-4C12-91AB-71A8B6E0EC1C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {92B8FAFF-3EBC-4C12-91AB-71A8B6E0EC1C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {92B8FAFF-3EBC-4C12-91AB-71A8B6E0EC1C}.Release|Any CPU.Build.0 = Release|Any CPU + {6C8B2D4E-6B4E-4F71-AA72-BF0BB37D6DAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C8B2D4E-6B4E-4F71-AA72-BF0BB37D6DAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C8B2D4E-6B4E-4F71-AA72-BF0BB37D6DAD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C8B2D4E-6B4E-4F71-AA72-BF0BB37D6DAD}.Release|Any CPU.Build.0 = Release|Any CPU + {66B48A43-2EA8-4463-81B5-D842A49DBD73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66B48A43-2EA8-4463-81B5-D842A49DBD73}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66B48A43-2EA8-4463-81B5-D842A49DBD73}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66B48A43-2EA8-4463-81B5-D842A49DBD73}.Release|Any CPU.Build.0 = Release|Any CPU + {30536342-FF9E-4B4E-8679-55DDF1583BCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30536342-FF9E-4B4E-8679-55DDF1583BCE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30536342-FF9E-4B4E-8679-55DDF1583BCE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30536342-FF9E-4B4E-8679-55DDF1583BCE}.Release|Any CPU.Build.0 = Release|Any CPU + {1A694B8E-C1E4-4BC2-A5F3-F658EB733EDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A694B8E-C1E4-4BC2-A5F3-F658EB733EDB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A694B8E-C1E4-4BC2-A5F3-F658EB733EDB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A694B8E-C1E4-4BC2-A5F3-F658EB733EDB}.Release|Any CPU.Build.0 = Release|Any CPU + {86177A39-B69B-40BC-AAA4-E5DDDCE80B54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86177A39-B69B-40BC-AAA4-E5DDDCE80B54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86177A39-B69B-40BC-AAA4-E5DDDCE80B54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86177A39-B69B-40BC-AAA4-E5DDDCE80B54}.Release|Any CPU.Build.0 = Release|Any CPU + {3FF581CD-E646-48CE-8611-159999784EDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3FF581CD-E646-48CE-8611-159999784EDB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FF581CD-E646-48CE-8611-159999784EDB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3FF581CD-E646-48CE-8611-159999784EDB}.Release|Any CPU.Build.0 = Release|Any CPU + {6BDE17DC-A368-4EB8-9BA5-222E2E8469D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BDE17DC-A368-4EB8-9BA5-222E2E8469D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BDE17DC-A368-4EB8-9BA5-222E2E8469D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BDE17DC-A368-4EB8-9BA5-222E2E8469D1}.Release|Any CPU.Build.0 = Release|Any CPU + {24C6898B-ACF8-4406-8767-4EB388950D3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24C6898B-ACF8-4406-8767-4EB388950D3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24C6898B-ACF8-4406-8767-4EB388950D3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24C6898B-ACF8-4406-8767-4EB388950D3B}.Release|Any CPU.Build.0 = Release|Any CPU + {2F80BDCE-7606-4F23-99CE-B980E1E8C70E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F80BDCE-7606-4F23-99CE-B980E1E8C70E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F80BDCE-7606-4F23-99CE-B980E1E8C70E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F80BDCE-7606-4F23-99CE-B980E1E8C70E}.Release|Any CPU.Build.0 = Release|Any CPU + {C5A5B136-224B-43B4-B220-C677BF4D8294}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5A5B136-224B-43B4-B220-C677BF4D8294}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5A5B136-224B-43B4-B220-C677BF4D8294}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5A5B136-224B-43B4-B220-C677BF4D8294}.Release|Any CPU.Build.0 = Release|Any CPU + {DB1D40BF-6C1B-4565-B629-4647834B8F40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB1D40BF-6C1B-4565-B629-4647834B8F40}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB1D40BF-6C1B-4565-B629-4647834B8F40}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB1D40BF-6C1B-4565-B629-4647834B8F40}.Release|Any CPU.Build.0 = Release|Any CPU + {316025D1-B4C1-4053-87E4-34DC46FF7B23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {316025D1-B4C1-4053-87E4-34DC46FF7B23}.Debug|Any CPU.Build.0 = Debug|Any CPU + {316025D1-B4C1-4053-87E4-34DC46FF7B23}.Release|Any CPU.ActiveCfg = Release|Any CPU + {316025D1-B4C1-4053-87E4-34DC46FF7B23}.Release|Any CPU.Build.0 = Release|Any CPU + {7808E16E-87A9-4D8C-82A5-BFBABBDD2C3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7808E16E-87A9-4D8C-82A5-BFBABBDD2C3C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7808E16E-87A9-4D8C-82A5-BFBABBDD2C3C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7808E16E-87A9-4D8C-82A5-BFBABBDD2C3C}.Release|Any CPU.Build.0 = Release|Any CPU + {DD1FEF33-10CA-4DF2-872A-D8879A8302DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD1FEF33-10CA-4DF2-872A-D8879A8302DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD1FEF33-10CA-4DF2-872A-D8879A8302DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD1FEF33-10CA-4DF2-872A-D8879A8302DA}.Release|Any CPU.Build.0 = Release|Any CPU + {1098672C-C215-4912-AB71-906E6176A4AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1098672C-C215-4912-AB71-906E6176A4AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1098672C-C215-4912-AB71-906E6176A4AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1098672C-C215-4912-AB71-906E6176A4AA}.Release|Any CPU.Build.0 = Release|Any CPU + {F932902B-7C87-4E8A-B43D-FEAABBB1AB2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F932902B-7C87-4E8A-B43D-FEAABBB1AB2A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F932902B-7C87-4E8A-B43D-FEAABBB1AB2A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F932902B-7C87-4E8A-B43D-FEAABBB1AB2A}.Release|Any CPU.Build.0 = Release|Any CPU + {21DD38E0-3B0C-4F3E-B7B2-77869FB5471D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21DD38E0-3B0C-4F3E-B7B2-77869FB5471D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21DD38E0-3B0C-4F3E-B7B2-77869FB5471D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21DD38E0-3B0C-4F3E-B7B2-77869FB5471D}.Release|Any CPU.Build.0 = Release|Any CPU + {096D90EF-4ABC-40B4-85D1-E813969C40D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {096D90EF-4ABC-40B4-85D1-E813969C40D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {096D90EF-4ABC-40B4-85D1-E813969C40D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {096D90EF-4ABC-40B4-85D1-E813969C40D1}.Release|Any CPU.Build.0 = Release|Any CPU + {10DE679A-E842-4227-8120-AB0D91F02C3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10DE679A-E842-4227-8120-AB0D91F02C3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10DE679A-E842-4227-8120-AB0D91F02C3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10DE679A-E842-4227-8120-AB0D91F02C3B}.Release|Any CPU.Build.0 = Release|Any CPU + {161D23AA-B910-4826-984E-5F71E6115F3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {161D23AA-B910-4826-984E-5F71E6115F3C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {161D23AA-B910-4826-984E-5F71E6115F3C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {161D23AA-B910-4826-984E-5F71E6115F3C}.Release|Any CPU.Build.0 = Release|Any CPU + {8F19C132-61E2-4351-AC47-4653E86D7456}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F19C132-61E2-4351-AC47-4653E86D7456}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8F19C132-61E2-4351-AC47-4653E86D7456}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8F19C132-61E2-4351-AC47-4653E86D7456}.Release|Any CPU.Build.0 = Release|Any CPU + {CE704EE3-FC1E-48D5-A9FF-13ACB9C2E529}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE704EE3-FC1E-48D5-A9FF-13ACB9C2E529}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE704EE3-FC1E-48D5-A9FF-13ACB9C2E529}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE704EE3-FC1E-48D5-A9FF-13ACB9C2E529}.Release|Any CPU.Build.0 = Release|Any CPU + {15344920-AE73-4C0A-AEB2-7D75748B791E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15344920-AE73-4C0A-AEB2-7D75748B791E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {15344920-AE73-4C0A-AEB2-7D75748B791E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15344920-AE73-4C0A-AEB2-7D75748B791E}.Release|Any CPU.Build.0 = Release|Any CPU + {39664900-A87E-4A6D-8BFA-EAC97F5892ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39664900-A87E-4A6D-8BFA-EAC97F5892ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39664900-A87E-4A6D-8BFA-EAC97F5892ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39664900-A87E-4A6D-8BFA-EAC97F5892ED}.Release|Any CPU.Build.0 = Release|Any CPU + {EBDF3AD9-BE1C-43B3-ADE4-2336DE09355E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EBDF3AD9-BE1C-43B3-ADE4-2336DE09355E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EBDF3AD9-BE1C-43B3-ADE4-2336DE09355E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EBDF3AD9-BE1C-43B3-ADE4-2336DE09355E}.Release|Any CPU.Build.0 = Release|Any CPU + {54B5632D-C113-4383-913E-2701501D951D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54B5632D-C113-4383-913E-2701501D951D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54B5632D-C113-4383-913E-2701501D951D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54B5632D-C113-4383-913E-2701501D951D}.Release|Any CPU.Build.0 = Release|Any CPU + {54742C48-894C-4B28-B0D6-BF4F6CE7E76B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54742C48-894C-4B28-B0D6-BF4F6CE7E76B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54742C48-894C-4B28-B0D6-BF4F6CE7E76B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54742C48-894C-4B28-B0D6-BF4F6CE7E76B}.Release|Any CPU.Build.0 = Release|Any CPU + {60637559-5F48-44A1-B1F6-16AEA6B1BA01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60637559-5F48-44A1-B1F6-16AEA6B1BA01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60637559-5F48-44A1-B1F6-16AEA6B1BA01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60637559-5F48-44A1-B1F6-16AEA6B1BA01}.Release|Any CPU.Build.0 = Release|Any CPU + {A4619E76-5B45-4B85-B305-FD99A80EAAFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4619E76-5B45-4B85-B305-FD99A80EAAFF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4619E76-5B45-4B85-B305-FD99A80EAAFF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4619E76-5B45-4B85-B305-FD99A80EAAFF}.Release|Any CPU.Build.0 = Release|Any CPU + {A0D587EC-3860-41A7-A648-ABDE1DBB2B01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0D587EC-3860-41A7-A648-ABDE1DBB2B01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0D587EC-3860-41A7-A648-ABDE1DBB2B01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0D587EC-3860-41A7-A648-ABDE1DBB2B01}.Release|Any CPU.Build.0 = Release|Any CPU + {AEDA5B3F-0DD4-4F00-AD27-9C74E7B58E4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEDA5B3F-0DD4-4F00-AD27-9C74E7B58E4A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEDA5B3F-0DD4-4F00-AD27-9C74E7B58E4A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AEDA5B3F-0DD4-4F00-AD27-9C74E7B58E4A}.Release|Any CPU.Build.0 = Release|Any CPU + {1346E39C-2A3C-45F3-B3F1-7BC486BC6C3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1346E39C-2A3C-45F3-B3F1-7BC486BC6C3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1346E39C-2A3C-45F3-B3F1-7BC486BC6C3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1346E39C-2A3C-45F3-B3F1-7BC486BC6C3F}.Release|Any CPU.Build.0 = Release|Any CPU + {136DFCD0-EEC3-4856-88FC-875549E69567}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {136DFCD0-EEC3-4856-88FC-875549E69567}.Debug|Any CPU.Build.0 = Debug|Any CPU + {136DFCD0-EEC3-4856-88FC-875549E69567}.Release|Any CPU.ActiveCfg = Release|Any CPU + {136DFCD0-EEC3-4856-88FC-875549E69567}.Release|Any CPU.Build.0 = Release|Any CPU + {BB6E867B-D3C5-4EB8-8A08-919A8E530753}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB6E867B-D3C5-4EB8-8A08-919A8E530753}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB6E867B-D3C5-4EB8-8A08-919A8E530753}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB6E867B-D3C5-4EB8-8A08-919A8E530753}.Release|Any CPU.Build.0 = Release|Any CPU + {1BE80F2C-F652-4E36-8DA3-EFFD46BEC8AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1BE80F2C-F652-4E36-8DA3-EFFD46BEC8AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1BE80F2C-F652-4E36-8DA3-EFFD46BEC8AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1BE80F2C-F652-4E36-8DA3-EFFD46BEC8AA}.Release|Any CPU.Build.0 = Release|Any CPU + {650813DD-F043-4C38-B235-4F2986B96DF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {650813DD-F043-4C38-B235-4F2986B96DF4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {650813DD-F043-4C38-B235-4F2986B96DF4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {650813DD-F043-4C38-B235-4F2986B96DF4}.Release|Any CPU.Build.0 = Release|Any CPU + {E064C30A-5B7D-4253-B3F2-A2172F4DBF7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E064C30A-5B7D-4253-B3F2-A2172F4DBF7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E064C30A-5B7D-4253-B3F2-A2172F4DBF7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E064C30A-5B7D-4253-B3F2-A2172F4DBF7D}.Release|Any CPU.Build.0 = Release|Any CPU + {F4511D97-994D-4393-BE3D-178C0DC1301A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F4511D97-994D-4393-BE3D-178C0DC1301A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F4511D97-994D-4393-BE3D-178C0DC1301A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F4511D97-994D-4393-BE3D-178C0DC1301A}.Release|Any CPU.Build.0 = Release|Any CPU + {E340800D-3FCB-4389-8E95-39454110F40A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E340800D-3FCB-4389-8E95-39454110F40A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E340800D-3FCB-4389-8E95-39454110F40A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E340800D-3FCB-4389-8E95-39454110F40A}.Release|Any CPU.Build.0 = Release|Any CPU + {8262B019-389D-4E9A-9EE4-606D3F2023FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8262B019-389D-4E9A-9EE4-606D3F2023FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8262B019-389D-4E9A-9EE4-606D3F2023FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8262B019-389D-4E9A-9EE4-606D3F2023FC}.Release|Any CPU.Build.0 = Release|Any CPU + {CB5B8A98-2204-4F53-A8A8-B6BB32E85F64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB5B8A98-2204-4F53-A8A8-B6BB32E85F64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB5B8A98-2204-4F53-A8A8-B6BB32E85F64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB5B8A98-2204-4F53-A8A8-B6BB32E85F64}.Release|Any CPU.Build.0 = Release|Any CPU + {C99CFF53-B1BD-4FAA-A285-3C149CACE44F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C99CFF53-B1BD-4FAA-A285-3C149CACE44F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C99CFF53-B1BD-4FAA-A285-3C149CACE44F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C99CFF53-B1BD-4FAA-A285-3C149CACE44F}.Release|Any CPU.Build.0 = Release|Any CPU + {AE455D02-0572-43BA-B213-4D6BF8EDD37B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE455D02-0572-43BA-B213-4D6BF8EDD37B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE455D02-0572-43BA-B213-4D6BF8EDD37B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE455D02-0572-43BA-B213-4D6BF8EDD37B}.Release|Any CPU.Build.0 = Release|Any CPU + {CE011088-8685-47FC-8274-2141025946D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE011088-8685-47FC-8274-2141025946D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE011088-8685-47FC-8274-2141025946D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE011088-8685-47FC-8274-2141025946D2}.Release|Any CPU.Build.0 = Release|Any CPU + {40244095-2B04-407C-AF92-CED881D0429D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40244095-2B04-407C-AF92-CED881D0429D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40244095-2B04-407C-AF92-CED881D0429D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40244095-2B04-407C-AF92-CED881D0429D}.Release|Any CPU.Build.0 = Release|Any CPU + {BAB2ACB4-1914-48FB-B141-A52C85FBDDC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAB2ACB4-1914-48FB-B141-A52C85FBDDC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAB2ACB4-1914-48FB-B141-A52C85FBDDC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAB2ACB4-1914-48FB-B141-A52C85FBDDC1}.Release|Any CPU.Build.0 = Release|Any CPU + {E6720C0D-274D-4AEF-A45E-897EBDCE0911}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E6720C0D-274D-4AEF-A45E-897EBDCE0911}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E6720C0D-274D-4AEF-A45E-897EBDCE0911}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E6720C0D-274D-4AEF-A45E-897EBDCE0911}.Release|Any CPU.Build.0 = Release|Any CPU + {CEBDD8CA-8AC5-41B2-95CE-21EDA9D38AFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CEBDD8CA-8AC5-41B2-95CE-21EDA9D38AFF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CEBDD8CA-8AC5-41B2-95CE-21EDA9D38AFF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CEBDD8CA-8AC5-41B2-95CE-21EDA9D38AFF}.Release|Any CPU.Build.0 = Release|Any CPU + {3BCB9CBC-A3EE-4493-B605-6EBE559F295A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BCB9CBC-A3EE-4493-B605-6EBE559F295A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BCB9CBC-A3EE-4493-B605-6EBE559F295A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BCB9CBC-A3EE-4493-B605-6EBE559F295A}.Release|Any CPU.Build.0 = Release|Any CPU + {5D786C6B-2A75-440B-A1FB-C077E8B8B898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D786C6B-2A75-440B-A1FB-C077E8B8B898}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D786C6B-2A75-440B-A1FB-C077E8B8B898}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D786C6B-2A75-440B-A1FB-C077E8B8B898}.Release|Any CPU.Build.0 = Release|Any CPU + {9F5AFB87-3F4F-40A9-A76F-BFC6C78BD59B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9F5AFB87-3F4F-40A9-A76F-BFC6C78BD59B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9F5AFB87-3F4F-40A9-A76F-BFC6C78BD59B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9F5AFB87-3F4F-40A9-A76F-BFC6C78BD59B}.Release|Any CPU.Build.0 = Release|Any CPU + {394C3304-3228-4F16-AD8A-06D7B32A3D46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {394C3304-3228-4F16-AD8A-06D7B32A3D46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {394C3304-3228-4F16-AD8A-06D7B32A3D46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {394C3304-3228-4F16-AD8A-06D7B32A3D46}.Release|Any CPU.Build.0 = Release|Any CPU + {121DD302-DF4B-4F49-B6F9-B3AD358BD842}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {121DD302-DF4B-4F49-B6F9-B3AD358BD842}.Debug|Any CPU.Build.0 = Debug|Any CPU + {121DD302-DF4B-4F49-B6F9-B3AD358BD842}.Release|Any CPU.ActiveCfg = Release|Any CPU + {121DD302-DF4B-4F49-B6F9-B3AD358BD842}.Release|Any CPU.Build.0 = Release|Any CPU + {033DCC6B-9081-4119-8F9E-F51B834992CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {033DCC6B-9081-4119-8F9E-F51B834992CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {033DCC6B-9081-4119-8F9E-F51B834992CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {033DCC6B-9081-4119-8F9E-F51B834992CC}.Release|Any CPU.Build.0 = Release|Any CPU + {4AC66D72-FD8B-40B3-9236-C76F97FFD487}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4AC66D72-FD8B-40B3-9236-C76F97FFD487}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4AC66D72-FD8B-40B3-9236-C76F97FFD487}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4AC66D72-FD8B-40B3-9236-C76F97FFD487}.Release|Any CPU.Build.0 = Release|Any CPU + {130FBF70-7031-4F7C-92AC-2C616442F18D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {130FBF70-7031-4F7C-92AC-2C616442F18D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {130FBF70-7031-4F7C-92AC-2C616442F18D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {130FBF70-7031-4F7C-92AC-2C616442F18D}.Release|Any CPU.Build.0 = Release|Any CPU + {56BC6E17-FC0B-4AB5-BFB2-B92344E707FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {56BC6E17-FC0B-4AB5-BFB2-B92344E707FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {56BC6E17-FC0B-4AB5-BFB2-B92344E707FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {56BC6E17-FC0B-4AB5-BFB2-B92344E707FA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {0A0FBC87-CC98-42F9-9A0A-8E9BA7BFFCD5} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {ACC68C00-F79A-4901-AD56-56608A4ED459} = {0A0FBC87-CC98-42F9-9A0A-8E9BA7BFFCD5} + {8EBFE2CE-07A1-45F6-85AC-8023014A0A8A} = {ACC68C00-F79A-4901-AD56-56608A4ED459} + {AAAB9A5A-635B-436F-8C37-EC7AEC4E2CD6} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {021CDAC2-FA64-47D4-B135-BE88307070F3} = {AAAB9A5A-635B-436F-8C37-EC7AEC4E2CD6} + {880203DF-F9E6-4888-9978-A2FBE22BD25A} = {021CDAC2-FA64-47D4-B135-BE88307070F3} + {8CA3AB2F-92C6-4C50-8D9E-CA2B47C2C3D8} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {E538F135-D7F1-4D06-B4FA-42CC9B2045C0} = {8CA3AB2F-92C6-4C50-8D9E-CA2B47C2C3D8} + {E5C344F3-4239-4F98-BF5B-642646B0A68A} = {E538F135-D7F1-4D06-B4FA-42CC9B2045C0} + {F2457324-04D1-4703-91D4-30CB9046C94F} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {D54F9F07-8ED9-4511-A572-57AA57D7ABEE} = {F2457324-04D1-4703-91D4-30CB9046C94F} + {CD8CA3A7-2D4D-416A-BB82-76279B1843C2} = {D54F9F07-8ED9-4511-A572-57AA57D7ABEE} + {D6AA01DF-D60F-497E-A29D-28268B164B8D} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {E20DDD90-B221-4873-A9F9-7F831F17FF95} = {D6AA01DF-D60F-497E-A29D-28268B164B8D} + {6846E9D4-264E-4FFD-876D-88BFBDAFE69F} = {E20DDD90-B221-4873-A9F9-7F831F17FF95} + {42DE3F58-875F-49A2-8BB3-AE9ABB6ABD98} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {EB2D434B-1053-42C1-95B0-3A1C8112DA49} = {42DE3F58-875F-49A2-8BB3-AE9ABB6ABD98} + {E10BD658-9B0E-4A95-97B7-C288C429C094} = {EB2D434B-1053-42C1-95B0-3A1C8112DA49} + {5A7E4CE3-E5F2-46FB-80F8-AAF2EA16D5E4} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {FAA052F2-328B-41A2-9A2B-CCD32A7517A3} = {5A7E4CE3-E5F2-46FB-80F8-AAF2EA16D5E4} + {CFA4A2CE-A230-4303-83B1-677B23B66266} = {FAA052F2-328B-41A2-9A2B-CCD32A7517A3} + {2FCA2E8E-D20D-421A-8F6B-4641DF47CF84} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {7BBC9237-2D49-4C6F-BDC6-0B495FD43FB6} = {2FCA2E8E-D20D-421A-8F6B-4641DF47CF84} + {7F6A3EC0-1B12-4F2A-B0F8-1EBA1C113460} = {7BBC9237-2D49-4C6F-BDC6-0B495FD43FB6} + {96FD05B9-272B-4AC4-81AB-A8D411823A37} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {D5E91541-FE1E-48BB-BCA2-EF80BF0F4381} = {96FD05B9-272B-4AC4-81AB-A8D411823A37} + {E69808C1-8776-4055-8385-05CCE596C4E5} = {D5E91541-FE1E-48BB-BCA2-EF80BF0F4381} + {5C85A61A-EED6-4A1D-9BA0-245900C0B493} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {91324E15-E4A3-4C49-9385-7F311012AB3D} = {5C85A61A-EED6-4A1D-9BA0-245900C0B493} + {98F1FA3D-7B10-4178-A6A4-41F6958CCBE5} = {91324E15-E4A3-4C49-9385-7F311012AB3D} + {985ED6EE-AC9D-4BD4-88D7-06CC4740ACD1} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {D9C0DE7D-885D-4CB3-80FA-2A653026A28E} = {985ED6EE-AC9D-4BD4-88D7-06CC4740ACD1} + {A90B225A-0F85-416B-9CE8-EEBDF2929BC4} = {D9C0DE7D-885D-4CB3-80FA-2A653026A28E} + {2A8BDC9C-C864-46B7-98A0-ECC9BA0ECDFF} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {5B9A381F-95C5-4879-BB11-67E7FE333C45} = {2A8BDC9C-C864-46B7-98A0-ECC9BA0ECDFF} + {48F1B70D-8C96-49BA-B4A2-957377393EEF} = {5B9A381F-95C5-4879-BB11-67E7FE333C45} + {F2100C68-99AA-437E-8B6F-569CFF60319A} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {D277FFE9-E342-4D8F-9EEA-ACB984B3F20E} = {F2100C68-99AA-437E-8B6F-569CFF60319A} + {C11D6283-7A34-4CDD-8C27-65F8499E5CFE} = {D277FFE9-E342-4D8F-9EEA-ACB984B3F20E} + {E3A38228-9D83-4287-BB40-3B37105327C3} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {0A6E4D7B-7E46-4428-B8A2-04670F4AE4E8} = {E3A38228-9D83-4287-BB40-3B37105327C3} + {C37BA915-33E8-48C6-9098-6681EE54884D} = {0A6E4D7B-7E46-4428-B8A2-04670F4AE4E8} + {263ABDC6-0FF9-4CEF-BADE-AF910A4CD06E} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {55BA7DED-599D-4518-BE9A-EF537FF15FD5} = {263ABDC6-0FF9-4CEF-BADE-AF910A4CD06E} + {2C70A6EE-70B7-42C0-8C0B-66C690AB8C87} = {55BA7DED-599D-4518-BE9A-EF537FF15FD5} + {4FBDE444-8013-449D-829B-1A10E5C84ED2} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {81C41B64-01DB-4B74-ACC0-E3FC9EBCC8F1} = {4FBDE444-8013-449D-829B-1A10E5C84ED2} + {F44EB030-BD0E-42AB-82BD-5E7E0F530A24} = {81C41B64-01DB-4B74-ACC0-E3FC9EBCC8F1} + {3C7B03EF-F829-4183-8447-5FFAAB41736D} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {504632B3-C3E0-4AEE-BB19-4B83AB67EE98} = {3C7B03EF-F829-4183-8447-5FFAAB41736D} + {96C98AA8-D5D5-4F3D-AC36-DFB044A10283} = {504632B3-C3E0-4AEE-BB19-4B83AB67EE98} + {CF5E9E32-F322-427D-9282-75D9241B01A9} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {36D4B481-06AB-4B67-8794-E9CFB5502973} = {CF5E9E32-F322-427D-9282-75D9241B01A9} + {D3966891-3616-427F-BC24-CEBAD4B3B6BE} = {36D4B481-06AB-4B67-8794-E9CFB5502973} + {F15D5FFF-2C08-4EB8-B2D7-A1DD8162F5AF} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {BBB2D930-94EA-4246-8455-237671065539} = {F15D5FFF-2C08-4EB8-B2D7-A1DD8162F5AF} + {FAFEE1DA-438D-4D7F-91B1-9BB2444DB30E} = {BBB2D930-94EA-4246-8455-237671065539} + {6E2CC07F-56CA-40F3-B3F3-3DA8AE603896} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {C6A58830-B745-41A4-90D2-DA163CF2BB67} = {6E2CC07F-56CA-40F3-B3F3-3DA8AE603896} + {DA97B418-6D04-4FA2-8214-6FE3113E02C7} = {C6A58830-B745-41A4-90D2-DA163CF2BB67} + {A3BE5D15-F8AA-4EDB-8E75-E1F37924CEF6} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {8E528AAF-4A6F-4829-B806-EDBD5C30F355} = {A3BE5D15-F8AA-4EDB-8E75-E1F37924CEF6} + {DD92F97D-EA78-4377-8DB7-63D1C6048670} = {8E528AAF-4A6F-4829-B806-EDBD5C30F355} + {4D2D22C2-B933-495B-9846-811D5907A57D} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {929BA453-227D-46A5-BDD7-0A19825BE5E5} = {4D2D22C2-B933-495B-9846-811D5907A57D} + {891D09C7-E16C-4467-BDEE-BDAAB5552B7A} = {929BA453-227D-46A5-BDD7-0A19825BE5E5} + {269FF747-D5E0-40D8-B049-6E4C4964ADA6} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {2E90B124-81A7-4537-927F-8DB160C1FE80} = {269FF747-D5E0-40D8-B049-6E4C4964ADA6} + {A3B23699-5387-4266-B784-C7AE207E6923} = {2E90B124-81A7-4537-927F-8DB160C1FE80} + {9101C64B-D96D-473D-B675-3774012104DA} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {35EB5074-E17E-414B-9057-2E26E4C43D5B} = {9101C64B-D96D-473D-B675-3774012104DA} + {BA41DE74-F49C-4C07-A83D-2317566E7808} = {35EB5074-E17E-414B-9057-2E26E4C43D5B} + {3F4A40BF-90D0-4F0B-A8E7-4353FAC34D4C} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {E78D409D-0A8E-4A95-9E03-165B01A953BF} = {3F4A40BF-90D0-4F0B-A8E7-4353FAC34D4C} + {80B82340-D9C3-431F-9B22-947F6DDAE0F6} = {E78D409D-0A8E-4A95-9E03-165B01A953BF} + {044CF8A5-7174-45AD-A429-BFAE3DC59B3B} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {2924AEED-876E-4AFA-A233-B34229F73BE4} = {044CF8A5-7174-45AD-A429-BFAE3DC59B3B} + {74B56470-25B2-4846-810D-53560F6EB5F1} = {2924AEED-876E-4AFA-A233-B34229F73BE4} + {DB05923D-5D5E-4630-AF81-386E8FD267A6} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {AABB6D87-3D71-4E9B-964C-C2327BE60CFA} = {DB05923D-5D5E-4630-AF81-386E8FD267A6} + {5C73EE37-B28D-476A-825E-4EF73D0F6D80} = {AABB6D87-3D71-4E9B-964C-C2327BE60CFA} + {25A7010F-FAAF-47FB-85F4-CBA5803D29FB} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {C430C499-9B05-46D5-A3F8-5BA3FB0FEC97} = {25A7010F-FAAF-47FB-85F4-CBA5803D29FB} + {61FCF96E-F3D6-4609-9D75-78D9582E692D} = {C430C499-9B05-46D5-A3F8-5BA3FB0FEC97} + {7856E480-B1CB-4658-A2FB-ABA0C201A41F} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {0819B57C-7DC1-4766-88DE-2E6EE93100B8} = {7856E480-B1CB-4658-A2FB-ABA0C201A41F} + {BF317DEB-2946-49C4-A6D2-3A0B4175AF64} = {0819B57C-7DC1-4766-88DE-2E6EE93100B8} + {8A254CA8-A07F-4729-9D33-0494853B734B} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {48443654-8823-499D-9FDA-B95460C5307C} = {8A254CA8-A07F-4729-9D33-0494853B734B} + {951F433D-47BB-46CD-9577-38DC2EEF38F1} = {48443654-8823-499D-9FDA-B95460C5307C} + {0EE07F7A-DE9B-4C55-A697-3A17B5D3E0B4} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {92896FB4-C0F8-4387-858D-A290CD242622} = {0EE07F7A-DE9B-4C55-A697-3A17B5D3E0B4} + {92B8FAFF-3EBC-4C12-91AB-71A8B6E0EC1C} = {92896FB4-C0F8-4387-858D-A290CD242622} + {2EBD7821-313E-4099-B11E-A64208AF5828} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {D7AF3953-4C0F-4D48-9B9B-41CC9030C3CC} = {2EBD7821-313E-4099-B11E-A64208AF5828} + {6C8B2D4E-6B4E-4F71-AA72-BF0BB37D6DAD} = {D7AF3953-4C0F-4D48-9B9B-41CC9030C3CC} + {916C4EA8-832B-4A46-87E0-B7E791370E40} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {59C0DA6D-19D4-4558-99E4-214E303A4577} = {916C4EA8-832B-4A46-87E0-B7E791370E40} + {66B48A43-2EA8-4463-81B5-D842A49DBD73} = {59C0DA6D-19D4-4558-99E4-214E303A4577} + {B980A4D6-935E-4EBC-B2EA-6CCA456F7A58} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {5D0E2857-73F0-4629-8E2E-AE0697AD80D1} = {B980A4D6-935E-4EBC-B2EA-6CCA456F7A58} + {30536342-FF9E-4B4E-8679-55DDF1583BCE} = {5D0E2857-73F0-4629-8E2E-AE0697AD80D1} + {BE0926CC-9242-4907-B7D9-DD44FA3DB846} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {483EBECF-595C-41E1-9133-F6823CAEAD21} = {BE0926CC-9242-4907-B7D9-DD44FA3DB846} + {1A694B8E-C1E4-4BC2-A5F3-F658EB733EDB} = {483EBECF-595C-41E1-9133-F6823CAEAD21} + {2C0EA586-4767-4FD7-B994-7FD140C88410} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {921533E6-BAEC-4661-81D4-93379BC098C5} = {2C0EA586-4767-4FD7-B994-7FD140C88410} + {86177A39-B69B-40BC-AAA4-E5DDDCE80B54} = {921533E6-BAEC-4661-81D4-93379BC098C5} + {6FE112DA-68F4-4478-B3D4-0998C796B069} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {9A6E6002-400C-4E20-B720-98E4C6C08C91} = {6FE112DA-68F4-4478-B3D4-0998C796B069} + {3FF581CD-E646-48CE-8611-159999784EDB} = {9A6E6002-400C-4E20-B720-98E4C6C08C91} + {E08F12C4-FC31-46E7-8929-D588E0516D1E} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {A6FAE91B-BC05-4231-9B18-B77861456554} = {E08F12C4-FC31-46E7-8929-D588E0516D1E} + {6BDE17DC-A368-4EB8-9BA5-222E2E8469D1} = {A6FAE91B-BC05-4231-9B18-B77861456554} + {FB1CC579-E541-4CB9-B1B8-4F5DF7E9AC14} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {78A1EE8A-2B3C-48C5-B604-A769436714D6} = {FB1CC579-E541-4CB9-B1B8-4F5DF7E9AC14} + {24C6898B-ACF8-4406-8767-4EB388950D3B} = {78A1EE8A-2B3C-48C5-B604-A769436714D6} + {B3B19CA3-CA80-4010-98E6-C175AA88B8CC} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {99767C82-2DC7-41C7-92F8-C92C28985A87} = {B3B19CA3-CA80-4010-98E6-C175AA88B8CC} + {2F80BDCE-7606-4F23-99CE-B980E1E8C70E} = {99767C82-2DC7-41C7-92F8-C92C28985A87} + {3085F22A-78A0-4BF2-AF0D-5E2A0EC3B1FD} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {805B67FD-07D3-4B16-85E6-EA8039FE0C51} = {3085F22A-78A0-4BF2-AF0D-5E2A0EC3B1FD} + {C5A5B136-224B-43B4-B220-C677BF4D8294} = {805B67FD-07D3-4B16-85E6-EA8039FE0C51} + {1DC7633F-5218-4A44-963F-730CA81B66E2} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {E4806DB9-88E3-4192-8077-90047B8DD2A1} = {1DC7633F-5218-4A44-963F-730CA81B66E2} + {DB1D40BF-6C1B-4565-B629-4647834B8F40} = {E4806DB9-88E3-4192-8077-90047B8DD2A1} + {CF2C3F58-8A1E-48C4-ACA7-7D540DBEDD80} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {B34807AE-1728-48FE-8B3A-4FCC4DD8D40C} = {CF2C3F58-8A1E-48C4-ACA7-7D540DBEDD80} + {316025D1-B4C1-4053-87E4-34DC46FF7B23} = {B34807AE-1728-48FE-8B3A-4FCC4DD8D40C} + {CACFA014-FC77-4B94-827C-2B59DE04BE16} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {96787B73-62AA-4C09-B688-823A4E4FB6E2} = {CACFA014-FC77-4B94-827C-2B59DE04BE16} + {7808E16E-87A9-4D8C-82A5-BFBABBDD2C3C} = {96787B73-62AA-4C09-B688-823A4E4FB6E2} + {C6AEDC14-DF11-4B52-BB08-6FF557237010} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {F425D415-34EF-4A22-B010-F250131034F6} = {C6AEDC14-DF11-4B52-BB08-6FF557237010} + {DD1FEF33-10CA-4DF2-872A-D8879A8302DA} = {F425D415-34EF-4A22-B010-F250131034F6} + {C5965E3E-F9B7-457D-976B-FF198E971AEE} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {BC476C0E-2947-47EE-B395-69D71D46C179} = {C5965E3E-F9B7-457D-976B-FF198E971AEE} + {1098672C-C215-4912-AB71-906E6176A4AA} = {BC476C0E-2947-47EE-B395-69D71D46C179} + {4254A869-193E-4AD5-B403-AA628B30E75D} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {5C8BC972-E212-4ACD-BF34-AC11F29372F2} = {4254A869-193E-4AD5-B403-AA628B30E75D} + {F932902B-7C87-4E8A-B43D-FEAABBB1AB2A} = {5C8BC972-E212-4ACD-BF34-AC11F29372F2} + {AEA3EB59-34FB-455C-AD80-C93186A5BE8D} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {7E3CABB1-B098-486F-BBF9-93138E58E1B6} = {AEA3EB59-34FB-455C-AD80-C93186A5BE8D} + {21DD38E0-3B0C-4F3E-B7B2-77869FB5471D} = {7E3CABB1-B098-486F-BBF9-93138E58E1B6} + {EEA6E326-AAF9-4772-B4C1-AECF9FADAA19} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {BAA404DB-39D2-41E4-AC87-4DE55BE7B346} = {EEA6E326-AAF9-4772-B4C1-AECF9FADAA19} + {096D90EF-4ABC-40B4-85D1-E813969C40D1} = {BAA404DB-39D2-41E4-AC87-4DE55BE7B346} + {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} = {B8F1F599-6153-4506-BA3A-C68123D23987} + {000361F4-B47A-430A-A0C2-0A7086A31436} = {B8F1F599-6153-4506-BA3A-C68123D23987} + {1387AD44-A709-427B-8B95-2262C0284BE5} = {B8F1F599-6153-4506-BA3A-C68123D23987} + {67FCA1BE-D816-4972-9138-F74F39F3A158} = {B8F1F599-6153-4506-BA3A-C68123D23987} + {50BD1A91-4AE4-4595-A3E5-C3CCB29C222A} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {6BFD42BE-5AB6-484B-9751-18184B4602A1} = {50BD1A91-4AE4-4595-A3E5-C3CCB29C222A} + {10DE679A-E842-4227-8120-AB0D91F02C3B} = {6BFD42BE-5AB6-484B-9751-18184B4602A1} + {08A830E5-212D-4BB4-8ABA-0C22368496AC} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {0485686F-900D-4D21-9ED6-60CB21E3F0D4} = {08A830E5-212D-4BB4-8ABA-0C22368496AC} + {161D23AA-B910-4826-984E-5F71E6115F3C} = {0485686F-900D-4D21-9ED6-60CB21E3F0D4} + {704C4816-BDEA-47B7-94A7-00F3E19BD47E} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {7467768D-4858-4847-9A5B-97ECB096EFE8} = {704C4816-BDEA-47B7-94A7-00F3E19BD47E} + {8F19C132-61E2-4351-AC47-4653E86D7456} = {7467768D-4858-4847-9A5B-97ECB096EFE8} + {8E9348FF-4214-4BFE-953F-E564A2C01DFD} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {7D0320C0-C6C2-45F5-8F14-EA15BB063A90} = {8E9348FF-4214-4BFE-953F-E564A2C01DFD} + {CE704EE3-FC1E-48D5-A9FF-13ACB9C2E529} = {7D0320C0-C6C2-45F5-8F14-EA15BB063A90} + {01B3171D-AF96-4796-8388-8649053CF04E} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {313BAE04-DBEC-4EE2-ACF3-D85D8C8798C5} = {01B3171D-AF96-4796-8388-8649053CF04E} + {15344920-AE73-4C0A-AEB2-7D75748B791E} = {313BAE04-DBEC-4EE2-ACF3-D85D8C8798C5} + {DE565C75-358D-43AF-82FA-0A70925FFFB4} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {1CDBE1A6-3E5B-4FBE-B98F-5705633BFE9C} = {DE565C75-358D-43AF-82FA-0A70925FFFB4} + {39664900-A87E-4A6D-8BFA-EAC97F5892ED} = {1CDBE1A6-3E5B-4FBE-B98F-5705633BFE9C} + {F9D1F2B5-1B82-4B5F-A65A-18EA75F38457} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {93D303A0-945B-403E-82D4-AC8E2CA4463F} = {F9D1F2B5-1B82-4B5F-A65A-18EA75F38457} + {EBDF3AD9-BE1C-43B3-ADE4-2336DE09355E} = {93D303A0-945B-403E-82D4-AC8E2CA4463F} + {471F09E3-9BA6-43AB-A8F1-359D797FD136} = {4EB973CF-9705-442F-AA83-7DBE73B010D0} + {DCB5C4A9-9AA5-413D-A4AA-CBBB66A0262E} = {471F09E3-9BA6-43AB-A8F1-359D797FD136} + {54B5632D-C113-4383-913E-2701501D951D} = {DCB5C4A9-9AA5-413D-A4AA-CBBB66A0262E} + {1DC34F9A-8397-4B6D-8B13-175A850DECFB} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {E98FBEDE-0103-4D38-8A72-92FAE634C67E} = {1DC34F9A-8397-4B6D-8B13-175A850DECFB} + {54742C48-894C-4B28-B0D6-BF4F6CE7E76B} = {E98FBEDE-0103-4D38-8A72-92FAE634C67E} + {6D68EB04-A8B4-4843-A20E-5BFC4F07923B} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {477D4BB3-CA8F-4CB3-AD08-CD84CBF4215E} = {6D68EB04-A8B4-4843-A20E-5BFC4F07923B} + {60637559-5F48-44A1-B1F6-16AEA6B1BA01} = {477D4BB3-CA8F-4CB3-AD08-CD84CBF4215E} + {4EB973CF-9705-442F-AA83-7DBE73B010D0} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {86C29745-85F2-4F63-9CBB-EF0F364E3633} = {4EB973CF-9705-442F-AA83-7DBE73B010D0} + {A4619E76-5B45-4B85-B305-FD99A80EAAFF} = {86C29745-85F2-4F63-9CBB-EF0F364E3633} + {E12EF30F-3FD3-4A97-8BBD-FC008108298D} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {77EB4E23-F3B6-4259-8A37-68ADDEC79FA3} = {E12EF30F-3FD3-4A97-8BBD-FC008108298D} + {A0D587EC-3860-41A7-A648-ABDE1DBB2B01} = {77EB4E23-F3B6-4259-8A37-68ADDEC79FA3} + {FA0D3054-CC09-4B44-BE75-A4BBA43CF568} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {FE9B754D-0964-43E7-B284-E5BFCE219339} = {FA0D3054-CC09-4B44-BE75-A4BBA43CF568} + {AEDA5B3F-0DD4-4F00-AD27-9C74E7B58E4A} = {FE9B754D-0964-43E7-B284-E5BFCE219339} + {761F0B1D-C5E2-4B7F-9757-2569DE22242C} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {1346E39C-2A3C-45F3-B3F1-7BC486BC6C3F} = {7CE65D69-9B3F-4CA8-9837-75BCB4E3F083} + {7CE65D69-9B3F-4CA8-9837-75BCB4E3F083} = {761F0B1D-C5E2-4B7F-9757-2569DE22242C} + {44497CF8-959A-44C6-A40B-E517BC2376A6} = {000361F4-B47A-430A-A0C2-0A7086A31436} + {9357F636-7980-46DF-8AE1-967D9B52D4C7} = {44497CF8-959A-44C6-A40B-E517BC2376A6} + {136DFCD0-EEC3-4856-88FC-875549E69567} = {9357F636-7980-46DF-8AE1-967D9B52D4C7} + {AA4DF06F-0801-4132-8993-A5BED221A9F2} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {D73D3AA8-4D8A-4820-B62C-9BB9F0C0CB3A} = {AA4DF06F-0801-4132-8993-A5BED221A9F2} + {BB6E867B-D3C5-4EB8-8A08-919A8E530753} = {D73D3AA8-4D8A-4820-B62C-9BB9F0C0CB3A} + {8564D43C-9FD5-4B61-86F6-5F1DE20B072E} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {CC2F9BCC-C904-4EC8-A7D6-B45B3FC6946E} = {8564D43C-9FD5-4B61-86F6-5F1DE20B072E} + {1BE80F2C-F652-4E36-8DA3-EFFD46BEC8AA} = {CC2F9BCC-C904-4EC8-A7D6-B45B3FC6946E} + {21586975-5E83-42BD-BDB0-B34FCD5B734A} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {0B90312C-7E10-4C6F-B3EC-C580BAD0FFE9} = {21586975-5E83-42BD-BDB0-B34FCD5B734A} + {650813DD-F043-4C38-B235-4F2986B96DF4} = {0B90312C-7E10-4C6F-B3EC-C580BAD0FFE9} + {653A4FE9-34F5-4248-AD24-2113A58731B4} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {6E66E383-08AD-49AD-AE98-062EF74A2D0A} = {653A4FE9-34F5-4248-AD24-2113A58731B4} + {E064C30A-5B7D-4253-B3F2-A2172F4DBF7D} = {6E66E383-08AD-49AD-AE98-062EF74A2D0A} + {83AD0011-B9F9-41CE-993A-C82BEC443354} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {B16C0689-BE91-4470-867C-29CD41BECBE3} = {83AD0011-B9F9-41CE-993A-C82BEC443354} + {E340800D-3FCB-4389-8E95-39454110F40A} = {B16C0689-BE91-4470-867C-29CD41BECBE3} + {5658AB3B-3A50-4586-B407-D028CA678ADE} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {FB7BBE6E-9121-415B-ACAC-FE412DF3CE41} = {5658AB3B-3A50-4586-B407-D028CA678ADE} + {450B0EA2-2AFF-4CBF-9ED0-B3F230C33621} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {AD67A5A6-BA20-4F9E-83C7-1D0AFB9091C2} = {450B0EA2-2AFF-4CBF-9ED0-B3F230C33621} + {8262B019-389D-4E9A-9EE4-606D3F2023FC} = {AD67A5A6-BA20-4F9E-83C7-1D0AFB9091C2} + {FA87E4AC-AFBE-4811-848E-EF6AED874F59} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {CB5B8A98-2204-4F53-A8A8-B6BB32E85F64} = {AA75ECB6-3554-4CD6-A240-53637B392904} + {AA75ECB6-3554-4CD6-A240-53637B392904} = {FA87E4AC-AFBE-4811-848E-EF6AED874F59} + {B572C23F-1A8A-4514-A785-CF1C717691EB} = {ED714ADB-432F-456C-B767-06576666A43B} + {31293883-B73F-4DA8-9BA2-4A9930B44AA2} = {1387AD44-A709-427B-8B95-2262C0284BE5} + {35CDF4F0-89D5-463D-B3BA-628F032DDCDC} = {31293883-B73F-4DA8-9BA2-4A9930B44AA2} + {C99CFF53-B1BD-4FAA-A285-3C149CACE44F} = {35CDF4F0-89D5-463D-B3BA-628F032DDCDC} + {06C10087-A052-40BD-8101-18DB37909B14} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {AE455D02-0572-43BA-B213-4D6BF8EDD37B} = {FB7BBE6E-9121-415B-ACAC-FE412DF3CE41} + {83888528-487F-4071-8605-151E4F586C78} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {5A8BECBC-089B-4425-BE29-AB6F2750DAC6} = {83888528-487F-4071-8605-151E4F586C78} + {CE011088-8685-47FC-8274-2141025946D2} = {5A8BECBC-089B-4425-BE29-AB6F2750DAC6} + {2D9E833E-0229-4DA6-BC6C-2A039E925176} = {B8F1F599-6153-4506-BA3A-C68123D23987} + {7E38EF2C-F2CD-40A4-9052-F5472E30CBDC} = {2D9E833E-0229-4DA6-BC6C-2A039E925176} + {F85E1F14-3D62-4F7A-BEB2-B73AA16BB2F8} = {7E38EF2C-F2CD-40A4-9052-F5472E30CBDC} + {40244095-2B04-407C-AF92-CED881D0429D} = {F85E1F14-3D62-4F7A-BEB2-B73AA16BB2F8} + {197C8362-EB09-4F2C-A70B-2D29E5F04D21} = {2D9E833E-0229-4DA6-BC6C-2A039E925176} + {4B4DE002-28B5-4E4A-AD2F-837DF34D5F2F} = {197C8362-EB09-4F2C-A70B-2D29E5F04D21} + {BAB2ACB4-1914-48FB-B141-A52C85FBDDC1} = {4B4DE002-28B5-4E4A-AD2F-837DF34D5F2F} + {CA1F8B6F-2EA4-4A7C-B468-190B7C76E97B} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {F623050B-10E1-407E-91F4-0AE24EE144FB} = {CA1F8B6F-2EA4-4A7C-B468-190B7C76E97B} + {E6720C0D-274D-4AEF-A45E-897EBDCE0911} = {F623050B-10E1-407E-91F4-0AE24EE144FB} + {CEBDD8CA-8AC5-41B2-95CE-21EDA9D38AFF} = {57375AE4-BFE0-4D8A-8D76-27AF0FA5479E} + {57375AE4-BFE0-4D8A-8D76-27AF0FA5479E} = {06C10087-A052-40BD-8101-18DB37909B14} + {644EE9B7-3883-4C1A-900C-0A3217CD5122} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {5EF9AA74-6CD0-4FC4-8D8F-19BECE6D5041} = {644EE9B7-3883-4C1A-900C-0A3217CD5122} + {3BCB9CBC-A3EE-4493-B605-6EBE559F295A} = {5EF9AA74-6CD0-4FC4-8D8F-19BECE6D5041} + {C66C3B0F-2B02-414E-A02C-20E40E4323CA} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {38F41597-6448-4CB2-A73B-457C53354FD6} = {C66C3B0F-2B02-414E-A02C-20E40E4323CA} + {5D786C6B-2A75-440B-A1FB-C077E8B8B898} = {38F41597-6448-4CB2-A73B-457C53354FD6} + {BBF714D6-0319-4D28-B531-BD06728F5E4F} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {09CDBAFA-14B3-4C0D-A604-56AB25627D75} = {BBF714D6-0319-4D28-B531-BD06728F5E4F} + {9F5AFB87-3F4F-40A9-A76F-BFC6C78BD59B} = {09CDBAFA-14B3-4C0D-A604-56AB25627D75} + {ECD7B20D-BB60-447D-9379-CB231CED783D} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {99DE7371-2C7F-49CB-BE2D-03C2C6DB4ABB} = {ECD7B20D-BB60-447D-9379-CB231CED783D} + {394C3304-3228-4F16-AD8A-06D7B32A3D46} = {99DE7371-2C7F-49CB-BE2D-03C2C6DB4ABB} + {6337C220-C88D-40F6-8430-5D587AAAA6E1} = {B8F1F599-6153-4506-BA3A-C68123D23987} + {1A8EC1C6-6712-4C84-9495-1E6B9C7C0695} = {6337C220-C88D-40F6-8430-5D587AAAA6E1} + {121DD302-DF4B-4F49-B6F9-B3AD358BD842} = {1A8EC1C6-6712-4C84-9495-1E6B9C7C0695} + {9184AD19-8580-4A8F-8220-8A679639C57F} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {D1E71180-9B7B-40BB-831D-48BB98F0A834} = {9184AD19-8580-4A8F-8220-8A679639C57F} + {033DCC6B-9081-4119-8F9E-F51B834992CC} = {D1E71180-9B7B-40BB-831D-48BB98F0A834} + {A1466055-9F55-4B87-8D6F-323E4F0EA85C} = {E1863B9A-556C-4B02-A74D-E47F6EFCCC5E} + {06F7B8FB-7357-4F31-93CF-E76050F07224} = {A1466055-9F55-4B87-8D6F-323E4F0EA85C} + {4AC66D72-FD8B-40B3-9236-C76F97FFD487} = {06F7B8FB-7357-4F31-93CF-E76050F07224} + {72128F4D-352C-4DEF-BA5A-DAB4A2A7CC93} = {2D9E833E-0229-4DA6-BC6C-2A039E925176} + {B257C040-9707-4DF4-93BB-F7151D0C0702} = {72128F4D-352C-4DEF-BA5A-DAB4A2A7CC93} + {130FBF70-7031-4F7C-92AC-2C616442F18D} = {B257C040-9707-4DF4-93BB-F7151D0C0702} + {50494B33-0532-42E6-AF1F-05BA2F7B8D81} = {67FCA1BE-D816-4972-9138-F74F39F3A158} + {B7B98608-DFC0-47A9-AA5A-760D948D7DE1} = {50494B33-0532-42E6-AF1F-05BA2F7B8D81} + {56BC6E17-FC0B-4AB5-BFB2-B92344E707FA} = {B7B98608-DFC0-47A9-AA5A-760D948D7DE1} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8A34D641-4198-452E-88BE-371C26F30977} + EndGlobalSection +EndGlobal diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders.xml new file mode 100644 index 0000000..5fdd3f2 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders.xml @@ -0,0 +1,31 @@ + + + BookMultipleOrders + Script 1.0.1.77 + Automation + SKYLINE2\VictorSC + FALSE + YLE/Customer UI + + + + + + + + + + OrderIds + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/BookMultipleOrdersDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/BookMultipleOrdersDialog.cs new file mode 100644 index 0000000..46f70ab --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/BookMultipleOrdersDialog.cs @@ -0,0 +1,165 @@ +namespace BookMultipleOrders_2 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Controllers; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notifications; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.LoadingScreenTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.OrderTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.LoadingScreens; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using OrderStatus = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status; + using Status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.Status; + + public class BookMultipleOrdersDialog : LoadingDialog + { + private readonly List orderGuids = new List(); + private readonly List ordersToBook = new List(); + private readonly List ordersThatShouldNotBeBooked = new List(); + private readonly List ordersThatWereSuccessfullyBooked = new List(); + private readonly List ordersThatFailedToGetBooked = new List(); + + public BookMultipleOrdersDialog(Helpers helpers) : base(helpers) + { + } + + protected override void GetScriptInput() + { + string scriptParameter = Engine.GetScriptParam("OrderIds").Value; + + foreach (var orderId in scriptParameter.Split(',')) + { + if (Guid.TryParse(orderId, out var orderGuid)) + { + orderGuids.Add(orderGuid); + } + else + { + Log(nameof(GetScriptInput), $"Unable to parse {orderId} to a Guid"); + } + } + } + + protected override void CollectActions() + { + methodsToExecute.Add(GetOrdersAndLocks); + methodsToExecute.Add(StartChangeTracking); + methodsToExecute.Add(GetUserInfo); + methodsToExecute.Add(BookOrders); + methodsToExecute.Add(ShowResultsInUi); + } + + private void StartChangeTracking() + { + ordersToBook.ForEach(o => o.AcceptChanges()); + } + + protected override void SendReportButton_Pressed(object sender, EventArgs e) + { + string title = "Exception while booking multiple orders [" + DateTime.Now + "]"; + + string message = $"Orders: {string.Join(",", ordersToBook.Select(o => o.Name))}
User: {Engine.UserLoginName}
Timestamp: {DateTime.Now}
Exception: {informationMessageLabel.Text.Replace(" at ", "
at ")}"; + + NotificationManager.SendMailToSkylineDevelopers(Helpers, title, message); + + reportSuccessfullySentLabel.IsVisible = true; + } + + private void GetOrdersAndLocks() + { + foreach (var orderGuid in orderGuids) + { + var getOrderTask = new GetOrderTask(Helpers, orderGuid); + Tasks.Add(getOrderTask); + getOrderTask.Execute(); + if (getOrderTask.Status == Status.Fail) continue; + + var getLockTask = new GetOrderLockTask(Helpers, getOrderTask.Order.Id); + Tasks.Add(getLockTask); + getLockTask.Execute(); + + if (getLockTask.Status == Status.Fail) continue; + + if (getOrderTask.Order.Status == OrderStatus.Preliminary && getLockTask.LockInfo != null && getLockTask.LockInfo.IsLockGranted) + { + ordersToBook.Add(getOrderTask.Order); + } + else + { + ordersThatShouldNotBeBooked.Add(getOrderTask.Order); + } + } + } + + private void GetUserInfo() + { + var getUserInfoTask = new GetBaseUserInfoTask(Helpers); + Tasks.Add(getUserInfoTask); + + IsSuccessful &= getUserInfoTask.Execute(); + if (!IsSuccessful) return; + + UserInfo = getUserInfoTask.UserInfo; + } + + private void BookOrders() + { + foreach (var order in ordersToBook) + { + Helpers.AddOrderReferencesForLogging(order.Id); + + if (UserInfo.IsMcrUser) order.Status = OrderStatus.Confirmed; + else if (order.Status == OrderStatus.Preliminary || order.Status == OrderStatus.Cancelled || order.Status == OrderStatus.Rejected) order.Status = OrderStatus.Planned; + else if (order.Status == OrderStatus.Confirmed) order.Status = OrderStatus.ChangeRequested; + else + { + // No order status update required + } + + if (!new OrderValidator(Helpers, order, UserInfo, Options.None).Validate()) + { + ordersThatShouldNotBeBooked.Add(order); + continue; + } + + var updateResult = order.AddOrUpdate(Helpers, UserInfo.IsMcrUser); + Helpers.LockManager.ReleaseOrderLock(order.Id); + Tasks.AddRange(updateResult.Tasks); + + if (!updateResult.UpdateWasSuccessful) + { + ordersThatFailedToGetBooked.Add(order); + } + else + { + ordersThatWereSuccessfullyBooked.Add(order); + } + } + } + + private void ShowResultsInUi() + { + var sb = new StringBuilder(); + + if (ordersThatWereSuccessfullyBooked.Any()) + { + sb.Append($"Orders {string.Join(", ", ordersThatWereSuccessfullyBooked.Select(o => o.Name))} were successfully booked. \n"); + } + + if (ordersThatFailedToGetBooked.Any()) + { + sb.Append($"Orders {string.Join(", ", ordersThatFailedToGetBooked.Select(o => o.Name))} failed to get booked. \n"); + } + + if (ordersThatShouldNotBeBooked.Any()) + { + sb.Append($"Orders {string.Join(", ", ordersThatShouldNotBeBooked.Select(o => o.Name))} are not Preliminary, not valid or couldn't get a valid lock \n"); + } + + PrepareUiForManualMessage(sb.ToString(), showSendReportButton: false, showExceptionWidgets: false); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/BookMultipleOrders_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/BookMultipleOrders_2.csproj new file mode 100644 index 0000000..650b014 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/BookMultipleOrders_2.csproj @@ -0,0 +1,101 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {E10BD658-9B0E-4A95-97B7-C288C429C094} + Library + Properties + BookMultipleOrders_2 + BookMultipleOrders_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\BookMultipleOrders_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\BookMultipleOrders_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..80893a7 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("BookMultipleOrders_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("BookMultipleOrders_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("C0DD7709-41FC-4519-88F6-7D7EDDE8A6AB")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/Script.cs new file mode 100644 index 0000000..8509546 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/Script.cs @@ -0,0 +1,147 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + + + +//--------------------------------- +// BookMultipleOrders_2.cs +//--------------------------------- + +namespace BookMultipleOrders_2 +{ + using System; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + /// + /// DataMiner Script Class. + /// + class Script : IDisposable + { + private InteractiveController app; + private Helpers helpers; + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + try + { + //engine.ShowUI(); + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.SetFlag(RunTimeFlags.NoCheckingSets); + engine.SetFlag(RunTimeFlags.NoInformationEvents); + engine.Timeout = TimeSpan.FromHours(10); + + app = new InteractiveController(engine); + helpers = new Helpers(engine, Scripts.BookMultipleOrders); + + var bookMultipleOrdersDialog = new BookMultipleOrdersDialog(helpers); + bookMultipleOrdersDialog.Execute(); + helpers.LockManager.ReleaseLocks(); + app.Run(bookMultipleOrdersDialog); + } + catch (ScriptAbortException) + { + // nothing + } + catch (InteractiveUserDetachedException) + { + // nothing + } + catch (Exception e) + { + helpers?.Log(nameof(Script), nameof(Run), $"Exception: {e}"); + ShowExceptionDialog(engine, e); + } + finally + { + helpers?.LockManager.ReleaseLocks(); + Dispose(); + } + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + var dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong during the booking of multiple orders."); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/BookMultipleOrders_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders.xml new file mode 100644 index 0000000..10626eb --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders.xml @@ -0,0 +1,31 @@ + + + CancelMultipleOrders + Script 1.0.1.77 + Automation + SKYLINE2\VictorSC + FALSE + YLE/Customer UI + + + + + + + + + + OrderIds + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/CancelMultipleOrdersProgressDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/CancelMultipleOrdersProgressDialog.cs new file mode 100644 index 0000000..b15b5a0 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/CancelMultipleOrdersProgressDialog.cs @@ -0,0 +1,192 @@ +namespace CancelMultipleOrders_2 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notifications; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.LoadingScreenTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.OrderTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.LoadingScreens; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using OrderStatus = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status; + using Status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.Status; + + public class CancelMultipleOrdersProgressDialog : LoadingDialog + { + private readonly string reasonForCancellation; + private readonly List orderGuids = new List(); + private readonly List retrievedOrders = new List(); + private readonly List orderIdsThatFailedToBeRetrieved = new List(); + private readonly List ordersToCancel = new List(); + private readonly List ordersThatFailedToBeCancelled = new List(); + private readonly List lockedOrders = new List(); + private readonly List ordersThatCantBeCancelled = new List(); + private readonly List ordersThatSucceededToBeCancelled = new List(); + + public CancelMultipleOrdersProgressDialog(Helpers helpers, string reasonForCancellation) : base(helpers) + { + this.reasonForCancellation = reasonForCancellation; + } + + protected override void GetScriptInput() + { + string scriptParameter = Engine.GetScriptParam("OrderIds").Value; + + foreach (var orderId in scriptParameter.Split(',')) + { + if (Guid.TryParse(orderId, out var orderGuid)) + { + orderGuids.Add(orderGuid); + Helpers.AddOrderReferencesForLogging(orderGuid); + } + else + { + Engine.Log($"Run|Unable to parse {orderId} to a Guid"); + } + } + } + + protected override void CollectActions() + { + methodsToExecute.Add(InitializeOrderLogger); + methodsToExecute.Add(GetOrders); + methodsToExecute.Add(GetLocks); + methodsToExecute.Add(CancelOrders); + methodsToExecute.Add(ShowResultsInUi); + } + + protected override void SendReportButton_Pressed(object sender, EventArgs e) + { + string title = "Exception while canceling multiple orders [" + DateTime.Now + "]"; + + string message = $"Orders: {string.Join(",", ordersToCancel.Select(o => o.Name))}
User: {Engine.UserLoginName}
Timestamp: {DateTime.Now}
Exception: {informationMessageLabel.Text.Replace(" at ", "
at ")}"; + + NotificationManager.SendMailToSkylineDevelopers(Helpers, title, message); + + reportSuccessfullySentLabel.IsVisible = true; + } + + private void InitializeOrderLogger() + { + Helpers.Log(nameof(CancelMultipleOrdersProgressDialog), "START SCRIPT", "Cancel Multiple Orders"); + } + + private void GetOrders() + { + LogActionStart(nameof(GetOrders), out var stopWatch); + + foreach (var orderGuid in orderGuids) + { + var getOrderTask = new GetOrderTask(Helpers, orderGuid); + Tasks.Add(getOrderTask); + + IsSuccessful &= getOrderTask.Execute(); + if (IsSuccessful) + { + retrievedOrders.Add(getOrderTask.Order); + } + else + { + orderIdsThatFailedToBeRetrieved.Add(orderGuid); + } + } + + Log(nameof(GetOrders), $"Unable to retrieve orders {string.Join(", ", orderIdsThatFailedToBeRetrieved)}"); + + LogActionCompleted(nameof(GetOrders), stopWatch); + } + + private void GetLocks() + { + LogActionStart(nameof(GetLocks), out var stopWatch); + + foreach (var order in retrievedOrders) + { + var getLockTask = new GetOrderLockTask(Helpers, order.Id); + Tasks.Add(getLockTask); + + IsSuccessful &= getLockTask.Execute(); + if (!IsSuccessful) return; + + if (getLockTask.Status == Status.Fail) continue; + + LockInfos.Add(getLockTask.LockInfo); + + if (!order.CanCancel) + { + ordersThatCantBeCancelled.Add(order); + } + else if (!getLockTask.LockInfo.IsLockGranted) + { + lockedOrders.Add(order); + } + else + { + ordersToCancel.Add(order); + } + } + + LogActionCompleted(nameof(GetLocks), stopWatch); + } + + private void CancelOrders() + { + LogActionStart(nameof(CancelOrders), out var stopWatch); + + foreach (var order in ordersToCancel) + { + order.ReasonForCancellationOrRejection = reasonForCancellation; + var updateOrderStatusTask = new UpdateOrderStatusTask(Helpers, order, OrderStatus.Cancelled); + Tasks.Add(updateOrderStatusTask); + updateOrderStatusTask.Execute(); + + Helpers.LockManager.ReleaseOrderLock(order.Id); + + if (updateOrderStatusTask.Status == Status.Fail) + { + ordersThatFailedToBeCancelled.Add(order); + } + else + { + ordersThatSucceededToBeCancelled.Add(order); + } + } + + LogActionCompleted(nameof(CancelOrders), stopWatch); + } + + private void ShowResultsInUi() + { + var sb = new StringBuilder(); + + if (ordersThatSucceededToBeCancelled.Any()) + { + sb.AppendLine($"Order{(lockedOrders.Count > 1 ? "s" : String.Empty)} {string.Join(", ", ordersThatSucceededToBeCancelled.Select(o => o.Name))} {(lockedOrders.Count > 1 ? "were" : "was")} successfully canceled."); + } + + if (orderIdsThatFailedToBeRetrieved.Any()) + { + sb.AppendLine($"Some orders could not be retrieved."); + } + + if (ordersThatFailedToBeCancelled.Any()) + { + sb.AppendLine($"Orders {string.Join(", ", ordersThatFailedToBeCancelled.Select(o => o.Name))} failed to get canceled."); + } + + foreach (var order in ordersThatCantBeCancelled) + { + sb.AppendLine($"Order {order.Name} can't be canceled because is has state {order.Status.GetDescription()}"); + } + + if (lockedOrders.Any()) + { + sb.AppendLine($"Order{(lockedOrders.Count > 1 ? "s" : String.Empty)} {string.Join(", ", lockedOrders.Select(o => o.Name))} couldn't be canceled because {(lockedOrders.Count > 1 ? "they are" : "it is")} locked."); + } + + PrepareUiForManualMessage(sb.ToString(), showSendReportButton: false, showExceptionWidgets: false); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/CancelMultipleOrders_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/CancelMultipleOrders_2.csproj new file mode 100644 index 0000000..97898fa --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/CancelMultipleOrders_2.csproj @@ -0,0 +1,101 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {CFA4A2CE-A230-4303-83B1-677B23B66266} + Library + Properties + CancelMultipleOrders_2 + CancelMultipleOrders_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\CancelMultipleOrders_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\CancelMultipleOrders_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d14bf05 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("CancelMultipleOrders_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("CancelMultipleOrders_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("A2D7791A-1055-4790-B9DA-722276902179")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/Script.cs new file mode 100644 index 0000000..6a7502a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/Script.cs @@ -0,0 +1,158 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace CancelMultipleOrders_2 +{ + using System; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + using OrderStatus = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + /// + /// DataMiner Script Class. + /// + class Script : IDisposable + { + private Helpers helpers; + private InteractiveController app; + private ProvideReasonForStatusChangeDialog provideReasonForStatusChangeDialog; + private CancelMultipleOrdersProgressDialog cancelMultipleOrdersProgresssDialog; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + try + { + //engine.ShowUI(); + engine.Timeout = TimeSpan.FromHours(10); + + app = new InteractiveController(engine); + helpers = new Helpers(engine, Scripts.CancelMultipleOrders); + + provideReasonForStatusChangeDialog = new ProvideReasonForStatusChangeDialog(engine, OrderStatus.Cancelled); + provideReasonForStatusChangeDialog.OkButton.Pressed += CancelOrders; + app.Run(provideReasonForStatusChangeDialog); + } + catch (ScriptAbortException) + { + // nothing + } + catch (InteractiveUserDetachedException) + { + // nothing + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Something went wrong: {e}"); + ShowExceptionDialog(e); + } + finally + { + helpers.LockManager.ReleaseLocks(); + Dispose(); + } + } + + private void CancelOrders(object sender, EventArgs e) + { + cancelMultipleOrdersProgresssDialog = new CancelMultipleOrdersProgressDialog(helpers, provideReasonForStatusChangeDialog.ReasonForStatusChange); + cancelMultipleOrdersProgresssDialog.Execute(); + helpers.LockManager.ReleaseLocks(); + + if (app.IsRunning) app.ShowDialog(cancelMultipleOrdersProgresssDialog); + else app.Run(cancelMultipleOrdersProgresssDialog); + } + + private void ShowExceptionDialog(Exception exception) + { + var dialog = new ExceptionDialog((Engine)helpers.Engine, exception); + dialog.OkButton.Pressed += (sender, args) => helpers.Engine.ExitSuccess("Something went wrong during the creation of the new Order."); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + #region IDisposable Support + private bool disposedValue; // To detect redundant calls + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue && disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + + ~Script() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(false); + } + + // This code added to correctly implement the disposable pattern. + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CancelMultipleOrders_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices.xml new file mode 100644 index 0000000..b0bafda --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices.xml @@ -0,0 +1,28 @@ + + + ClearExpiredServices + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/SRM + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/.editorconfig new file mode 100644 index 0000000..c54055f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/.editorconfig @@ -0,0 +1,17 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true + +# SA1501: Statement should not be on a single line +dotnet_diagnostic.SA1501.severity = none + +# S1172: Unused method parameters should be removed +dotnet_diagnostic.S1172.severity = none diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/ClearExpiredServices_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/ClearExpiredServices_1.csproj new file mode 100644 index 0000000..8c660bf --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/ClearExpiredServices_1.csproj @@ -0,0 +1,101 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {951F433D-47BB-46CD-9577-38DC2EEF38F1} + Library + Properties + ClearExpiredServices_1 + ClearExpiredServices_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ClearExpiredServices_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ClearExpiredServices_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + 1.1.0.5 + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f98fa16 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ClearExpiredServices_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ClearExpiredServices_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("F8794006-B94C-4989-8415-3470A9741382")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/Script.cs new file mode 100644 index 0000000..63617ce --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/Script.cs @@ -0,0 +1,384 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace ClearExpiredServices_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.Advanced; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ReportsAndDashboards; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Net.ServiceManager.Objects; + using Skyline.DataMiner.Net.Ticketing; + + /// + /// DataMiner Script Class. + /// + class Script : IDisposable + { + private Helpers helpers; + private TicketingGatewayHelper ticketingHelper; + + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + helpers = new Helpers(engine, Scripts.ClearExpiredServices); + engine.Timeout = TimeSpan.FromHours(2); + + ticketingHelper = new TicketingGatewayHelper { HandleEventsAsync = false }; + ticketingHelper.RequestResponseEvent += (sender, args) => args.responseMessage = Engine.SLNet.SendSingleResponseMessage(args.requestMessage); + + ReportInfo reportInfo = new ReportInfo(); + reportInfo = RetrieveServicesToRemove(engine, reportInfo); + reportInfo = RetrieveServiceDefinitionsToRemove(reportInfo); + + if (reportInfo.ServicesToRemove.Any()) RemoveServices(reportInfo.ServicesToRemove); + if (reportInfo.ReservationsToRemove.Any()) RemoveReservationInstances(reportInfo.ReservationsToRemove); + if (reportInfo.TicketsToRemove.Any()) RemoveTickets(ticketingHelper, reportInfo.TicketsToRemove); + //if (reportInfo.ServiceDefinitionsToRemove.Any()) RemoveServiceDefinitions(reportInfo.ServiceDefinitionsToRemove); + + GenerateReport(engine, reportInfo); + + Dispose(); + } + + private void Log(string nameOfMethod, string message) + { + helpers?.Log(nameof(Script), nameOfMethod, message); + } + + private ReportInfo RetrieveServicesToRemove(Engine engine, ReportInfo reportInfo) + { + var dms = Engine.SLNetRaw.GetDms(); + + // get the srm service view + var srmServiceViews = dms.GetViews().Where(v => v.Name.Contains("Services")).ToList(); + if (!srmServiceViews.Any()) + { + Log(nameof(RetrieveServicesToRemove), "No SRM service views found"); + return reportInfo; + } + + reportInfo.ServicesToRemove = new List(); + reportInfo.ReservationsToRemove = new List(); + reportInfo.TicketsToRemove = new List(); + + foreach (var service in dms.GetServices()) + { + if (!service.Views.Overlaps(srmServiceViews)) + { + // not an SRM service + continue; + } + + // find reservation instance with name of this service + var reservationInstance = FindReservationInstance(service.Name); + if (reservationInstance == null) + { + reportInfo.ServicesToRemove.Add(service.DmsServiceId); + continue; + } + + // check if it's an order or service + if (IsOrderReservationInstance(reservationInstance)) + { + // Remove the DM Service if the order is finished (this should have happened by the SRM solution) + if (reservationInstance.End.AddHours(1) < DateTime.Now) + { + reportInfo.ServicesToRemove.Add(service.DmsServiceId); + } + + // no need to remove the reservation instances of orders. + continue; + } + + // find service order reservation instances + var orderReservationInstances = FindOrderReservationInstancesForService(reservationInstance); + bool isUsedByOneOrMoreOrders = orderReservationInstances.Any(); + + if (!isUsedByOneOrMoreOrders) + { + // remove service and service reservationInstance if there is no order reservation for it + reportInfo.ReservationsToRemove.Add(reservationInstance); + reportInfo.TicketsToRemove.AddRange(FindTicketsForService(ticketingHelper, reservationInstance)); + reportInfo.ServicesToRemove.Add(service.DmsServiceId); + } + } + + return reportInfo; + } + + private ReportInfo RetrieveServiceDefinitionsToRemove(ReportInfo reportInfo) + { + reportInfo.ServiceDefinitionsToRemove = new List(); + + var serviceDefinitions = DataMinerInterface.ServiceManager.GetServiceDefinitions(helpers, ServiceDefinitionExposers.Name.NotMatches("_.*").AND(ServiceDefinitionExposers.Name.NotMatches(".*[.]Default"))).ToArray(); + + foreach (var serviceDefinition in serviceDefinitions) + { + try + { + var filter = ServiceReservationInstanceExposers.ServiceDefinitionID.Equal(serviceDefinition.ID); + var reservationInstances = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, filter); + + if (reservationInstances == null) + { + reportInfo.ExtraMessages.Add($"Received null when requesting reservation instances using service definition {serviceDefinition.Name}"); + continue; + } + + if (reservationInstances.Any()) continue; // the SD is being used + + reportInfo.ServiceDefinitionsToRemove.Add(serviceDefinition); + } + catch (Exception e) + { + reportInfo.ExtraMessages.Add($"Exception occurred while getting reservations for definition {serviceDefinition.ID}: {e}"); + } + } + + return reportInfo; + } + + private ReservationInstance FindReservationInstance(string name) + { + try + { + return DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(ReservationInstanceExposers.Name.Contains(name))).FirstOrDefault(); + } + catch (Exception) + { + // no need to log + } + + return null; + } + + private static bool IsOrderReservationInstance(ReservationInstance reservationInstance) + { + try + { + var virtualPlatformProperty = reservationInstance.Properties.FirstOrDefault(p => p.Key == "Virtual Platform"); + if (virtualPlatformProperty.Value == null || String.IsNullOrEmpty(Convert.ToString(virtualPlatformProperty.Value))) return true; + + return virtualPlatformProperty.Value.ToString() == "Order"; + } + catch (Exception) + { + // no need to log + } + + return true; + } + + private List FindOrderReservationInstancesForService(ReservationInstance serviceReservationInstance) + { + var orderReservationInstances = new List(); + + try + { + var contributingResourceFilter = ReservationInstanceExposers.ResourceIDsInReservationInstance.Contains(serviceReservationInstance.ID); + + orderReservationInstances = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(contributingResourceFilter)).ToList(); + } + catch (Exception ex) + { + Log(nameof(FindOrderReservationInstancesForService), $"Exception occurred while finding order reservations using contributing resource {serviceReservationInstance.ID}: {ex}"); + } + + return orderReservationInstances; + } + + private static List FindTicketsForService(TicketingGatewayHelper helper, ReservationInstance serviceReservationInstance) + { + try + { + return helper.GetTickets(filter: TicketingExposers.CustomTicketFields.DictStringField("Service ID").Equal(serviceReservationInstance.ID.ToString())).ToList(); + } + catch (Exception) + { + // no need to log + } + + return new List(); + } + + private static void GenerateReport(Engine engine, ReportInfo reportInfo) + { + var message = new StringBuilder(); + + message.AppendLine("Services to remove: "); + if (!reportInfo.ServicesToRemove.Any()) message.Append("None
"); + foreach (var service in reportInfo.ServicesToRemove) message.AppendLine($"
{service.Value}"); + + message.AppendLine("
"); + message.AppendLine("
Reservations to remove: "); + if (!reportInfo.ReservationsToRemove.Any()) message.Append("None
"); + foreach (var reservationInstance in reportInfo.ReservationsToRemove) message.AppendLine($"
{reservationInstance.Name} [{reservationInstance.ID}]"); + + message.AppendLine("
"); + message.AppendLine("
Tickets to remove: "); + if (!reportInfo.TicketsToRemove.Any()) message.Append("None
"); + foreach (var ticket in reportInfo.TicketsToRemove) message.AppendLine($"
{ticket.ID}"); + + message.AppendLine("
"); + message.AppendLine("
Service Definitions that are marked to be removed: "); + if (!reportInfo.ServiceDefinitionsToRemove.Any()) message.Append("None
"); + foreach (var serviceDefinition in reportInfo.ServiceDefinitionsToRemove) message.AppendLine($"
{serviceDefinition.Name}"); + + message.AppendLine("
"); + message.AppendLine("
Extra messages: "); + foreach(var extraMessage in reportInfo.ExtraMessages) message.AppendLine($"
{extraMessage}"); + + engine.SendEmail(new EmailOptions(message.ToString(), "YLE DEBUG - Clear Expired Services Report", "squad.deploy-the.pioneers@skyline.be")); + } + + private void RemoveServices(List services) + { + foreach (var serviceId in services) + { + try + { + helpers.Engine.SendSLNetMessage(new SetDataMinerInfoMessage + { + Uia1 = new UIA(new[] { (uint)serviceId.AgentId, (uint)serviceId.ServiceId }), + What = 74 + }); + } + catch (Exception e) + { + Log(nameof(RemoveServices), $"Exception removing service '{serviceId}': {e}"); + } + } + } + + private void RemoveReservationInstances(List reservationInstances) + { + try + { + helpers.ResourceManager.RemoveReservationInstances(reservationInstances.ToArray()); + } + catch (Exception e) + { + Log(nameof(RemoveReservationInstances), $"Exception removing reservations: {e}"); + } + } + + private void RemoveTickets(TicketingGatewayHelper helper, List tickets) + { + if (tickets.Any()) + { + try + { + if (!helper.RemoveTickets(out var error, tickets.ToArray())) + { + Log(nameof(RemoveTickets), $"Error removing tickets: {error}"); + } + } + catch (Exception e) + { + Log(nameof(RemoveTickets), $"Exception removing tickets: {e}"); + } + } + } + + private bool disposedValue; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue && disposing) + { + helpers.Dispose(); + + helpers.LockManager.ReleaseLocks(); + } + + disposedValue = true; + } + + ~Script() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + + class ReportInfo + { + public List ServicesToRemove { get; set; } = new List(); + + public List ReservationsToRemove { get; set; } = new List(); + + public List TicketsToRemove { get; set; } = new List(); + + public List ServiceDefinitionsToRemove { get; set; } = new List(); + + public List ExtraMessages { get; set; } = new List(); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearExpiredServices_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations.xml new file mode 100644 index 0000000..657234a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations.xml @@ -0,0 +1,29 @@ + + ClearReservations + Script 1.0.1.77 + Automation + SKYLINE2\ThomasRE + FALSE + YLE/SRM + + + + + + + ConfirmClearAll + + + ClearNonLive + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/ClearReservations_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/ClearReservations_2.csproj new file mode 100644 index 0000000..ca08c6d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/ClearReservations_2.csproj @@ -0,0 +1,92 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {BF317DEB-2946-49C4-A6D2-3A0B4175AF64} + Library + Properties + ClearReservations_2 + ClearReservations_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ClearReservations_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ClearReservations_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7dfcf0c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ClearReservations_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ClearReservations_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("188C15ED-0693-49F8-BD62-9C2F11730ED1")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/Script.cs new file mode 100644 index 0000000..3ef6355 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/Script.cs @@ -0,0 +1,513 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2020 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace ClearReservations_2 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Net.Jobs; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.Advanced; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Net.ServiceManager.Objects; + using Skyline.DataMiner.Net.Ticketing; + using Skyline.DataMiner.Net.Ticketing.Helpers; + + /// + /// DataMiner Script Class. + /// + class Script + { + private static readonly string[] contributingResourcePoolNames = new[] { "Audio Processing", "Destination Service", "Graphics Processing Service", "Reception", "Recording Service", "Routing", "Transmission", "Video Processing Service" }; + + private static readonly string[] serviceNamesToKeep = new[] { "YleX" }; + + private const string userTasksTicketDomainName = "User Tasks"; + //private const string ingestExportTicketDomainName = "Ingest/Export"; + private const string notesTicketDomainName = "Notes"; + + private bool clearNonLive; + + private const string IngestExportFkTicketField = "Ingest Export FK"; + private const string ServiceIdTicketField = "Service ID"; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + if (engine.GetScriptParam(1).Value != "yes") return; + + clearNonLive = bool.TryParse(engine.GetScriptParam(3).Value, out bool parsedClearNonLive) && parsedClearNonLive; + + engine.Timeout = TimeSpan.FromHours(5); + + ClearSrmData(engine); + ClearServices(engine); + ClearJobs(engine); + ClearTickets(engine); + ClearOrderManagerData(engine); + + // Clear the generated SRM protocols + // Comment this in case not needed + //ClearSrmProtocols(engine); + } + + private static void ClearSrmData(Engine engine) + { + var resourceManager = new ResourceManagerHelper(); + resourceManager.RequestResponseEvent += (s, e) => e.responseMessage = Engine.SLNet.SendSingleResponseMessage(e.requestMessage); + + // remove all reservations + if (RemoveAllReservations(engine, resourceManager)) + { + engine.Log("(ClearSrmData) Reservation instances are deleted"); + } + // Used in case RemoveAllReservations would throw an out of memory exception + else if (RemoveReservationsInBulk(engine, resourceManager)) + { + engine.Log("(ClearSrmData) Reservation instances are deleted"); + } + else + { + engine.Log("(ClearSrmData) Unable to remove reservation instances"); + } + + var serviceHelper = new ServiceManagerHelper(); + serviceHelper.RequestResponseEvent += (s, e) => e.responseMessage = Engine.SLNet.SendSingleResponseMessage(e.requestMessage); + + // remove all SRMServiceInfo + try + { + var srmServiceInfo = serviceHelper.GetSRMServiceInfo(SRMServiceInfoExposers.Name.NotEqual(String.Empty)).ToArray(); + if (srmServiceInfo.Any()) + { + engine.Log("(ClearSrmData) Removing SRM service info: " + srmServiceInfo.Length); + serviceHelper.RemoveSRMServiceInfo(srmServiceInfo); + engine.Log("(ClearSrmData) Removing SRM service completed"); + } + } + catch (Exception e) + { + engine.Log("[ClearSrmData]Error removing SRM Service Info: " + e); + } + + // remove all SRMSettableServiceStates + try + { + var srmSettableServiceStates = serviceHelper.SRMSettableServiceStates.Read(SRMSettableServiceStateExposers.ServiceId.NotEqual("")); + if (srmSettableServiceStates.Any()) + { + engine.Log("(ClearSrmData) Removing SRM settable service state: " + srmSettableServiceStates.Count); + foreach (var srmSettableServiceState in srmSettableServiceStates) serviceHelper.SRMSettableServiceStates.Delete(srmSettableServiceState); + engine.Log("(ClearSrmData) Removing SRM settable service state completed"); + } + + } + catch (Exception e) + { + engine.Log("[ClearSrmData]Error removing SRM Settable Service States: " + e); + } + + // remove all generated service definitions + try + { + // all static service definitions start with an '_' in the name + var serviceDefinitions = serviceHelper.GetServiceDefinitions(ServiceDefinitionExposers.IsTemplate.Equal(true)).Where(s => !s.Name.StartsWith("_")).ToArray(); + if (serviceDefinitions.Any()) + { + engine.Log("(ClearSrmData) Removing service definitions: " + serviceDefinitions.Length); + if (!serviceHelper.RemoveServiceDefinitions(out var error, serviceDefinitions)) + { + engine.Log("[ClearSrmData]Error removing service definitions: " + error); + } + engine.Log("(ClearSrmData) Removing service definitions completed"); + } + } + catch (Exception e) + { + engine.Log("[ClearSrmData]Error removing service definitions: " + e); + } + + // remove all contributed resources + try + { + // first get the pool ids for the contributing resource pools + var resourcePools = resourceManager.GetResourcePools(); + var contributingResourcePoolGuids = resourcePools.Where(r => contributingResourcePoolNames.Contains(r.Name)).Select(r => r.GUID); + + var resourcePoolGuidFilter = new ORFilterElement(contributingResourcePoolGuids.Select(guid => new ORFilterElement(ResourceExposers.PoolGUIDs.Contains(guid))).ToArray()); + + // get the resources from the contributing resource pools + var resources = resourceManager.GetResources(resourcePoolGuidFilter); + if (resources.Any()) + { + engine.Log("(ClearSrmData) Removing contributing resources: " + resources.Length); + resourceManager.RemoveResources(resources); + engine.Log("(ClearSrmData) Removing contributing resources completed"); + } + } + catch (Exception e) + { + engine.Log("[ClearSrmData]Error removing resources: " + e); + } + } + + private static bool RemoveAllReservations(Engine engine, ResourceManagerHelper resourceManager) + { + try + { + var reservationInstances = resourceManager.GetReservationInstances(ReservationInstanceExposers.Start.GreaterThanOrEqual(DateTime.MinValue)); + if (reservationInstances.Any()) + { + engine.Log("(ClearSrmData) Removing reservations: " + reservationInstances.Count()); + + resourceManager.RemoveReservationInstances(reservationInstances); + + engine.Log("(ClearSrmData) Removing reservations completed"); + return true; + } + else + { + engine.Log("(ClearSrmData) Removing reservations: No reservations found"); + return true; + } + } + catch (Exception e) + { + engine.Log("[ClearSrmData]Error removing reservations: " + e); + return false; + } + } + + private static bool RemoveReservationsInBulk(Engine engine, ResourceManagerHelper resourceManager) + { + try + { + var reservationInstances = resourceManager.GetReservationInstances(ReservationInstanceExposers.Start.GreaterThanOrEqual(DateTime.MinValue)); + if (!reservationInstances.Any()) + { + engine.Log("(ClearSrmData) Removing reservations: No reservations found"); + return true; + } + + engine.Log($"(ClearSrmData) Clearing {reservationInstances.Count()} reservations"); + + for (int start = 0; start < reservationInstances.Length; start += 1000) + { + int end = start + 1000; + if (end >= reservationInstances.Length) end = reservationInstances.Length - 1; + + var reservationsToRemove = new ReservationInstance[end - start]; + + Array.Copy(reservationInstances, start, reservationsToRemove, 0, reservationsToRemove.Length); + + engine.Log($"(ClearSrmData) Removing first {end} reservations"); + + resourceManager.RemoveReservationInstances(reservationsToRemove); + + engine.Log($"(ClearSrmData) Removing first {end} reservations completed"); + } + + return true; + } + catch (Exception e) + { + engine.Log("[ClearSrmData]Error removing reservations: " + e); + return false; + } + } + + private static void ClearServices(Engine engine) + { + try + { + var messages = Engine.SLNet.SendMessage(new GetInfoMessage(InfoType.ServiceInfo)); + engine.Log("(ClearServices) Removing services: " + messages.Length); + + foreach (DMSMessage message in messages) + { + ServiceInfoEventMessage service = message as ServiceInfoEventMessage; + if (service == null) continue; + + // skip templates + if (service.Type != ServiceType.Service) continue; + + // skip services that shouldn't be removed + if (serviceNamesToKeep.Contains(service.Name)) continue; + + engine.SendSLNetMessage(new SetDataMinerInfoMessage + { + Uia1 = new UIA(new[] { (uint)service.DataMinerID, (uint)service.ElementID }), + What = 74 + }); + } + + engine.Log("(ClearServices) Removing services completed"); + } + catch (Exception e) + { + engine.Log("[ClearServices]Error removing services: " + e); + } + } + + private static void ClearJobs(Engine engine) + { + var jobManagerHelper = new JobManagerHelper(m => Engine.SLNet.SendMessages(m)); + + try + { + var jobs = jobManagerHelper.Jobs.Read(JobExposers.FieldValues.JobStartGreaterThan(DateTime.MinValue)); + engine.Log("(ClearJobs) Removing jobs: " + jobs.Count); + + foreach (var job in jobs) + { + jobManagerHelper.Jobs.Delete(job); + } + + engine.Log("(ClearJobs) Removing jobs completed"); + } + catch (Exception e) + { + engine.Log("[ClearJobs]Error removing jobs: " + e); + } + } + + private void ClearTickets(Engine engine) + { + var ticketingHelper = new TicketingGatewayHelper { HandleEventsAsync = false }; + ticketingHelper.RequestResponseEvent += (s, e) => e.responseMessage = Engine.SLNet.SendSingleResponseMessage(e.requestMessage); + + // remove all user tasks + try + { + var userTasksTicketFieldResolver = ticketingHelper.GetTicketFieldResolvers(TicketFieldResolver.Factory.CreateEmptyResolver(userTasksTicketDomainName)).FirstOrDefault() ?? throw new InvalidOperationException("Could not find user task ticket field resolver"); + var userTaskTickets = ticketingHelper.GetTickets(null, TicketingExposers.ResolverID.Equal(userTasksTicketFieldResolver.ID)); + List ticketsToRemove = new List(); + foreach (Ticket ticket in userTaskTickets) + { + if (ticket.CustomTicketFields.TryGetValue(IngestExportFkTicketField, out object nonLiveForeignKey) && !String.IsNullOrEmpty(Convert.ToString(nonLiveForeignKey)) && !clearNonLive) + { + engine.Log($"ClearTickets|User Tasks|Skipped removing ticket {ticket.ID.ToString()} because it contains an Ingest Export FK {nonLiveForeignKey}"); + continue; // Non-Live user task + } + + if (!ticket.CustomTicketFields.TryGetValue(ServiceIdTicketField, out object serviceId) || String.IsNullOrEmpty(Convert.ToString(serviceId)) && !clearNonLive) + { + engine.Log($"ClearTickets|User Tasks|Skipped removing ticket {ticket.ID.ToString()} because it has an empty Service ID field"); + continue; // Possible Non-Live user task + } + + ticketsToRemove.Add(ticket); + } + + engine.Log($"ClearTickets|User Tasks|User task tickets to remove {ticketsToRemove.Count} | {String.Join(", ", ticketsToRemove.Select(x => x.ID.ToString()))}"); + //RemoveTickets(engine, userTasksTicketDomainName, ticketingHelper, ticketsToRemove); + } + catch (Exception e) + { + engine.Log("[ClearTickets]Error removing user task tickets: " + e); + } + + // remove all ingest/export tickets + //if (ClearNonLive) + //{ + // try + // { + // var ingestExportTicketFieldResolver = ticketingHelper.GetTicketFieldResolvers(TicketFieldResolver.Factory.CreateEmptyResolver(ingestExportTicketDomainName)).FirstOrDefault(); + // var ingestExportTickets = ticketingHelper.GetTickets(null, TicketingExposers.ResolverID.Equal(ingestExportTicketFieldResolver.ID)); + // RemoveTickets(engine, ingestExportTicketDomainName, ticketingHelper, ingestExportTickets); + // } + // catch (Exception e) + // { + // engine.Log("[ClearTickets]Error removing ingest/export tickets: " + e); + // } + //} + + // remove all notes tickets + try + { + var notesTicketFieldResolver = ticketingHelper.GetTicketFieldResolvers(TicketFieldResolver.Factory.CreateEmptyResolver(notesTicketDomainName)).FirstOrDefault() ?? throw new InvalidOperationException("Could not find ticket field resolver"); + var notesTickets = ticketingHelper.GetTickets(null, TicketingExposers.ResolverID.Equal(notesTicketFieldResolver.ID)); + RemoveTickets(engine, notesTicketDomainName, ticketingHelper, notesTickets); + } + catch (Exception e) + { + engine.Log("[ClearTickets]Error removing notes tickets: " + e); + } + } + + private static void RemoveTickets(IEngine engine, string domain, TicketingGatewayHelper ticketingHelper, IEnumerable ticketsToRemove) + { + if (ticketsToRemove.Any()) + { + engine.Log($"{nameof(RemoveTickets)}|{domain}|Removing tickets: " + ticketsToRemove.Count()); + + if (!ticketingHelper.RemoveTickets(out var error, ticketsToRemove.ToArray())) + { + engine.Log($"{nameof(RemoveTickets)}|{domain}|Error removing user task tickets: " + error); + } + + engine.Log($"{nameof(RemoveTickets)}|{domain}|Removing tickets completed"); + } + } + + private static void ClearOrderManagerData(Engine engine) + { + var orderManagerElement = engine.FindElementsByProtocol("Finnish Broadcasting Company Order Manager").FirstOrDefault(); + if (orderManagerElement == null) + { + engine.Log("(ClearOrderManagerData) Order Manager element not found"); + return; + } + + if (!orderManagerElement.IsActive) + { + engine.Log("(ClearOrderManagerData) Order Manager element not active"); + return; + } + + try + { + var orderReservationIds = orderManagerElement.GetTablePrimaryKeys(2000); + foreach (var orderReservationId in orderReservationIds) orderManagerElement.SetParameterByPrimaryKey(2006, orderReservationId, "Delete"); + + var eventJobIds = orderManagerElement.GetTablePrimaryKeys(2500); + foreach (var eventJobId in eventJobIds) orderManagerElement.SetParameterByPrimaryKey(2507, eventJobId, "Delete"); + } + catch (Exception e) + { + engine.Log("(ClearOrderManagerData) Exception clearing data from order manager: " + e); + } + } + + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Major Code Smell", "S1144:Unused private types or members should be removed", Justification = "")] + private static void ClearSrmProtocols(Engine engine) + { + try + { + engine.Log("(ClearSrmProtocols) Removing SRM protocols"); + + var functions = (GetProtocolFunctionsResponseMessage)Engine.SLNet.SendSingleResponseMessage(new GetProtocolFunctionsMessage()); + + var messages = engine.SendSLNetMessage(new GetInfoMessage(InfoType.Protocols)); + foreach (DMSMessage message in messages) + { + GetProtocolsResponseMessage protocolInfoMessage = message as GetProtocolsResponseMessage; + if (protocolInfoMessage == null) continue; + + if (!protocolInfoMessage.Protocol.StartsWith("_")) continue; + + var protocolFunctions = functions.Functions.Where(f => f.ProtocolName == protocolInfoMessage.Protocol); + DeleteFunctionsXml(engine, protocolInfoMessage.Protocol, protocolFunctions); + + DeleteProtocolVersions(engine, protocolInfoMessage.Protocol, protocolInfoMessage.Versions); + } + + engine.Log("(ClearSrmProtocols) Removing ingest/export tickets completed"); + } + catch (Exception e) + { + engine.Log("[ClearSrmProtocols]Error removing SRM protocols: " + e); + } + } + + private static void DeleteFunctionsXml(Engine engine, string protocol, IEnumerable protocolFunctions) + { + foreach (var protocolFunction in protocolFunctions) + { + foreach (var protocolFunctionVersion in protocolFunction.ProtocolFunctionVersions) + { + try + { + Engine.SLNet.SendSingleResponseMessage(new DeleteFunctionsXmlRequestMessage + { + FileName = protocolFunctionVersion.FileName, + Force = true, + ProtocolName = protocol + }); + } + catch (Exception) + { + engine.Log("[ClearSrmProtocols]Error removing SRM protocol function: " + protocol); + } + } + } + } + + private static void DeleteProtocolVersions(Engine engine, string protocol, IEnumerable versions) + { + foreach (string version in versions) + { + try + { + Engine.SLNet.SendSingleResponseMessage(new DeleteProtocolFileMessage + { + Force = true, + ProtocolName = protocol, + ProtocolVersion = "", + Sa = new SA(new[] { protocol }), + What = 0 + }); + } + catch(Exception e) + { + engine.Log($"[ClearSrmProtocols]Error removing SRM protocol version: {protocol}.{version}: {e}"); + } + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ClearReservations_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors.xml new file mode 100644 index 0000000..faff9d4 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors.xml @@ -0,0 +1,26 @@ + + + Configure Ticketing Colors + Script 1.0.1.77 + Automation + SKYLINE2\Matthijs + FALSE + YLE/Tools + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/Configure Ticketing Colors_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/Configure Ticketing Colors_1.cs new file mode 100644 index 0000000..8350c9e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/Configure Ticketing Colors_1.cs @@ -0,0 +1,154 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.Net.Messages.SLDataGateway; +using Skyline.DataMiner.Net.Ticketing.Helpers; +using Skyline.DataMiner.Net.Ticketing.Helpers.Visualization; +using Skyline.DataMiner.Net.Tickets; + +/// +/// DataMiner Script Class. +/// +public class Script +{ + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + //Define Colors + Color Green = Color.FromArgb(0, 90, 204, 101); + Color Grey = Color.FromArgb(0, 184, 189, 183); + Color Yellow = Color.FromArgb(0, 229, 232, 63); + Color Orange = Color.FromArgb(0, 240, 189, 79); + Color White = Color.FromArgb(0, 255, 255, 255); + Color Red = Color.FromArgb(0, 242, 145, 145); + Color Blue = Color.FromArgb(0, 0, 128, 255); + + + // Create helper + var ticketingHelper = new TicketingHelper(engine.SendSLNetMessages); + + // Retrieve the existing resolver////////////////////////////////////////////////////////User Tasks + var filter = TicketFieldResolverExposers.Name.Equal("User Tasks"); + var resolver = ticketingHelper.TicketFieldResolvers.Read(filter).FirstOrDefault(); + if (resolver == null) + { + engine.GenerateInformation("No resolver found with that name"); + return; + } + + // Change the resolver + resolver.VisualizationHints = new TicketingVisualizationHints + { + VisualFieldEnums = new List + { + new VisualFieldEnum("State", 1, Grey.ToArgb()),//Incomplete + new VisualFieldEnum("State", 2, Green.ToArgb()),//Complete + new VisualFieldEnum("State", 3, Green.ToArgb())//Closed + } + }; + // Update the resolver on server + ticketingHelper.TicketFieldResolvers.Update(resolver); + + // Retrieve the existing resolver////////////////////////////////////////////////////////Non-Live Ingest/Export + filter = TicketFieldResolverExposers.Name.Equal("Ingest/Export"); + resolver = ticketingHelper.TicketFieldResolvers.Read(filter).FirstOrDefault(); + if (resolver == null) + { + engine.GenerateInformation("No resolver found with that name"); + return; + } + // Change the resolver + resolver.VisualizationHints = new TicketingVisualizationHints + { + VisualFieldEnums = new List + { + new VisualFieldEnum("State", 0, Grey.ToArgb()),//Preliminary + new VisualFieldEnum("State", 1, Yellow.ToArgb()),//Submitted + new VisualFieldEnum("State", 2, Green.ToArgb()),//Work In Progress + new VisualFieldEnum("State", 3, Orange.ToArgb()),//Change Requested + new VisualFieldEnum("State", 4, White.ToArgb()),//Completed + new VisualFieldEnum("State", 5, Red.ToArgb())//Cancelled By Customer + } + }; + // Update the resolver on server + ticketingHelper.TicketFieldResolvers.Update(resolver); + + // Retrieve the existing resolver////////////////////////////////////////////////////////Notes + filter = TicketFieldResolverExposers.Name.Equal("Notes"); + resolver = ticketingHelper.TicketFieldResolvers.Read(filter).FirstOrDefault(); + if (resolver == null) + { + engine.GenerateInformation("No resolver found with that name"); + return; + } + // Change the resolver + resolver.VisualizationHints = new TicketingVisualizationHints + { + VisualFieldEnums = new List + { + new VisualFieldEnum("State", 1, Grey.ToArgb()), //Open + new VisualFieldEnum("State", 2, White.ToArgb()), //Closed + new VisualFieldEnum("State", 3, Red.ToArgb()), //Alarm + new VisualFieldEnum("State", 4, Blue.ToArgb()) //Alarm Acknowledged + } + }; + + // Update the resolver on server + ticketingHelper.TicketFieldResolvers.Update(resolver); + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/Configure Ticketing Colors_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/Configure Ticketing Colors_1.csproj new file mode 100644 index 0000000..1d2449b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/Configure Ticketing Colors_1.csproj @@ -0,0 +1,90 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {161D23AA-B910-4826-984E-5F71E6115F3C} + Library + Properties + Configure_Ticketing_Colors_1 + Configure Ticketing Colors_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\Configure Ticketing Colors_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\Configure Ticketing Colors_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..cf76520 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Configure Ticketing Colors_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("Configure Ticketing Colors_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("494D264E-0E81-4F59-AC60-0B7A6BEB7726")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/app.config new file mode 100644 index 0000000..57e666a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Configure Ticketing Colors_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager.xml new file mode 100644 index 0000000..a941aa7 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager.xml @@ -0,0 +1,26 @@ + + + ConfigureContractManager + Script 1.0.1.77 + Automation + SKYLINE2\RijadCO + FALSE + YLE/Tools + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/ConfigureContractManagerDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/ConfigureContractManagerDialog.cs new file mode 100644 index 0000000..8e65db6 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/ConfigureContractManagerDialog.cs @@ -0,0 +1,158 @@ +namespace ConfigureContractManager_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text.RegularExpressions; + using System.Threading; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Automation; + + internal class ConfigureContractManagerDialog : Dialog + { + private int tableIdToPoll = ContractManagerProtocol.UsersTableID; + private Element element; + private readonly Helpers helpers; + private readonly Dictionary objectKeys = new Dictionary(); + private IReadOnlyDictionary columnIdxToColumnName = ContractManagerProtocol.NotificationParamsIDX; + private IDictionary table; + + private readonly Label infoLabel = new Label("Info:") { Style = TextStyle.Bold }; + private readonly Label tableToConfigureLabel = new Label("Table to Configure"); + private readonly Button updateButton = new Button("Update"); + private readonly Button getSelectedInfoButton = new Button("Get Selected Info"); + private readonly Label rowToConfigureLabel = new Label(); + private DropDown allObjectsDropdown; + private readonly DropDown typeOfConfigDropdown = new DropDown(EnumExtensions.GetEnumDescriptions()); + private readonly List allWidgetsToSet = new List(); + + public ConfigureContractManagerDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Configure Contract Manager"; + this.helpers = helpers; + Initialize(); + GenerateUI(); + } + + private void Initialize() + { + element = helpers.Engine.FindElementsByProtocol(ContractManagerProtocol.ProtocolName).SingleOrDefault() ?? throw new ElementNotFoundException(ContractManagerProtocol.ProtocolName); + rowToConfigureLabel.Text = $"{typeOfConfigDropdown.Selected.Trim('s')} to Configure"; + allObjectsDropdown = new DropDown(); + UpdateObjectsDropdown(); + typeOfConfigDropdown.Changed += TypeOfConfig_Changed; + getSelectedInfoButton.Pressed += GetObjectInfo_Pressed; + updateButton.Pressed += UpdateButton_Pressed; + } + + private void TypeOfConfig_Changed(object sender, DropDown.DropDownChangedEventArgs e) + { + try + { + objectKeys.Clear(); + allWidgetsToSet.Clear(); + var selectedType = typeOfConfigDropdown.Selected.GetEnumValue(); + tableIdToPoll = (selectedType == TypeToConfigure.User) ? ContractManagerProtocol.UsersTableID : ContractManagerProtocol.UsersGroupTableID; + columnIdxToColumnName = (selectedType == TypeToConfigure.User) ? ContractManagerProtocol.NotificationParamsIDX : ContractManagerProtocol.UserGroupParamsIDX; + rowToConfigureLabel.Text = $"{typeOfConfigDropdown.Selected.Trim('s')} to Configure"; + UpdateObjectsDropdown(); + GenerateUI(); + } + catch (Exception ex) + { + helpers.Log(nameof(Script), nameof(GetObjectInfo_Pressed), ex.ToString()); + } + } + + private void UpdateObjectsDropdown() + { + table = element.GetTable(helpers.Engine, tableIdToPoll); + var objectsFromTable = new List(); + foreach (var value in table.Values) + { + objectKeys.Add(Convert.ToString(value[1]), Convert.ToInt32(value[0])); + objectsFromTable.Add(Convert.ToString(value[1])); + } + allObjectsDropdown.SetOptions(objectsFromTable); + } + + private void GetObjectInfo_Pressed(object sender, EventArgs e) + { + try + { + allWidgetsToSet.Clear(); + int userKey = objectKeys[allObjectsDropdown.Selected]; + var userRow = table[userKey.ToString()]; + var selectedType = typeOfConfigDropdown.Selected.GetEnumValue(); + foreach (var idx in columnIdxToColumnName) + { + var labelAndCheckbox = new UsersGroupWidgets(); + labelAndCheckbox.Label.Text = idx.Value; + bool isUserTextParam = ((idx.Key == ContractManagerProtocol.UsersEmailIDX || idx.Key == ContractManagerProtocol.UsersPhoneIDX) && selectedType == TypeToConfigure.User); + bool isUsersGroupTextParam = ((idx.Key == ContractManagerProtocol.CompanyIdx || idx.Key == ContractManagerProtocol.GroupCustomNameIdx) && selectedType == TypeToConfigure.UserGroup); + if (isUserTextParam || isUsersGroupTextParam) + { + labelAndCheckbox.InteractiveWidget = new TextBox(Convert.ToString(userRow[idx.Key])); + } + else + { + labelAndCheckbox.InteractiveWidget = new CheckBox { IsChecked = Convert.ToBoolean(userRow[idx.Key]) }; + } + allWidgetsToSet.Add(labelAndCheckbox); + } + + GenerateUI(); + } + catch (Exception ex) + { + helpers.Log(nameof(Script), nameof(GetObjectInfo_Pressed), ex.ToString()); + } + } + + private void UpdateButton_Pressed(object sender, EventArgs e) + { + int userKey = objectKeys[allObjectsDropdown.Selected]; + var userRow = table[userKey.ToString()]; + foreach (var idx in columnIdxToColumnName) + { + var labelCheckboxPair = allWidgetsToSet.Single(x => x.Label.Text.Equals(idx.Value)); + userRow[idx.Key] = labelCheckboxPair.WidgetValue; + } + element.SetRow((Engine)helpers.Engine, tableIdToPoll, userKey.ToString(), userRow.ToArray()); + allWidgetsToSet.Clear(); + Thread.Sleep(1000); + table = element.GetTable(helpers.Engine, tableIdToPoll); + GenerateUI(); + } + + private void GenerateUI() + { + Clear(); + + int row = 0; + + AddWidget(tableToConfigureLabel, ++row, 0); + AddWidget(typeOfConfigDropdown, row, 1); + + AddWidget(rowToConfigureLabel, ++row, 0); + AddWidget(allObjectsDropdown, new WidgetLayout(row, 1)); + + AddWidget(getSelectedInfoButton, new WidgetLayout(++row, 0)); + + if (allWidgetsToSet.Any()) + { + AddWidget(infoLabel, ++row, 0, 1, 2); + foreach (var item in allWidgetsToSet) + { + AddWidget(item.Label, ++row, 0); + AddWidget(item.InteractiveWidget, row, 1); + } + AddWidget(updateButton, row + 1, 0); + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/ConfigureContractManager_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/ConfigureContractManager_1.cs new file mode 100644 index 0000000..9fdb927 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/ConfigureContractManager_1.cs @@ -0,0 +1,119 @@ +/* +**************************************************************************** +* Copyright (c) 2023, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2023 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace ConfigureContractManager_1 +{ + using System; + using System.Runtime.Remoting.Channels; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + + /// + /// Represents a DataMiner Automation script. + /// + public class Script : IDisposable + { + private InteractiveController app; + private Helpers helpers; + /// + /// The script entry point. + /// + /// Link with SLAutomation process. + public void Run(IEngine engine) + { + try + { + // engine.ShowUI(); + helpers = new Helpers(engine, Scripts.ConfigureContractManager); + app = new InteractiveController(engine); + var dialog = new ConfigureContractManagerDialog(helpers); + app.Run(dialog); + } + catch (Exception ex) + { + helpers.Log(nameof(Script), nameof(Run), ex.ToString()); + } + finally + { + Dispose(); + } + } + + #region IDisposable Support + private bool disposedValue; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue && disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + + ~Script() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + #endregion + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/ConfigureContractManager_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/ConfigureContractManager_1.csproj new file mode 100644 index 0000000..bf36a0a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/ConfigureContractManager_1.csproj @@ -0,0 +1,99 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {5D786C6B-2A75-440B-A1FB-C077E8B8B898} + Library + Properties + ConfigureContractManager_1 + ConfigureContractManager_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ConfigureContractManager_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ConfigureContractManager_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + C:\Skyline DataMiner\Files\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..951bb46 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ConfigureContractManager_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ConfigureContractManager_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("5E3AB466-FBAB-40E4-ADE1-B0E6D3253767")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/TypeToConfigure.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/TypeToConfigure.cs new file mode 100644 index 0000000..fe3e9b5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/TypeToConfigure.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ConfigureContractManager_1 +{ + public enum TypeToConfigure + { + [Description("Users")] + User, + [Description("User Groups")] + UserGroup, + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/UsersGroupWidgets.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/UsersGroupWidgets.cs new file mode 100644 index 0000000..0f3e085 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/UsersGroupWidgets.cs @@ -0,0 +1,30 @@ +namespace ConfigureContractManager_1 +{ + using System; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + internal class UsersGroupWidgets + { + public Label Label { get; set; } = new Label(); + public InteractiveWidget InteractiveWidget { get; set; } + + public object WidgetValue + { + get + { + if (InteractiveWidget is CheckBox checkBox) + { + return Convert.ToInt32(checkBox.IsChecked); + } + else if (InteractiveWidget is TextBox textBox) + { + return textBox.Text; + } + else + { + throw new NotSupportedException("Widget type not supported."); + } + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfigureContractManager_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders.xml new file mode 100644 index 0000000..4d3ca6b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders.xml @@ -0,0 +1,31 @@ + + + ConfirmOrders + Script 1.0.1.77 + Automation + SKYLINE2\thomasre + FALSE + YLE/Customer UI + + + + + + + + + + BookingID + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/ConfirmOrders_5.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/ConfirmOrders_5.csproj new file mode 100644 index 0000000..56f5807 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/ConfirmOrders_5.csproj @@ -0,0 +1,99 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {7F6A3EC0-1B12-4F2A-B0F8-1EBA1C113460} + Library + Properties + ConfirmOrders_5 + ConfirmOrders_5 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ConfirmOrders_5.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ConfirmOrders_5.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1f4d7e0 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ConfirmOrders_5")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ConfirmOrders_5")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("E1318018-211D-47C1-9A1A-35BDA7495AB5")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/Script.cs new file mode 100644 index 0000000..02e83d0 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/Script.cs @@ -0,0 +1,215 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +22/11/2021 1.0.0.1 TRE, Skyline Initial version +**************************************************************************** +*/ + +namespace ConfirmOrders_5 +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notifications; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.ResourceManager.Objects; + + /// + /// DataMiner Script Class. + /// + public class Script : IDisposable + { + private Helpers helpers; + + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + try + { + helpers = new Helpers(engine, Scripts.ConfirmOrders); + + var stopwatch = Stopwatch.StartNew(); + + var orderReservation = GetOrderReservationInstance(engine); + if (orderReservation != null) + { + Order order = helpers.OrderManager.GetOrder(orderReservation, forceServiceReservationsToOverwriteServiceConfig: false, skipGettingEvent: true); + + if (orderReservation.Start <= DateTime.Now.ToUniversalTime()) + { + // Order is running + helpers.Log(nameof(Script), nameof(Run), "Confirming Running Order"); + UpdateRunningOrderStatus(helpers, order, orderReservation); + } + else + { + // Order is not running + helpers.Log(nameof(Script), nameof(Run), "Confirming Non-Running Order"); + UpdateOrderStatus(helpers, order, orderReservation); + } + } + + stopwatch.Stop(); + helpers.Log(nameof(Script), nameof(Run), $"Confirming Order took {stopwatch.ElapsedMilliseconds} ms"); + } + catch (ScriptAbortException) + { + Dispose(); + } + catch (InteractiveUserDetachedException) + { + Dispose(); + } + catch (Exception e) + { + helpers?.Log(nameof(Script), nameof(Run), $"Something went wrong: {e}"); + Dispose(); + } + } + + private ServiceReservationInstance GetOrderReservationInstance(Engine engine) + { + if (!TryGetOrderId(engine, out var orderId)) + { + helpers.Log(nameof(Script), nameof(UpdateOrderStatus), $"Invalid booking id: {engine.GetScriptParam("BookingID")?.Value}"); + return null; + } + + var orderReservation = DataMinerInterface.ResourceManager.GetReservationInstance(helpers, orderId) as ServiceReservationInstance; + if (orderReservation == null) + { + helpers.Log(nameof(Script), nameof(UpdateOrderStatus), $"No reservation instance found with ID: {orderId}"); + return null; + } + + helpers.AddOrderReferencesForLogging(orderReservation.ID); + + return orderReservation; + } + + private static void UpdateRunningOrderStatus(Helpers helper, Order order, ReservationInstance reservation) + { + if (order == null) + { + helper.Log(nameof(Script), nameof(UpdateRunningOrderStatus), $"No Order found with ID: {reservation.ID}"); + return; + } + + order.UpdateStatus(helper, Status.Confirmed); + order.UpdateUiProperties(helper); + } + + private static void UpdateOrderStatus(Helpers helper, Order order, ServiceReservationInstance reservationInstance) + { + if (order == null) + { + helper.Log(nameof(Script), nameof(UpdateOrderStatus), $"No Order found with ID: {reservationInstance.ID}"); + return; + } + + order.Status = Status.Confirmed; + try + { + DataMinerInterface.ReservationInstance.UpdateServiceReservationProperties(helper, reservationInstance, new Dictionary { { LiteOrder.PropertyNameStatus, Status.Confirmed.GetDescription() } }); + helper.Log(nameof(Script), nameof(UpdateOrderStatus), $"Updated status of order {reservationInstance.ID} to Confirmed"); + } + catch(Exception e) + { + helper.Log(nameof(Script), nameof(UpdateOrderStatus), $"Unable to update status of order {reservationInstance.ID} to Confirmed|{e}"); + } + + order.UpdateUiProperties(helper); + NotificationManager.SendLiveOrderConfirmationMail(helper, order); + } + + private static bool TryGetOrderId(IEngine engine, out Guid orderId) + { + orderId = Guid.Empty; + string bookingId = engine.GetScriptParam("BookingID")?.Value; + + if (String.IsNullOrEmpty(bookingId)) return false; + if (!Guid.TryParse(bookingId, out orderId)) return false; + return true; + } + + #region IDisposable Support + private bool disposedValue; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + ~Script() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ConfirmOrders_5/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport.xml new file mode 100644 index 0000000..6623a21 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport.xml @@ -0,0 +1,26 @@ + + + CreateInvoiceReport + Script 1.0.1.77 + Automation + SKYLINE2\GillesVH + FALSE + YLE/Tools + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/CreateInvoiceReport_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/CreateInvoiceReport_1.cs new file mode 100644 index 0000000..50ed002 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/CreateInvoiceReport_1.cs @@ -0,0 +1,175 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Reports; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.ReportTasks; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; +using Skyline.DataMiner.Utils.InteractiveAutomationScript; +using Task = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.Task; + +/// +/// DataMiner Script Class. +/// +public class Script : IDisposable +{ + private InvoiceReportDialog invoiceReportDialog; + private LoadInvoiceReportDialog loadInvoiceReportDialog; + + private Helpers helpers; + private InteractiveController app; + + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + try + { + //engine.ShowUI() + helpers = new Helpers(engine, Scripts.CreateInvoiceReport); + + app = new InteractiveController(engine); + + loadInvoiceReportDialog = new LoadInvoiceReportDialog(helpers); + + if (loadInvoiceReportDialog.Execute()) ShowCreateInvoiceReportDialog(); + else app.Run(invoiceReportDialog); + } + catch (ScriptAbortException) + { + helpers?.Log(nameof(Script), nameof(Run), "STOP SCRIPT", "Create Invoice Report"); + Dispose(); + } + catch (InteractiveUserDetachedException) + { + helpers?.Log(nameof(Script), nameof(Run), "STOP SCRIPT", "Create Invoice Report"); + Dispose(); + } + catch (Exception e) + { + helpers?.Log(nameof(Script), nameof(Run), "STOP SCRIPT", "Create Invoice Report"); + engine.Log("Run|Something went wrong: " + e); + + Dispose(); + } + } + + private void ShowCreateInvoiceReportDialog() + { + invoiceReportDialog = loadInvoiceReportDialog.InvoiceReportDialog; + invoiceReportDialog.CreateInvoiceReportButton.Pressed += CreateInvoiceReportButton_Pressed; + + if (app.IsRunning) app.ShowDialog(invoiceReportDialog); + else app.Run(invoiceReportDialog); + } + + private void CreateInvoiceReportButton_Pressed(object sender, EventArgs e) + { + string selectedCompany = invoiceReportDialog.SelectedCompany; + DateTime selectedStartTime = invoiceReportDialog.SelectedStartTime; + DateTime selectedEndTime = invoiceReportDialog.SelectedEndTime; + + try + { + var reportDialog = new AddOrUpdateReportDialog(helpers); + reportDialog.OkButton.Pressed += (o, args) => { helpers.Engine.ExitSuccess($"Successfully Generated Invoice Report for company {selectedCompany}"); }; + app.ShowDialog(reportDialog); + + var tasks = new List(); + var generateInvoiceReportExcelTask = new GenerateInvoiceReportExcelTask(helpers, selectedStartTime, selectedEndTime, selectedCompany); + tasks.Add(generateInvoiceReportExcelTask); + + generateInvoiceReportExcelTask.Execute(); + + if (tasks.Any()) + { + reportDialog.Finish(tasks); + } + } + catch (Exception ex) + { + helpers.Log(nameof(Script), nameof(CreateInvoiceReportButton_Pressed), $"Something went wrong during creation of the invoice report for company {selectedCompany}: " + ex); + } + } + + #region IDisposable Support + protected virtual void Dispose(bool disposing) + { + if (!disposedValue && disposing) + { + helpers?.Dispose(); + } + + disposedValue = true; + } + + ~Script() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + #endregion +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/CreateInvoiceReport_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/CreateInvoiceReport_1.csproj new file mode 100644 index 0000000..2b6307f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/CreateInvoiceReport_1.csproj @@ -0,0 +1,102 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {8262B019-389D-4E9A-9EE4-606D3F2023FC} + Library + Properties + CreateInvoiceReport_1 + CreateInvoiceReport_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\CreateInvoiceReport_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\CreateInvoiceReport_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + False + ..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Net.Http.dll + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8ecd419 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("CreateInvoiceReport_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("CreateInvoiceReport_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("250B81BE-5073-47D2-BA71-2C3E86CC082D")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/app.config new file mode 100644 index 0000000..b8ffc0f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CreateInvoiceReport_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/CustomerUI_Launcher_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/CustomerUI_Launcher_2.csproj new file mode 100644 index 0000000..3498101 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/CustomerUI_Launcher_2.csproj @@ -0,0 +1,94 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {AE455D02-0572-43BA-B213-4D6BF8EDD37B} + Library + Properties + FinnishBroadcastingCompany_CustomerUI_Launcher_3 + FinnishBroadcastingCompany_CustomerUI_Launcher_3 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\FinnishBroadcastingCompany_CustomerUI_Launcher_3.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\FinnishBroadcastingCompany_CustomerUI_Launcher_3.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..287a291 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("FinnishBroadcastingCompany_CustomerUI_Launcher_3")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("FinnishBroadcastingCompany_CustomerUI_Launcher_3")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("AE5D86EA-795E-4BF4-9068-58F3F01BA06C")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/Script.cs new file mode 100644 index 0000000..e5f1d83 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/Script.cs @@ -0,0 +1,408 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2020 1.0.0.1 TRE, Skyline Initial version +**************************************************************************** +*/ + +// Engine.ShowUI(); + +using System; +using System.Collections.Generic; +using System.Linq; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.Utils.InteractiveAutomationScript; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; +using Skyline.DataMiner.Net.ResourceManager.Objects; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + +/// +/// DataMiner Script Class. +/// +/// +/// DataMiner Script Class. +/// +public class Script : IDisposable +{ + private InteractiveController app; + + private Helpers helpers; + + private LaunchDialog dialog; + + private Engine engine; + + private string CustomerUiScriptName; + + private Element orderBookingManagerElement; + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + try + { + this.engine = engine; + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.SetFlag(RunTimeFlags.NoCheckingSets); + engine.Timeout = TimeSpan.FromHours(10); + RunSafe(engine); + } + catch (ScriptAbortException) + { + throw; + } + catch (Exception e) + { + engine.Log("Run|Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + } + + private void RunSafe(Engine engine) + { + // Init CustomerUiScriptName + CustomerUiScriptName = engine.GetScriptParam("CustomerUiScriptName").Value; + + // Find Order Booking Manager + orderBookingManagerElement = engine.FindElementsByName("Order Booking Manager").FirstOrDefault(); + if (orderBookingManagerElement == null) + { + engine.ExitFail("Unable to find Order Booking Manager"); + } + + // Launch Dialog + app = new InteractiveController(engine); + helpers = new Helpers(engine, Scripts.CustomerUiLauncher); + dialog = new LaunchDialog(engine, helpers.OrderManager.GetAllFutureAndOngoingVideoReservations(), helpers.EventManager.GetAllEvents()); + + dialog.ViewButton.Pressed += ViewButton_Pressed; + dialog.AddButton.Pressed += AddButton_Pressed; + dialog.AddFromTemplateButton.Pressed += AddFromTemplateButton_Pressed; + dialog.AddToEventButton.Pressed += AddToEventButton_Pressed; + dialog.EditButton.Pressed += EditButton_Pressed; + dialog.DuplicateButton.Pressed += DuplicateButton_Pressed; + + app.Run(dialog); + } + + private void EditButton_Pressed(object sender, EventArgs e) + { + ReservationInstance selectedOrder = dialog.SelectedOrder; + Guid guid = Guid.Empty; + if (selectedOrder != null) guid = selectedOrder.ID; + + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", guid.ToString()); + subscriptInfo.SelectScriptParam("Action", "Edit"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + + private void DuplicateButton_Pressed(object sender, EventArgs e) + { + ReservationInstance selectedOrder = dialog.SelectedOrder; + Guid guid = Guid.Empty; + if (selectedOrder != null) guid = selectedOrder.ID; + + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", guid.ToString()); + subscriptInfo.SelectScriptParam("Action", "Duplicate"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + private void ViewButton_Pressed(object sender, EventArgs e) + { + ReservationInstance selectedOrder = dialog.SelectedOrder; + Guid guid = Guid.Empty; + if (selectedOrder != null) guid = selectedOrder.ID; + + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", guid.ToString()); + subscriptInfo.SelectScriptParam("Action", "View"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + } + + + private void AddButton_Pressed(object sender, EventArgs e) + { + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", "-1"); + subscriptInfo.SelectScriptParam("Action", "Add new"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + private void AddFromTemplateButton_Pressed(object sender, EventArgs e) + { + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", "-1"); + subscriptInfo.SelectScriptParam("Action", "From template"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + private void AddToEventButton_Pressed(object sender, EventArgs e) + { + Event selectedEvent = dialog.SelectedEvent; + Guid guid = Guid.Empty; + if (selectedEvent != null) guid = selectedEvent.Id; + + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", guid.ToString()); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", "-1"); + subscriptInfo.SelectScriptParam("Action", "Add"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + private void RefreshOrders() + { + dialog.UpdateOrders(helpers.OrderManager.GetAllFutureAndOngoingVideoReservations()); + } + + private void RefreshEvents() + { + dialog.UpdateEvents(helpers.EventManager.GetAllEvents()); + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog exceptionDialog = new ExceptionDialog(engine, exception); + exceptionDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong during the creation of the new event."); + exceptionDialog.Show(); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } +} + +public class LaunchDialog : Dialog +{ + private IEnumerable orders; + private IEnumerable events; + + public LaunchDialog(Engine engine, IEnumerable orders, IEnumerable events) + : base(engine) + { + this.orders = orders; + this.events = events; + + Title = "Customer UI Launcher"; + + OrderDropdown = new DropDown(orders.Select(x => x.Name)) { Width = 500, IsDisplayFilterShown = true }; + EventDropDown = new DropDown(events.Select(x => x.Name)) { Width = 500, IsDisplayFilterShown = true }; + AddButton = new Button("Add"); + AddFromTemplateButton = new Button("Add From Template"); + AddToEventButton = new Button("Add to Event"); + EditButton = new Button("Edit"); + DuplicateButton = new Button("Duplicate"); + ViewButton = new Button("View"); + + GenerateUI(); + } + + public void UpdateOrders(IEnumerable orders) + { + this.orders = orders; + OrderDropdown.Options = orders.Select(x => x.Name); + } + + public void UpdateEvents(IEnumerable events) + { + this.events = events; + EventDropDown.Options = events.Select(x => x.Name); + } + + public ReservationInstance SelectedOrder + { + get + { + return orders.FirstOrDefault(x => x.Name.Equals(OrderDropdown.Selected)); + } + } + + public Event SelectedEvent + { + get + { + return events.FirstOrDefault(x => x.Name.Equals(EventDropDown.Selected)); + } + } + + public DropDown EventDropDown + { + get; + private set; + } + + public DropDown OrderDropdown + { + get; + private set; + } + + public Button AddButton + { + get; + private set; + } + + public Button AddFromTemplateButton + { + get; + private set; + } + + public Button AddToEventButton + { + get; + private set; + } + + public Button EditButton + { + get; + private set; + } + + public Button DuplicateButton + { + get; + private set; + } + + public Button ViewButton + { + get; + private set; + } + + private void GenerateUI() + { + int row = -1; + AddWidget(new Label("Create new Order"), ++row, 0); + AddWidget(AddButton, row, 1); + AddWidget(AddFromTemplateButton, ++row, 1); + + AddWidget(EventDropDown, ++row, 0); + AddWidget(AddToEventButton, row, 1); + + AddWidget(OrderDropdown, ++row, 0); + AddWidget(ViewButton, row, 1); + AddWidget(EditButton, ++row, 1); + AddWidget(DuplicateButton, row + 1, 1); + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/app.config new file mode 100644 index 0000000..b8ffc0f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUI_Launcher_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUiLauncher.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUiLauncher.xml new file mode 100644 index 0000000..9774f95 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/CustomerUiLauncher.xml @@ -0,0 +1,24 @@ + + CustomerUI Launcher + Script 1.0.1.77 + Automation + SKYLINE2\ThomasRE + FALSE + YLE/Tools + + + + + + + CustomerUiScriptName + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug.xml new file mode 100644 index 0000000..efd8206 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug.xml @@ -0,0 +1,31 @@ + + + Debug + Script 1.0.1.77 + Automation + SKYLINE2\VictorSC + FALSE + YLE/Tools + + + + + + + + + + ID + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/BookingManagers/RemoveDuplicatePropertiesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/BookingManagers/RemoveDuplicatePropertiesDialog.cs new file mode 100644 index 0000000..14ff299 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/BookingManagers/RemoveDuplicatePropertiesDialog.cs @@ -0,0 +1,184 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.BookingManagers +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Automation; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + + public class RemoveDuplicatePropertiesDialog : DebugDialog + { + private readonly List bookingManagerSections = new List(); + + public RemoveDuplicatePropertiesDialog(Helpers helpers) : base(helpers) + { + Title = "Remove Duplicate Booking Manager Properties"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + var bookingManagers = Automation.Engine.SLNetRaw.GetDms().GetElements().Where(x => x.Protocol.Name.Equals("Skyline Booking Manager") && x.State == ElementState.Active).ToList(); + foreach (var bookingManager in bookingManagers) + { + bookingManagerSections.Add(new BookingManagerPropertiesSection(bookingManager)); + } + } + + private void GenerateUi() + { + Clear(); + + int row = 0; + foreach (var section in bookingManagerSections) + { + AddSection(section, new SectionLayout(++row, 0)); + row += section.RowCount; + } + + SetColumnWidth(0, 40); + } + + private class BookingManagerPropertiesSection : Section + { + private readonly IDmsElement element; + private readonly List duplicatePropertySections = new List(); + + public BookingManagerPropertiesSection(IDmsElement element) + { + this.element = element ?? throw new ArgumentNullException(nameof(element)); + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + DeleteAllDuplicatesButton.Pressed += DeleteAllDuplicatesButton_Pressed; + FindDuplicateProperties(); + } + + private void FindDuplicateProperties() + { + duplicatePropertySections.Clear(); + + IDmsTable propertiesTable = element.GetTable(4000); + + var properties = propertiesTable.GetData().Select(x => new Property { Key = Convert.ToString(x.Value[0]), Name = Convert.ToString(x.Value[1]) }).ToList(); + HashSet duplicateProperties = new HashSet(); + foreach (var property in properties) + { + if (properties.Count(x => String.Equals(x.Name, property.Name)) > 1) + { + duplicateProperties.Add(property); + } + } + + foreach (var duplicateProperty in duplicateProperties) + { + var section = new PropertySection(duplicateProperty); + section.DeleteButtonPressed += Section_DeleteButtonPressed; + duplicatePropertySections.Add(section); + } + } + + private void DeleteAllDuplicatesButton_Pressed(object sender, EventArgs e) + { + foreach (var section in duplicatePropertySections) + { + element.GetTable(4000).DeleteRow(section.Property.Key); + } + + FindDuplicateProperties(); + GenerateUi(); + } + + private void Section_DeleteButtonPressed(object sender, string rowKey) + { + element.GetTable(4000).DeleteRow(rowKey); + + FindDuplicateProperties(); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + AddWidget(new Label(element.Name) { Style = TextStyle.Bold }, ++row, 0, 1, 4); + if (!duplicatePropertySections.Any()) + { + AddWidget(new Label("This booking manager does not contain duplicate properties") { Style = TextStyle.Bold }, ++row, 1, 1, 3); + } + else + { + foreach (var duplicatePropertySection in duplicatePropertySections) + { + AddSection(duplicatePropertySection, new SectionLayout(++row, 1)); + row += duplicatePropertySection.RowCount; + } + + AddWidget(DeleteAllDuplicatesButton, ++row, 1, 1, 3); + } + } + + public Button DeleteAllDuplicatesButton { get; } = new Button("Delete All Duplicates") { Style = ButtonStyle.CallToAction }; + } + + private class Property + { + public string Name { get; set; } + + public string Key { get; set; } + + public override bool Equals(object obj) + { + Property other = obj as Property; + if (other == null) return false; + return String.Equals(Name, other.Name); + } + + public override int GetHashCode() + { + return Name.GetHashCode(); + } + } + + private class PropertySection : Section + { + private readonly Property property; + private readonly Button deleteButton = new Button("Delete"); + + public PropertySection(Property property) + { + this.property = property ?? throw new ArgumentNullException(nameof(property)); + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + deleteButton.Pressed += (s, e) => DeleteButtonPressed?.Invoke(this, property.Key); + } + + private void GenerateUi() + { + AddWidget(new Label(property.Key), 0, 0); + AddWidget(new Label(property.Name), 0, 1); + AddWidget(deleteButton, 0, 2); + } + + public Property Property => property; + + public event EventHandler DeleteButtonPressed; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ConfirmationDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ConfirmationDialog.cs new file mode 100644 index 0000000..9214938 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ConfirmationDialog.cs @@ -0,0 +1,28 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class ConfirmationDialog : Dialog + { + private readonly Label messageLabel = new Label(); + + public ConfirmationDialog(IEngine engine, string message) : base(engine) + { + messageLabel.Text = message; + + AddWidget(messageLabel, 0, 0, 1, 2); + AddWidget(YesButton, 1, 0, HorizontalAlignment.Left); + AddWidget(NoButton, 1, 1, HorizontalAlignment.Right); + } + + public Button YesButton { get; } = new Button("Yes") { Width = 80 }; + + public Button NoButton { get; } = new Button("No") { Width = 80 }; + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/DebugDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/DebugDialog.cs new file mode 100644 index 0000000..f9bd47b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/DebugDialog.cs @@ -0,0 +1,48 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug +{ + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public abstract class DebugDialog : YleDialog + { + protected readonly List responseSections = new List(); + + protected DebugDialog(Helpers helpers) : base(helpers) + { + + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + protected void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + } + + protected void AddResponseSections(int row) + { + row++; + foreach (var responseSection in responseSections) + { + if (Widgets.Contains(responseSection.Widgets.First())) continue; // skip already added sections + + responseSection.Collapse(); + + AddSection(responseSection, ++row, 0); + row += responseSection.RowCount; + } + } + + protected override void HandleEnabledUpdate() + { + foreach (var interactiveWidget in Widgets.OfType()) + { + interactiveWidget.IsEnabled = IsEnabled; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/DownloadDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/DownloadDialog.cs new file mode 100644 index 0000000..b960ea9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/DownloadDialog.cs @@ -0,0 +1,27 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript.Components; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class DownloadDialog : Dialog + { + public DownloadButton DownloadButton { get; private set; } = new DownloadButton(); + + public DownloadDialog(IEngine engine, string remoteFilePath) : base(engine) + { + DownloadButton.RemoteFilePath = remoteFilePath; + DownloadButton.DownloadedFileName = Path.GetFileName(remoteFilePath); + DownloadButton.StartDownloadImmediately = true; + + AddWidget(new Label("Download will start immediately"), 0, 0); + AddWidget(DownloadButton, 1, 0); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Functions/ActiveFunctionsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Functions/ActiveFunctionsDialog.cs new file mode 100644 index 0000000..c642d0e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Functions/ActiveFunctionsDialog.cs @@ -0,0 +1,84 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Functions +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + + public class ActiveFunctionsDialog : DebugDialog + { + private readonly Label viewActiveFunctionsLabel = new Label("Active Functions") { Style = TextStyle.Bold }; + private readonly Label duplicateFunctionsLabel = new Label("Duplicate Functions") { Style = TextStyle.Bold }; + private readonly Label functionNameLabel = new Label("Name") { Style = TextStyle.Heading }; + private readonly Label functionIdLabel = new Label("ID") { Style = TextStyle.Heading }; + private readonly List> functions = new List>(); + //private readonly List> duplicateFunctions = new List>(); + + public ActiveFunctionsDialog(Helpers helpers) : base(helpers) + { + Title = "View Active Functions"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + var activeProtocolFunctionVersions = SrmManagers.ProtocolFunctionManager.GetAllProtocolFunctions(true).Select(p => p.ProtocolFunctionVersions.FirstOrDefault()); + foreach (var activeProtocolFunctionVersion in activeProtocolFunctionVersions) + { + foreach (var functionDefinition in activeProtocolFunctionVersion.FunctionDefinitions) + { + var functionDefinitionId = functionDefinition.FunctionDefinitionID.Id; + functions.Add(new Tuple(functionDefinition.Name, functionDefinitionId, activeProtocolFunctionVersion.ProtocolName)); + } + } + + // Check for duplicates + //for (int i = 0; i < functions.Count; i++) + //{ + // var possibleDuplicates = functions.Where(x => x.Item1.Equals(functions[i].Item1)); + // if (possibleDuplicates.Count() <= 1) continue; + + // foreach (var duplicateFunction in possibleDuplicates) + // { + // if (duplicateFunctions.Any(x => x.Item1.Equals(duplicateFunction.Item1) && x.Item2.Equals(duplicateFunction.Item2))) continue; + // duplicateFunctions.Add(duplicateFunction); + // } + //} + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(viewActiveFunctionsLabel, ++row, 0, 1, 5); + + AddWidget(functionNameLabel, ++row, 0); + AddWidget(functionIdLabel, row, 1); + foreach (var kvp in functions.OrderBy(x => x.Item1)) + { + AddWidget(new Label(kvp.Item1), ++row, 0); + AddWidget(new Label(kvp.Item2.ToString()), row, 1); + AddWidget(new Label(kvp.Item3 ?? String.Empty), row, 2); + } + + //if (duplicateFunctions.Any()) + //{ + // AddWidget(new WhiteSpace(), ++row, 0); + // AddWidget(duplicateFunctionsLabel, ++row, 0, 1, 5); + // foreach (var kvp in duplicateFunctions.OrderBy(x => x.Item1)) + // { + // AddWidget(new Label(kvp.Item1), ++row, 0); + // AddWidget(new Label(kvp.Item2.ToString()), row, 1); + // } + //} + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/GetOrderReservationsSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/GetOrderReservationsSection.cs new file mode 100644 index 0000000..2b6f1a3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/GetOrderReservationsSection.cs @@ -0,0 +1,194 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + + public class GetOrderReservationsSection : Section + { + private readonly CheckBox orderIdsCheckbox = new CheckBox("Newline-separated Order IDs"); + private readonly YleTextBox orderIdTextBox = new YleTextBox { IsMultiline = true, ValidationText = "Provide newline-separated guids", ValidationPredicate = text => text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).All(guid => Guid.TryParse(guid, out var parsedGuid)) }; + private readonly Button enterCurrentIdButton = new Button("Add Current ID") { Width = 200 }; + + private readonly CheckBox orderStartCheckbox = new CheckBox("Order start"); + private readonly CheckBox orderStartFromCheckbox = new CheckBox("from"); + private readonly CheckBox orderStartUntilCheckbox = new CheckBox("until"); + private readonly DateTimePicker orderStartLowerLimitDateTimePicker = new DateTimePicker(DateTime.Now); + private readonly DateTimePicker orderStartUpperLimitDateTimePicker = new DateTimePicker(DateTime.Now.AddDays(1)); + + private readonly CheckBox orderEndCheckbox = new CheckBox("Order end"); + private readonly CheckBox orderEndFromCheckbox = new CheckBox("from"); + private readonly CheckBox orderEndUntilCheckbox = new CheckBox("until"); + private readonly DateTimePicker orderEndLowerLimitDateTimePicker = new DateTimePicker(DateTime.Now.AddDays(1)); + private readonly DateTimePicker orderEndUpperLimitDateTimePicker = new DateTimePicker(DateTime.Now.AddDays(2)); + + private readonly CheckBox limitAmountOfOrdersToCheckBox = new CheckBox("Limit amount of Orders to") { IsChecked = true }; + private readonly Numeric limitAmountOfOrdersToNumeric = new Numeric(100) { Decimals = 0, Minimum = 1 }; + + private readonly Helpers helpers; + + public GetOrderReservationsSection(Helpers helpers) + { + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public bool IsValid + { + get + { + return !orderIdsCheckbox.IsChecked || orderIdTextBox.IsValid; + } + } + + public List> AdditionalFilters { get; } = new List>(); + + public List GetOrderReservations() + { + var orderStartFilter = GetOrderStartFilter(); + + var orderEndFilter = GetOrderEndFilter(); + + var orderIdFilter = GetOrderIdFilter(); + + List> filters = new List>() + { + orderStartFilter, + orderEndFilter, + orderIdFilter + }; + + filters.AddRange(AdditionalFilters); + + var allCustomFilters = filters.Where(filter => filter != null).ToArray(); + if (!allCustomFilters.Any()) + { + return new List(); + } + + var orderTypeFilter = ReservationInstanceExposers.Properties.DictStringField("Type").Equal("Video"); + + var fullFilter = orderTypeFilter.AND(allCustomFilters); + + var orderReservations = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, fullFilter).Cast().ToList(); + + orderReservations = orderReservations.OrderBy(r => r.Start).ToList(); + + if (limitAmountOfOrdersToCheckBox.IsChecked) + { + orderReservations = orderReservations.Take((int)limitAmountOfOrdersToNumeric.Value).ToList(); + } + + return orderReservations; + } + + private FilterElement GetOrderIdFilter() + { + if (!orderIdsCheckbox.IsChecked) return null; + + List orderIds = new List(); + foreach(var line in orderIdTextBox.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) + { + if (Guid.TryParse(line.Trim(), out Guid result)) orderIds.Add(result); + } + + if (!orderIds.Any()) return null; + + FilterElement filter = null; + + foreach (var orderId in orderIds) + { + filter = filter is null ? ReservationInstanceExposers.ID.Equal(orderId) : filter.OR(ReservationInstanceExposers.ID.Equal(orderId)); + } + + return filter; + } + + + private FilterElement GetOrderStartFilter() + { + FilterElement orderStartFilter = null; + + if (!orderStartCheckbox.IsChecked) return null; + + if (orderStartFromCheckbox.IsChecked) + { + orderStartFilter = ReservationInstanceExposers.Start.GreaterThanOrEqual(orderStartLowerLimitDateTimePicker.DateTime); + } + + if (orderStartUntilCheckbox.IsChecked) + { + var orderStartUpperLimitFilter = ReservationInstanceExposers.Start.LessThanOrEqual(orderStartUpperLimitDateTimePicker.DateTime); + + orderStartFilter = orderStartFilter is null ? orderStartUpperLimitFilter : orderStartFilter.AND(orderStartUpperLimitFilter); + } + + return orderStartFilter; + } + + private FilterElement GetOrderEndFilter() + { + if (!orderEndCheckbox.IsChecked) return null; + + FilterElement orderEndFilter = null; + if (orderEndFromCheckbox.IsChecked) + { + orderEndFilter = ReservationInstanceExposers.End.GreaterThanOrEqual(orderEndLowerLimitDateTimePicker.DateTime); + } + + if (orderEndUntilCheckbox.IsChecked) + { + var orderEndUpperLimitFilter = ReservationInstanceExposers.End.LessThanOrEqual(orderEndUpperLimitDateTimePicker.DateTime); + + orderEndFilter = orderEndFilter is null ? orderEndUpperLimitFilter : orderEndFilter.AND(orderEndUpperLimitFilter); + } + + return orderEndFilter; + } + + private void Initialize() + { + enterCurrentIdButton.Pressed += (s, e) => + { + List lines = orderIdTextBox.Text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).ToList(); + lines.Add(helpers.Engine.GetScriptParam(1)?.Value); + orderIdTextBox.Text = String.Join(Environment.NewLine, lines); + orderIdsCheckbox.IsChecked = true; + }; + } + + private void GenerateUi() + { + int row = -1; + + AddWidget(orderIdsCheckbox, ++row, 0, 1, 2, verticalAlignment: VerticalAlignment.Top); + AddWidget(orderIdTextBox, row, 2, 1, 2); + AddWidget(enterCurrentIdButton, row, 4, verticalAlignment: VerticalAlignment.Top); + + AddWidget(orderStartCheckbox, ++row, 0, verticalAlignment: VerticalAlignment.Top); + AddWidget(orderStartFromCheckbox, row, 1); + AddWidget(orderStartLowerLimitDateTimePicker, row, 2); + AddWidget(orderStartUntilCheckbox, ++row, 1); + AddWidget(orderStartUpperLimitDateTimePicker, row, 2); + + AddWidget(orderEndCheckbox, ++row, 0, verticalAlignment: VerticalAlignment.Top); + AddWidget(orderEndFromCheckbox, row, 1); + AddWidget(orderEndLowerLimitDateTimePicker, row, 2); + AddWidget(orderEndUntilCheckbox, ++row, 1); + AddWidget(orderEndUpperLimitDateTimePicker, row, 2); + + AddWidget(limitAmountOfOrdersToCheckBox, ++row, 0, 1, 2); + AddWidget(limitAmountOfOrdersToNumeric, row, 2, 1, 2); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/AnalyzePlasmaRecordingsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/AnalyzePlasmaRecordingsDialog.cs new file mode 100644 index 0000000..485abe5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/AnalyzePlasmaRecordingsDialog.cs @@ -0,0 +1,255 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Integrations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Plasma; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.Utils.YLE.Integrations; + using Skyline.DataMiner.Utils.YLE.Integrations.Integrations.Plasma.Enums; + using Skyline.DataMiner.Utils.YLE.Integrations.Plasma; + + public class AnalyzePlasmaRecordingsDialog : DebugDialog + { + private readonly Label analyzePlasmaRecordingsLabel = new Label("Analyze Plasma Recordings") { Style = TextStyle.Heading }; + + private GetOrderReservationsSection getOrderReservationsSection; + + private readonly Button analyzePlasmaRecordingsButton = new Button("Analyze Plasma Recordings") { Width = 200 }; + + private readonly Label descriptionLabel = new Label("This feature analyses the Plasma orders that are part of the filter. It checks if the Plasma orders have an additional PGM recording and removes it if not applicable."); + + public AnalyzePlasmaRecordingsDialog(Helpers helpers) : base(helpers) + { + Title = "Analyze Plasma Recordings"; + + Initialize(); + GenerateUi(); + } + + public event EventHandler ShowConfirmationDialog; + + public event EventHandler ShowProgressDialog; + + public event EventHandler OrdersUpdated; + + private void Initialize() + { + getOrderReservationsSection = new GetOrderReservationsSection(helpers); + getOrderReservationsSection.AdditionalFilters.Add(ReservationInstanceExposers.Properties.DictStringField("Integration").Equal("Plasma")); + + analyzePlasmaRecordingsButton.Pressed += AnalyzePlasmaOrdersButton_Pressed; + } + + private void AnalyzePlasmaOrdersButton_Pressed(object sender, EventArgs e) + { + if (!getOrderReservationsSection.IsValid) + { + ShowRequestResult("Invalid order IDs", "Invalid Order IDs"); + } + + var plasmaReservations = getOrderReservationsSection.GetOrderReservations().OrderBy(x => x.Start).ToList(); + if (!plasmaReservations.Any()) return; + + StringBuilder sb = new StringBuilder(); + sb.AppendLine($"Are you sure you want to analyze the following {plasmaReservations.Count} Plasma order(s):"); + foreach (var plasmaReservation in plasmaReservations) sb.AppendLine($"\t-{plasmaReservation.Name} ({plasmaReservation.Start.ToLocalTime()} - {plasmaReservation.End.ToLocalTime()})"); + + ConfirmationDialog confirmationDialog = new ConfirmationDialog(helpers.Engine, sb.ToString()); + + confirmationDialog.YesButton.Pressed += (s, args) => AnalyzePlasmaOrders(plasmaReservations); + + ShowConfirmationDialog?.Invoke(this, confirmationDialog); + } + + private void AnalyzePlasmaOrders(IEnumerable plasmaReservations) + { + ProgressDialog progressDialog = new ProgressDialog(helpers.Engine) { Title = "Analyzing Plasma Recordings" }; + progressDialog.OkButton.Pressed += (sender, args) => OrdersUpdated?.Invoke(this, EventArgs.Empty); + progressDialog.Show(false); + + var succeededGuids = new List(); + var failedGuids = new List(); + + OrderManagerElement orderManagerElement = new OrderManagerElement(helpers); + PlasmaIntegration integration = new PlasmaIntegration(helpers, orderManagerElement); + foreach (var plasmaReservation in plasmaReservations) + { + try + { + progressDialog.AddProgressLine($"Retrieving order {plasmaReservation.Name}..."); + var order = helpers.OrderManager.GetOrder(plasmaReservation); + progressDialog.AddProgressLine($"Order Retrieved"); + + if (order.ShouldBeRunning) + { + progressDialog.AddProgressLine($"Plasma order is running -> skip"); + succeededGuids.Add(plasmaReservation.ID); + continue; + } + + if (String.IsNullOrEmpty(order.PlasmaId)) + { + progressDialog.AddProgressLine($"Plasma order doesn't have a Plasma ID -> unable to retrieve Plasma information"); + failedGuids.Add(plasmaReservation.ID); + continue; + } + + progressDialog.AddProgressLine($"Getting Plasma Information for {order.PlasmaId}..."); + var program = RetrieveProgram(orderManagerElement.PlasmaElement, order.PlasmaId); + progressDialog.AddProgressLine($"Plasma Information Retrieved"); + + if (program.ShouldAddPgmNewsRecording(helpers)) + { + progressDialog.AddProgressLine($"Plasma order requires a PGM recording -> nothing to do"); + succeededGuids.Add(plasmaReservation.ID); + continue; + } + + var pgmRecordingService = GetPgmRecording(order); + if (pgmRecordingService == null) + { + progressDialog.AddProgressLine($"Plasma order doesn't have a PGM recording -> nothing to do"); + succeededGuids.Add(plasmaReservation.ID); + continue; + } + + progressDialog.AddProgressLine($"Removing PGM Recording {pgmRecordingService.Name}..."); + order.RemoveChildService(pgmRecordingService.Id, true); + var result = order.AddOrUpdate(helpers, true, YLE.Order.OrderUpdates.OrderUpdateHandler.OptionFlags.None); + + if (result.UpdateWasSuccessful) + { + progressDialog.AddProgressLine($"PGM Recording removed"); + succeededGuids.Add(order.Id); + } + else + { + progressDialog.AddProgressLine($"Failed to remove PGM Recording"); + failedGuids.Add(order.Id); + } + } + catch (Exception e) + { + progressDialog.AddProgressLine($"Something went wrong when analyzing Plasma order {plasmaReservation.Name}[{plasmaReservation.ID}]: {e}"); + failedGuids.Add(plasmaReservation.ID); + } + } + + ShowRequestResult($"Updated Plasma Orders {DateTime.Now.ToShortTimeString()}", $"Succeeded Guids:\n{string.Join("\n", succeededGuids)}\n\nFailed Guids:\n{string.Join("\n", failedGuids)}"); + + progressDialog.Finish(); + ShowProgressDialog?.Invoke(this, progressDialog); + } + + /// + /// Initializes a Program object for a given Plasma ID by retrieving the data from the Plasma integration element. + /// + /// Plasma element that holds the required entry. + /// The Plasma ID for this program. + /// + public Program RetrieveProgram(IDmsElement plasmaElement, string plasmaId) + { + throw new NotSupportedException(); + /* + IDmsTable programTable = plasmaElement.GetTable(MediagenixWhatsOnProtocol.ProgramsTable.TablePid) ?? throw new Exception("Programs table could not be retrieved"); + IDmsTable transmissionTable = plasmaElement.GetTable(MediagenixWhatsOnProtocol.PublicationEventsTable.TablePid) ?? throw new Exception("Transmission table could not be retrieved"); + IDmsTable videoAssetInformationTable = plasmaElement.GetTable(MediagenixWhatsOnProtocol.VideoResourcesTable.TablePid) ?? throw new Exception("Video Assets table could not be retrieved"); + IDmsTable audioAssetInformationTable = plasmaElement.GetTable(MediagenixWhatsOnProtocol.AudioResourcesTable.TablePid) ?? throw new Exception("Audio Assets table could not be retrieved"); + IDmsTable subtitleAssetInformationTable = plasmaElement.GetTable(MediagenixWhatsOnProtocol.SubtitleResourcesTable.TablePid) ?? throw new Exception("Subtitle Assets table could not be retrieved"); + IDmsTable productionJobTable = plasmaElement.GetTable(MediagenixWhatsOnProtocol.ProductionJobsTable.TablePid) ?? throw new Exception("Production Jobs table could not be retrieved"); + + var programRow = programTable.QueryData(new[] + { + new ColumnFilter { Pid = MediagenixWhatsOnProtocol.ProgramsTable.Pid.PlasmaId, Value = plasmaId, ComparisonOperator = ComparisonOperator.Equal } + }).SingleOrDefault(); + + if (programRow is null) + { + helpers.Log(nameof(AnalyzePlasmaRecordingsDialog), nameof(RetrieveProgram), "No entry found in the Programs table for: " + plasmaId); + + // return null in case this row no longer exists + // will be treated as a delete in this case + return null; + } + + string programId = Convert.ToString(programRow[MediagenixWhatsOnProtocol.ProgramsTable.Idx.Id]); + + var publicationEventRows = transmissionTable.QueryData(new[] + { + new ColumnFilter { Pid = MediagenixWhatsOnProtocol.PublicationEventsTable.Pid.ProgramId, Value = programId, ComparisonOperator = ComparisonOperator.Equal } + }).ToList(); + + List videoAssetInformationRows = videoAssetInformationTable.QueryData(new[] + { + new ColumnFilter { Pid = MediagenixWhatsOnProtocol.VideoResourcesTable.Pid.ProgramId, Value = programId, ComparisonOperator = ComparisonOperator.Equal } + }).ToList(); + + List audioAssetInformationRows = audioAssetInformationTable.QueryData(new[] + { + new ColumnFilter { Pid = MediagenixWhatsOnProtocol.AudioResourcesTable.Pid.ProgramId, Value = programId, ComparisonOperator = ComparisonOperator.Equal } + }).ToList(); + + List subtitleAssetInformationRows = subtitleAssetInformationTable.QueryData(new[] + { + new ColumnFilter { Pid = MediagenixWhatsOnProtocol.SubtitleResourcesTable.Pid.ProgramId, Value = programId, ComparisonOperator = ComparisonOperator.Equal } + }).ToList(); + + string productionJobId = Convert.ToString(programRow[MediagenixWhatsOnProtocol.ProgramsTable.Idx.ProductionJobId]); + + var productionJobRows = productionJobTable.QueryData(new[] + { + new ColumnFilter { Pid = MediagenixWhatsOnProtocol.ProductionJobsTable.Pid.Id, Value = productionJobId, ComparisonOperator = ComparisonOperator.Equal } + }).SingleOrDefault(); + + var program = new Program(programRow, videoAssetInformationRows, audioAssetInformationRows, subtitleAssetInformationRows, publicationEventRows, productionJobRows); + + helpers.Log(nameof(AnalyzePlasmaRecordingsDialog), nameof(RetrieveProgram), $"Retrieved program from Plasma element: {program.ToString()}"); + + return program; + */ + } + + private YLE.Service.Service GetPgmRecording(YLE.Order.Order order) + { + foreach (var plasmaRecordingService in order.AllServices.Where(x => x.Definition.VirtualPlatform == ServiceDefinition.VirtualPlatform.Recording && x.IntegrationType == IntegrationType.Plasma)) + { + var recordingFunction = plasmaRecordingService.Functions.FirstOrDefault(); + var feedTypeProfileParameter = recordingFunction?.Parameters?.FirstOrDefault(p => p.Name == SrmConfiguration.FeedTypeProfileParameterName); + + if (feedTypeProfileParameter?.Value?.ToString() == NewsRecordingType.PGM.ToString()) return plasmaRecordingService; + } + + return null; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(analyzePlasmaRecordingsLabel, ++row, 0, 1, 5); + + AddWidget(descriptionLabel, ++row, 0, 1, 5); + + AddSection(getOrderReservationsSection, ++row, 0); + row += getOrderReservationsSection.RowCount; + + AddWidget(analyzePlasmaRecordingsButton, ++row, 0, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/RetriggerIntegrationUpdatesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/RetriggerIntegrationUpdatesDialog.cs new file mode 100644 index 0000000..fcc6a64 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/RetriggerIntegrationUpdatesDialog.cs @@ -0,0 +1,497 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Integrations +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Linq; + using System.Text; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.ServiceConfigurations; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.YLE.Integrations; + + public class RetriggerIntegrationUpdatesDialog : Dialog + { + private enum TypeOfId + { + [Description("Key")] Key, + [Description("ID")] Id, + [Description("Order ID")] OrderId + } + + private enum DateTimeFilterOptions + { + [Description("Less Than")] LessThan, + [Description("Less Than or Equal")] LessThanOrEqual, + [Description("Greater Than")] GreaterThan, + [Description("Greater Than or Equal")] GreaterThanOrEqual, + [Description("Within Range")] WithinRange + } + + private readonly Helpers helpers; + + private readonly YleCollapseButton basedOnIdCollapseButton = new YleCollapseButton(true); + private readonly Label basedOnIdLabel = new Label("Based on ID"){Style = TextStyle.Heading}; + + private readonly Label typeOfIdLabel = new Label("Type of ID"); + private readonly RadioButtonList typeOfIdRadioButtonList = new RadioButtonList(EnumExtensions.GetEnumDescriptions(), TypeOfId.Key.GetDescription()); + private readonly Label idLabel = new Label("Key"); + private readonly TextBox idTextBox = new TextBox(string.Empty); + private readonly Button enterCurrentOrderIdButtton = new Button("Enter Current Order ID"){Width = 200, IsVisible = false}; + + private readonly Button retriggerBasedIdButton = new Button("Retrigger Based on ID"){Width = 200}; + + private readonly YleCollapseButton basedOnFiltersCollapseButton = new YleCollapseButton(true); + private readonly Label basedOnFiltersLabel = new Label("Based on Filters") {Style = TextStyle.Heading}; + + private readonly CheckBox integrationTypesCheckBox = new CheckBox("Integration Types"); + private readonly CheckBoxList integrationTypesCheckBoxList = new CheckBoxList(EnumExtensions.GetEnumDescriptions().Except(new []{IntegrationType.None.GetDescription()})); + + private readonly CheckBox orderStartCheckBox = new CheckBox("Order Start"); + private readonly DropDown orderStartFilterDropDown = new DropDown(EnumExtensions.GetEnumDescriptions()); + private readonly DateTimePicker orderStartDateTimePicker = new DateTimePicker(DateTime.Now); + private readonly Label orderStartUntilLabel = new Label("until") { IsVisible = false }; + private readonly DateTimePicker orderStartSecondDateTimePicker = new DateTimePicker(DateTime.Now.AddHours(1)) {IsVisible = false}; + + private readonly CheckBox orderEndCheckBox = new CheckBox("Order End"); + private readonly DropDown orderEndFilterDropDown = new DropDown(EnumExtensions.GetEnumDescriptions()); + private readonly DateTimePicker orderEndDateTimePicker = new DateTimePicker(DateTime.Now.AddHours(1)); + private readonly Label orderEndUntilLabel = new Label("until"){IsVisible = false}; + private readonly DateTimePicker orderEndSecondDateTimePicker = new DateTimePicker(DateTime.Now.AddHours(2)) {IsVisible = false}; + + private readonly CheckBox orderExistsCheckBox = new CheckBox("Order Exists"); + private readonly DropDown orderExistsDropDown = new DropDown(new[] {"Yes", "No"}); + + private readonly CheckBox processedAtCheckBox = new CheckBox("Processed At"); + private readonly DropDown processedAtFilterDropDown = new DropDown(EnumExtensions.GetEnumDescriptions()); + private readonly DateTimePicker processedAtDateTimePicker = new DateTimePicker(DateTime.Now.AddHours(1)); + private readonly Label processedAtUntilLabel = new Label("until") { IsVisible = false }; + private readonly DateTimePicker processedAtSecondDateTimePicker = new DateTimePicker(DateTime.Now.AddHours(2)) {IsVisible = false}; + + private readonly Label limitAmountOfRetriggersLabel = new Label("Limit Amount of sets to"); + private readonly Numeric limitAmountOfRetriggersNumeric = new Numeric(20){Minimum = 0, StepSize = 1, Decimals = 0}; + + private readonly Button retriggerBasedOnFiltersButton = new Button("Retrigger Based on Filters") {Width = 200}; + + private readonly List resultSections = new List(); + + public RetriggerIntegrationUpdatesDialog(Helpers helpers) : base(helpers.Engine) + { + this.helpers = helpers; + + Title = "Retrigger Integration Updates"; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back..."){Width = 150}; + + private void Initialize() + { + basedOnIdCollapseButton.Pressed += BasedOnIdCollapseButton_Pressed; + BasedOnIdCollapseButton_Pressed(null, EventArgs.Empty); + + typeOfIdRadioButtonList.Changed += (sender, args) => + { + enterCurrentOrderIdButtton.IsVisible = args.SelectedValue == TypeOfId.OrderId.GetDescription(); + idLabel.Text = TypeOfId.OrderId.GetDescription(); + }; + + enterCurrentOrderIdButtton.Pressed += (sender, args) => idTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + retriggerBasedIdButton.Pressed += RetriggerBasedIdButton_Pressed; + + basedOnFiltersCollapseButton.Pressed += BasedOnFiltersCollapseButton_Pressed; + BasedOnFiltersCollapseButton_Pressed(null, EventArgs.Empty); + + orderStartFilterDropDown.Changed += (sender, args) => + { + orderStartSecondDateTimePicker.IsVisible = args.Selected == DateTimeFilterOptions.WithinRange.GetDescription(); + orderStartUntilLabel.IsVisible = orderStartSecondDateTimePicker.IsVisible; + }; + + orderEndFilterDropDown.Changed += (sender, args) => + { + orderEndSecondDateTimePicker.IsVisible = args.Selected == DateTimeFilterOptions.WithinRange.GetDescription(); + orderEndUntilLabel.IsVisible = orderEndSecondDateTimePicker.IsVisible; + }; + + processedAtFilterDropDown.Changed += (sender, args) => + { + processedAtSecondDateTimePicker.IsVisible = args.Selected == DateTimeFilterOptions.WithinRange.GetDescription(); + processedAtUntilLabel.IsVisible = processedAtSecondDateTimePicker.IsVisible; + }; + + retriggerBasedOnFiltersButton.Pressed += RetriggerBasedOnFiltersButton_Pressed; + } + + private void BasedOnIdCollapseButton_Pressed(object sender, EventArgs e) + { + var basedOnIdWidgets = new Widget[] { typeOfIdLabel, typeOfIdRadioButtonList, idLabel, idTextBox, enterCurrentOrderIdButtton, retriggerBasedIdButton }; + + foreach (var widget in basedOnIdWidgets) + { + widget.IsVisible = !basedOnIdCollapseButton.IsCollapsed; + } + + enterCurrentOrderIdButtton.IsVisible = !basedOnIdCollapseButton.IsCollapsed && typeOfIdRadioButtonList.Selected == TypeOfId.OrderId.GetDescription(); + } + + private void BasedOnFiltersCollapseButton_Pressed(object sender, EventArgs e) + { + var basedOnFiltersWidgets = new Widget[] { integrationTypesCheckBox, integrationTypesCheckBoxList, orderStartCheckBox, orderStartFilterDropDown, orderStartDateTimePicker, orderStartUntilLabel, orderStartSecondDateTimePicker, orderEndCheckBox, orderEndFilterDropDown, orderEndDateTimePicker, orderEndUntilLabel, orderEndSecondDateTimePicker, processedAtCheckBox, processedAtFilterDropDown, processedAtDateTimePicker, processedAtUntilLabel, processedAtSecondDateTimePicker, orderExistsCheckBox, orderExistsDropDown, retriggerBasedOnFiltersButton, limitAmountOfRetriggersLabel, limitAmountOfRetriggersNumeric }; + + foreach (var widget in basedOnFiltersWidgets) + { + widget.IsVisible = !basedOnFiltersCollapseButton.IsCollapsed; + } + + orderStartSecondDateTimePicker.IsVisible = !basedOnFiltersCollapseButton.IsCollapsed && orderStartFilterDropDown.Selected == DateTimeFilterOptions.WithinRange.GetDescription(); + orderStartUntilLabel.IsVisible = orderStartSecondDateTimePicker.IsVisible; + + orderEndSecondDateTimePicker.IsVisible = !basedOnFiltersCollapseButton.IsCollapsed && orderEndFilterDropDown.Selected == DateTimeFilterOptions.WithinRange.GetDescription(); + orderEndUntilLabel.IsVisible = orderEndSecondDateTimePicker.IsVisible; + + processedAtSecondDateTimePicker.IsVisible = !basedOnFiltersCollapseButton.IsCollapsed && processedAtFilterDropDown.Selected == DateTimeFilterOptions.WithinRange.GetDescription(); + processedAtUntilLabel.IsVisible = processedAtSecondDateTimePicker.IsVisible; + } + + private void RetriggerBasedIdButton_Pressed(object sender, EventArgs e) + { + var table = GetIntegrationUpdatesTable(); + + Func predicate = row => false; + + switch (typeOfIdRadioButtonList.Selected.GetEnumValue()) + { + case TypeOfId.Key: + predicate = row => row.Key == idTextBox.Text; + break; + case TypeOfId.Id: + predicate = row => row.ID == idTextBox.Text; + break; + case TypeOfId.OrderId: + predicate = row => row.OrderId == idTextBox.Text; + break; + default: + // no predicate change required + break; + } + + var keysToRetrigger = table.Values.Where(predicate).Select(row => row.Key).ToArray(); + + helpers.OrderManagerElement.ReprocessIntegrationOrders(keysToRetrigger); + + ShowResult($"Retriggered Integration Updates {DateTime.Now}", $"ID = '{idTextBox.Text}'\nRetriggered Integrations:\n{(keysToRetrigger.Any() ? string.Join("\n", keysToRetrigger) : "None")}"); + } + + private void RetriggerBasedOnFiltersButton_Pressed(object sender, EventArgs e) + { + var table = GetIntegrationUpdatesTable(); + + var keysToRetrigger = new List(); + + foreach (var row in table.Values) + { + bool retriggerThisRow = true; + + if (integrationTypesCheckBox.IsChecked) + { + retriggerThisRow &= integrationTypesCheckBoxList.Checked.Contains(row.Integration.GetDescription()); + } + + retriggerThisRow = CheckOrderStartCheckBox(row, retriggerThisRow); + retriggerThisRow = CheckOrderEndCheckBox(row, retriggerThisRow); + + if (orderExistsCheckBox.IsChecked) + { + bool validGuid = Guid.TryParse(row.OrderId, out var guid); + retriggerThisRow &= (validGuid && orderExistsDropDown.Selected.Equals("yes", StringComparison.InvariantCultureIgnoreCase)) || (!validGuid && orderExistsDropDown.Selected.Equals("no", StringComparison.InvariantCultureIgnoreCase)); + } + + retriggerThisRow = CheckProcessedAtTime(row, retriggerThisRow); + + if (retriggerThisRow) + { + keysToRetrigger.Add(row.Key); + } + } + + int totalMatchingRows = keysToRetrigger.Count; + + keysToRetrigger = keysToRetrigger.Take((int) limitAmountOfRetriggersNumeric.Value).ToList(); + + helpers.OrderManagerElement.ReprocessIntegrationOrders(keysToRetrigger.ToArray()); + + ShowResult($"Retriggered Integration Updates {DateTime.Now}", $"Filters:\n{FiltersToString()}\nRetriggered Integrations (limited to {(int)limitAmountOfRetriggersNumeric.Value}/{totalMatchingRows}):\n{(keysToRetrigger.Any() ? string.Join("\n", keysToRetrigger) : "None")}"); + } + + private bool CheckOrderStartCheckBox(IntegrationUpdateRow row, bool retriggerThisRow) + { + if (!orderStartCheckBox.IsChecked) return retriggerThisRow; + + switch (orderStartFilterDropDown.Selected.GetEnumValue()) + { + case DateTimeFilterOptions.GreaterThan: + retriggerThisRow &= row.Start > orderStartDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.GreaterThanOrEqual: + retriggerThisRow &= row.Start >= orderStartDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.LessThan: + retriggerThisRow &= row.Start < orderStartDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.LessThanOrEqual: + retriggerThisRow &= row.Start <= orderStartDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.WithinRange: + retriggerThisRow &= orderStartDateTimePicker.DateTime <= row.Start && row.Start <= orderStartSecondDateTimePicker.DateTime; + break; + default: + // nothing to check + break; + } + + return retriggerThisRow; + } + + private bool CheckOrderEndCheckBox(IntegrationUpdateRow row, bool retriggerThisRow) + { + if (!orderEndCheckBox.IsChecked) return retriggerThisRow; + + switch (orderEndFilterDropDown.Selected.GetEnumValue()) + { + case DateTimeFilterOptions.GreaterThan: + retriggerThisRow &= row.End > orderEndDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.GreaterThanOrEqual: + retriggerThisRow &= row.End >= orderEndDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.LessThan: + retriggerThisRow &= row.End < orderEndDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.LessThanOrEqual: + retriggerThisRow &= row.End <= orderEndDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.WithinRange: + retriggerThisRow &= orderEndDateTimePicker.DateTime <= row.End && row.End <= orderEndSecondDateTimePicker.DateTime; + break; + default: + // nothing to check + break; + } + + return retriggerThisRow; + } + + private bool CheckProcessedAtTime(IntegrationUpdateRow row, bool retriggerThisRow) + { + if (!processedAtCheckBox.IsChecked) return retriggerThisRow; + + if (row.ProcessedAt.HasValue) + { + switch (processedAtFilterDropDown.Selected.GetEnumValue()) + { + case DateTimeFilterOptions.GreaterThan: + retriggerThisRow &= row.ProcessedAt > processedAtDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.GreaterThanOrEqual: + retriggerThisRow &= row.ProcessedAt >= processedAtDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.LessThan: + retriggerThisRow &= row.ProcessedAt < processedAtDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.LessThanOrEqual: + retriggerThisRow &= row.ProcessedAt <= processedAtDateTimePicker.DateTime; + break; + case DateTimeFilterOptions.WithinRange: + retriggerThisRow &= processedAtDateTimePicker.DateTime <= row.ProcessedAt && row.ProcessedAt <= processedAtSecondDateTimePicker.DateTime; + break; + default: + // nothing to check + break; + } + } + else + { + retriggerThisRow = false; + } + + return retriggerThisRow; + } + + private string FiltersToString() + { + var sb = new StringBuilder(); + + if (integrationTypesCheckBox.IsChecked) + { + sb.Append($"Integrations = {string.Join(",", integrationTypesCheckBoxList.Checked)}\n"); + } + + if (orderStartCheckBox.IsChecked) + { + sb.Append($"Order Start {orderStartFilterDropDown.Selected} {orderStartDateTimePicker.DateTime}"); + if (orderStartFilterDropDown.Selected == DateTimeFilterOptions.WithinRange.GetDescription()) + { + sb.Append($" until {orderStartSecondDateTimePicker.DateTime}"); + } + + sb.Append("\n"); + } + + if (orderEndCheckBox.IsChecked) + { + sb.Append($"Order End {orderEndFilterDropDown.Selected} {orderEndDateTimePicker.DateTime}"); + if (orderEndFilterDropDown.Selected == DateTimeFilterOptions.WithinRange.GetDescription()) + { + sb.Append($" until {orderEndSecondDateTimePicker.DateTime}"); + } + + sb.Append("\n"); + } + + if (orderExistsCheckBox.IsChecked) + { + sb.Append($"Order Exists = {orderExistsDropDown.Selected}\n"); + } + + if (processedAtCheckBox.IsChecked) + { + sb.Append($"Processed At {processedAtFilterDropDown.Selected} {processedAtDateTimePicker.DateTime}"); + if (processedAtFilterDropDown.Selected == DateTimeFilterOptions.WithinRange.GetDescription()) + { + sb.Append($" until {processedAtSecondDateTimePicker.DateTime}"); + } + + sb.Append("\n"); + } + + return sb.ToString(); + } + + private void ShowResult(string header, params string[] results) + { + resultSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 5); + + AddWidget(basedOnIdCollapseButton, ++row, 0); + AddWidget(basedOnIdLabel, row, 1, 1, 5); + + AddWidget(typeOfIdLabel, ++row, 0); + AddWidget(typeOfIdRadioButtonList, row, 1, 1, 4); + + AddWidget(idLabel, ++row, 0); + AddWidget(idTextBox, row, 1, 1, 3); + AddWidget(enterCurrentOrderIdButtton, row, 4); + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(retriggerBasedIdButton, ++row, 0, 1, 5); + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(basedOnFiltersCollapseButton, ++row, 0); + AddWidget(basedOnFiltersLabel, row, 1, 1, 5); + + AddWidget(integrationTypesCheckBox, ++row, 0); + AddWidget(integrationTypesCheckBoxList, row, 1, 1, 3); + + AddWidget(orderStartCheckBox, ++row, 0); + AddWidget(orderStartFilterDropDown, row, 1); + AddWidget(orderStartDateTimePicker, row, 2); + AddWidget(orderStartUntilLabel, row, 3); + AddWidget(orderStartSecondDateTimePicker, row, 4); + + AddWidget(orderEndCheckBox, ++row, 0); + AddWidget(orderEndFilterDropDown, row, 1); + AddWidget(orderEndDateTimePicker, row, 2); + AddWidget(orderEndUntilLabel, row, 3); + AddWidget(orderEndSecondDateTimePicker, row, 4); + + AddWidget(orderExistsCheckBox, ++row, 0); + AddWidget(orderExistsDropDown, row, 1, 1, 3); + + AddWidget(processedAtCheckBox, ++row, 0); + AddWidget(processedAtFilterDropDown, row, 1); + AddWidget(processedAtDateTimePicker, row, 2); + AddWidget(processedAtUntilLabel, row, 3); + AddWidget(processedAtSecondDateTimePicker, row, 4); + + AddWidget(limitAmountOfRetriggersLabel, ++row, 0); + AddWidget(limitAmountOfRetriggersNumeric, row, 1, 1, 4); + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(retriggerBasedOnFiltersButton, ++row, 0, 1, 5); + AddWidget(new WhiteSpace(), ++row, 0); + + foreach (var resultSection in resultSections) + { + AddSection(resultSection, ++row, 0); + row += resultSection.RowCount; + } + } + + private Dictionary GetIntegrationUpdatesTable() + { + helpers.LogMethodStart(nameof(RetriggerIntegrationUpdatesDialog), nameof(GetIntegrationUpdatesTable), out var stopwatch); + + var objectTable = helpers.OrderManagerElement.GetIntegrationOrdersTable(); + + var table = new Dictionary(); + + foreach (var pair in objectTable) + { + table.Add(pair.Key, new IntegrationUpdateRow(pair.Value)); + } + + helpers.Log(nameof(RetriggerIntegrationUpdatesDialog), nameof(GetIntegrationUpdatesTable), $"Found {table.Count} rows"); + + helpers.LogMethodCompleted(nameof(RetriggerIntegrationUpdatesDialog), nameof(GetIntegrationUpdatesTable),null, stopwatch); + + return table; + } + + private sealed class IntegrationUpdateRow + { + public IntegrationUpdateRow(object[] row) + { + if (row == null) throw new ArgumentNullException(nameof(row)); + + Key = Convert.ToString(row[0]); + ID = Convert.ToString(row[1]); + Integration = (IntegrationType)Convert.ToInt32(row[2]); + Start = DateTime.FromOADate(Convert.ToDouble(row[4])); + End = DateTime.FromOADate(Convert.ToDouble(row[5])); + OrderId = Convert.ToString(row[8]); + + var processedAtValue = Convert.ToDouble(row[10]); + ProcessedAt = processedAtValue > 0 ? DateTime.FromOADate(processedAtValue) : (DateTime?) null; + } + + public string Key { get; set; } + + public string ID { get; set; } + + public IntegrationType Integration { get; set; } + + public DateTime Start { get; set; } + + public DateTime End { get; set; } + + public string OrderId { get; set; } + + public DateTime? ProcessedAt { get; set; } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendCeitonIntegrationNotificationDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendCeitonIntegrationNotificationDialog.cs new file mode 100644 index 0000000..b2a942b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendCeitonIntegrationNotificationDialog.cs @@ -0,0 +1,539 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.Utils.YLE.Integrations.Ceiton; + + public class SendCeitonIntegrationNotificationDialog : DebugDialog + { + private readonly Label ceitonLabel = new Label("Ceiton") { Style = TextStyle.Heading }; + + private readonly Button addAdHocTaskButton = new Button("Add Ad Hoc Task") { Width = 200 }; + private readonly Button sendNotificationButton = new Button("Send Notification") { Width = 200 }; + private readonly Button deleteProjectInfoButton = new Button("Delete Project Info") { Width = 200 }; + private readonly CheckBox provideProductInfoCheckBox = new CheckBox("Provide Product Info?") { IsChecked = false }; + + private readonly ProjectSection projectSection = new ProjectSection(); + private readonly List adHocTaskSections = new List(); + + private ProductSection productSection = null; + + public SendCeitonIntegrationNotificationDialog(Utilities.Helpers helpers) : base(helpers) + { + Title = "Send Ceiton Integration Notification"; + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + projectSection.TriggerUiGeneration += (s, e) => GenerateUi(); + provideProductInfoCheckBox.Changed += (s, e) => + { + if (e.IsChecked) + { + productSection = new ProductSection(projectSection); + productSection.TriggerUiGeneration += (sec, args) => GenerateUi(); + } + else + { + productSection = null; + } + + GenerateUi(); + }; + + addAdHocTaskButton.Pressed += (s, e) => + { + var section = new CeitonTaskSection(); + section.DeleteTaskButton.Pressed += (sec, args) => + { + adHocTaskSections.Remove(section); + GenerateUi(); + }; + + section.TriggerUiGeneration += (sec, args) => GenerateUi(); + adHocTaskSections.Add(section); + + GenerateUi(); + }; + + sendNotificationButton.Pressed += (s, e) => SendNotification(); + deleteProjectInfoButton.Pressed += (s, e) => DeleteProject(); + } + + private void SendNotification() + { + string ceitonId = Guid.NewGuid().ToString(); + + List data = new List(); + foreach (var projectData in projectSection.Data) + { + projectData.ProjectCeitonId = ceitonId; + data.Add(projectData); + } + + if (productSection != null) + { + foreach (var productData in productSection.Data) + { + productData.ProductCeitonId = ceitonId; + data.Add(productData); + } + } + + foreach (var adHocData in adHocTaskSections.SelectMany(x => x.Data)) + { + data.Add(adHocData); + } + + OrderManagerElement orderManager = new OrderManagerElement(helpers); + CeitonElement ceitonElement = new CeitonElement(orderManager.CeitonElement); + + Export export = new Export + { + SystemId = ceitonId, + TimeStamp = DateTime.Now.Ticks, + TaskData = data + }; + + ceitonElement.SendNotification(export); + + ShowRequestResult($"Notification {export.SystemId} sent", JsonConvert.SerializeObject(export)); + GenerateUi(); + } + + private void DeleteProject() + { + if (!projectSection.NumberTextBox.IsValid) return; + + OrderManagerElement orderManagerElement = new OrderManagerElement(helpers); + if (orderManagerElement.CeitonElement == null || orderManagerElement.CeitonElement.State != ElementState.Active) + { + ShowRequestResult($"Unable to remove Ceiton Project {projectSection.NumberTextBox.Text}", "Ceiton element was not linked with order manager or not active"); + return; + } + + // Remove entry from Ceiton element + var liveStreamOrdersTable = orderManagerElement.CeitonElement.GetTable(1000); + if (liveStreamOrdersTable.RowExists(projectSection.NumberTextBox.Text)) + { + liveStreamOrdersTable.DeleteRow(projectSection.NumberTextBox.Text); + } + + // Trigger integration update + orderManagerElement.Element.SetParameter(110, projectSection.NumberTextBox.Text); + + ShowRequestResult($"Removed Ceiton project {projectSection.NumberTextBox.Text}", "Removed"); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(ceitonLabel, ++row, 0); + + AddWidget(new Label("Project Information") { Style = TextStyle.Heading }, ++row, 0, 1, 2); + AddSection(projectSection, new SectionLayout(++row, 0)); + row += projectSection.RowCount; + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(new Label("Product Information") { Style = TextStyle.Heading }, ++row, 0, 1, 2); + AddWidget(provideProductInfoCheckBox, row, 2); + + if (productSection != null) + { + AddSection(productSection, new SectionLayout(++row, 0)); + row += productSection.RowCount; + } + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(new Label("Ad Hoc Tasks") { Style = TextStyle.Heading }, ++row, 0, 1, 2); + foreach (var section in adHocTaskSections) + { + AddWidget(new Label("Ad Hoc Task") { Style = TextStyle.Heading }, ++row, 0, 1, 2); + AddSection(section, new SectionLayout(++row, 0)); + row += section.RowCount; + AddWidget(new WhiteSpace(), ++row, 0); + } + + AddWidget(addAdHocTaskButton, ++row, 0); + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(sendNotificationButton, ++row, 0); + AddWidget(deleteProjectInfoButton, ++row, 0); + + AddResponseSections(row + 1); + } + + private interface ICeitonSection + { + Data[] Data { get; } + + event EventHandler TriggerUiGeneration; + } + + private class ProjectSection : Section, ICeitonSection + { + private static readonly string[] contentClassCaptionOptions = new string[] + { + "Ajankohtainen", + "Asia", + "Draama", + "Hartaus", + "Musiikki", + "Lapset", + "Opetus ja tiede", + "Urheilu", + "Uutiset", + "Viihde" + }; + + private readonly Button addTaskButton = new Button("Add Project Task"); + private readonly Button randomProjectNumberButton = new Button("Enter Random Guid") { Width = 150 }; + private readonly List projectTaskSections = new List(); + + public ProjectSection() + { + Initialize(); + GenerateUi(); + } + + public YleTextBox NumberTextBox { get; } = new YleTextBox(Guid.NewGuid().ToString()); + + public TextBox NameTextBox { get; } = new TextBox(); + + public TextBox CeitonIdTextBox { get; } = new TextBox(); + + public TextBox DescriptionTextBox { get; } = new TextBox(); + + public TextBox ContentOwnerTextBox { get; } = new TextBox(); + + public DropDown ContentClassCaptionDropDown { get; } = new DropDown(contentClassCaptionOptions, contentClassCaptionOptions[0]); + + public Data[] Data + { + get + { + List data = new List() + { + new Data + { + ProjectNumber = NumberTextBox.Text, + ProjectName = NameTextBox.Text, + ProjectDescription = DescriptionTextBox.Text, + ProjectContentOwnerName = ContentOwnerTextBox.Text, + ProjectContentClassCaption = ContentClassCaptionDropDown.Selected, + } + }; + + foreach (var task in projectTaskSections.SelectMany(x => x.Data)) + { + task.ProjectCeitonId = CeitonIdTextBox.Text; + task.ProjectNumber = NumberTextBox.Text; + task.ProjectName = NameTextBox.Text; + + data.Add(task); + } + + return data.ToArray(); + } + } + + public event EventHandler TriggerUiGeneration; + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(new Label("Project Number"), ++row, 0); + AddWidget(NumberTextBox, row, 1, 1, 2); + AddWidget(randomProjectNumberButton, row, 3); + + AddWidget(new Label("Project Name"), ++row, 0); + AddWidget(NameTextBox, row, 1, 1, 2); + + AddWidget(new Label("Description"), ++row, 0); + AddWidget(DescriptionTextBox, row, 1, 1, 2); + + AddWidget(new Label("Content Owner"), ++row, 0); + AddWidget(ContentOwnerTextBox, row, 1, 1, 2); + + AddWidget(new Label("Class Caption"), ++row, 0); + AddWidget(ContentClassCaptionDropDown, row, 1, 1, 2); + + foreach (var section in projectTaskSections) + { + AddWidget(new Label("Project Task") { Style = TextStyle.Heading }, ++row, 1, 1, 2); + AddSection(section, new SectionLayout(++row, 1)); + AddWidget(new WhiteSpace(), ++row, 0); + row += section.RowCount; + } + + AddWidget(addTaskButton, row + 1, 0); + } + + private void Initialize() + { + randomProjectNumberButton.Pressed += (s, e) => NumberTextBox.Text = Guid.NewGuid().ToString(); + + addTaskButton.Pressed += (s, e) => + { + CeitonTaskSection section = new CeitonTaskSection(); + section.DeleteTaskButton.Pressed += (sec, args) => + { + projectTaskSections.Remove(section); + GenerateUi(); + TriggerUiGeneration?.Invoke(this, EventArgs.Empty); + }; + + section.TriggerUiGeneration += (sec, args) => TriggerUiGeneration?.Invoke(sec, args); + projectTaskSections.Add(section); + GenerateUi(); + + TriggerUiGeneration?.Invoke(this, EventArgs.Empty); + }; + } + } + + private class ProductSection : Section, ICeitonSection + { + private readonly Button addTaskButton = new Button("Add Product Task"); + private readonly Button randomProductNumberButton = new Button("Enter Random Guid") { Width = 150 }; + private readonly List productTaskSections = new List(); + private readonly ProjectSection projectSection; + + public ProductSection(ProjectSection projectSection) + { + this.projectSection = projectSection; + + Initialize(); + GenerateUi(); + } + + public TextBox NumberTextBox { get; } = new TextBox(Guid.NewGuid().ToString()); + + public TextBox NameTextBox { get; } = new TextBox(); + + public TextBox DescriptionTextBox { get; } = new TextBox(); + + public Data[] Data + { + get + { + List data = new List() + { + new Data + { + ProductNumber = NumberTextBox.Text, + ProductName = NameTextBox.Text, + ProductDescription = DescriptionTextBox.Text, + ProjectNumber = projectSection.NumberTextBox.Text, + } + }; + + foreach (var task in productTaskSections.SelectMany(x => x.Data)) + { + task.ProductNumber = NumberTextBox.Text; + task.ProductName = NameTextBox.Text; + + data.Add(task); + } + + return data.ToArray(); + } + } + + public event EventHandler TriggerUiGeneration; + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(new Label("Product Number"), ++row, 0); + AddWidget(NumberTextBox, row, 1, 1, 2); + AddWidget(randomProductNumberButton, row, 3); + + AddWidget(new Label("Product Name"), ++row, 0); + AddWidget(NameTextBox, row, 1, 1, 2); + + AddWidget(new Label("Description"), ++row, 0); + AddWidget(DescriptionTextBox, row, 1, 1, 2); + + foreach (var section in productTaskSections) + { + AddWidget(new Label("Product Task") { Style = TextStyle.Heading }, ++row, 1, 1, 2); + AddSection(section, new SectionLayout(++row, 1)); + AddWidget(new WhiteSpace(), ++row, 0); + row += section.RowCount; + } + + AddWidget(addTaskButton, row + 1, 0); + } + + private void Initialize() + { + randomProductNumberButton.Pressed += (s, e) => NumberTextBox.Text = Guid.NewGuid().ToString(); + + addTaskButton.Pressed += (s, e) => + { + CeitonTaskSection section = new CeitonTaskSection(); + section.DeleteTaskButton.Pressed += (sec, args) => + { + productTaskSections.Remove(section); + GenerateUi(); + TriggerUiGeneration?.Invoke(this, EventArgs.Empty); + }; + + section.TriggerUiGeneration += (sec, args) => TriggerUiGeneration?.Invoke(sec, args); + productTaskSections.Add(section); + GenerateUi(); + + TriggerUiGeneration?.Invoke(this, EventArgs.Empty); + }; + } + } + + private class CeitonTaskSection : Section, ICeitonSection + { + private readonly Button randomIdButton = new Button("Enter Random Guid") { Width = 150 }; + + public CeitonTaskSection() + { + Initialize(); + GenerateUi(); + } + + public TextBox IdTextBox = new TextBox(Guid.NewGuid().ToString()); + + public DropDown StateDropDown { get; } = new DropDown(Enum.GetNames(typeof(TaskStates)), Enum.GetName(typeof(TaskStates), TaskStates.Confirmed)); + + public CheckBox IsCanceledCheckBox { get; } = new CheckBox("Canceled?"); + + public TextBox CommentTextBox { get; } = new TextBox(); + + public YleDateTimePicker DatePicker { get; } = new YleDateTimePicker { DateTimeFormat = Automation.DateTimeFormat.LongDate }; + + public TimePicker StartTimePicker { get; } = new TimePicker(); + + public TimePicker EndTimePicker { get; } = new TimePicker(); + + public TextBox ActivityTypeTextBox { get; } = new TextBox(); + + public TextBox ActivityNameTextBox { get; } = new TextBox(); + + public TextBox ResourceIdTextBox { get; } = new TextBox(); + + public TextBox ResourceNameTextBox { get; } = new TextBox(); + + public CheckBox IsFlexibleCheckBox { get; } = new CheckBox("Flexible?"); + + public Button DeleteTaskButton { get; } = new Button("Delete Task"); + + public Data[] Data { + get + { + return new Data[] + { + new Data() + { + TaskId = IdTextBox.Text, + TaskStatus = (int)Enum.Parse(typeof(TaskStates), StateDropDown.Selected), + TaskIsCanceled = IsCanceledCheckBox.IsChecked.ToString(), + TaskComment = CommentTextBox.Text, + TaskIsFlexible = IsFlexibleCheckBox.IsChecked.ToString(), + StartTime = StartTimePicker.Time.ToString(@"hh\:mm"), + EndTime = EndTimePicker.Time.ToString(@"hh\:mm"), + Date = DatePicker.DateTime.ToString("dd.MM.yyyy"), + DurationAsString = Math.Abs(Math.Round(EndTimePicker.Time.Subtract(StartTimePicker.Time).TotalMinutes)).ToString(), + ActivityTypeId = ActivityTypeTextBox.Text, + ActivityTypeName = ActivityNameTextBox.Text, + ResourceId = ResourceIdTextBox.Text, + ResourceName = ResourceNameTextBox.Text, + } + }; + } + } + + public event EventHandler TriggerUiGeneration; + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(new Label("Task ID"), ++row, 0); + AddWidget(IdTextBox, row, 1); + AddWidget(randomIdButton, row, 2); + + AddWidget(new Label("Task Status"), ++row, 0); + AddWidget(StateDropDown, row, 1); + + AddWidget(new Label("Is Canceled"), ++row, 0); + AddWidget(IsCanceledCheckBox, row, 1); + + AddWidget(new Label("Comments"), ++row, 0); + AddWidget(CommentTextBox, row, 1); + + AddWidget(new Label("Is Flexible"), ++row, 0); + AddWidget(IsFlexibleCheckBox, row, 1); + + AddWidget(new Label("Start Time"), ++row, 0); + AddWidget(StartTimePicker, row, 1); + + AddWidget(new Label("End Time"), ++row, 0); + AddWidget(EndTimePicker, row, 1); + + AddWidget(new Label("Date"), ++row, 0); + AddWidget(DatePicker, row, 1); + + AddWidget(new Label("Activity Type"), ++row, 0); + AddWidget(ActivityTypeTextBox, row, 1); + + AddWidget(new Label("Activity Name"), ++row, 0); + AddWidget(ActivityNameTextBox, row, 1); + + AddWidget(new Label("Resource ID"), ++row, 0); + AddWidget(ResourceIdTextBox, row, 1); + + AddWidget(new Label("Resource Name"), ++row, 0); + AddWidget(ResourceNameTextBox, row, 1); + + AddWidget(DeleteTaskButton, row + 1, 0, 1, 2); + } + + private void Initialize() + { + randomIdButton.Pressed += (s, e) => IdTextBox.Text = Guid.NewGuid().ToString(); + } + } + + private enum TaskStates + { + Deleted = 0, + Unactivated = 1, + PrePlanned = 2, + Planned = 3, + Confirmed = 4, + Completed = 5, + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendEurovisionIntegrationNotificationDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendEurovisionIntegrationNotificationDialog.cs new file mode 100644 index 0000000..cdf97cf --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendEurovisionIntegrationNotificationDialog.cs @@ -0,0 +1,86 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations +{ + using System; + using Newtonsoft.Json; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.Utils.YLE.Integrations; + using Skyline.DataMiner.Utils.YLE.Integrations.Eurovision; + + public class SendEurovisionIntegrationNotificationDialog : DebugDialog + { + private readonly Label eurovisionLabel = new Label("Eurovision") { Style = TextStyle.Heading }; + private readonly Label infoLabel = new Label("Clicking 'Send Notification' will immediately trigger the HIU script without passing the data to the Order Manager"); + + private readonly Label transmissionNumberLabel = new Label("Transmission Number"); + private readonly TextBox transmissionNumberTextBox = new TextBox(); + private readonly Label synopsisXmlLabel = new Label("Synopsis XML"); + private readonly TextBox synopsisXmlTextBox = new TextBox { IsMultiline = true, Height = 400 }; + private readonly Button sendNotificationButton = new Button("Send Notification"); + + public SendEurovisionIntegrationNotificationDialog(Utilities.Helpers helpers) : base(helpers) + { + Title = "Send Eurovision Integration Notification"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + sendNotificationButton.Pressed += (s, e) => SendNotification(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(eurovisionLabel, ++row, 0, 1, 3); + + AddWidget(infoLabel, ++row, 0, 1, 2); + + AddWidget(transmissionNumberLabel, ++row, 0, verticalAlignment: VerticalAlignment.Top); + AddWidget(transmissionNumberTextBox, row, 1); + + AddWidget(synopsisXmlLabel, ++row, 0, verticalAlignment: VerticalAlignment.Top); + AddWidget(synopsisXmlTextBox, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(sendNotificationButton, ++row, 0, 1, 2); + + AddResponseSections(++row); + } + + private string TransmissionNumber => transmissionNumberTextBox.Text; + + private string SynopsisXml => synopsisXmlTextBox.Text; + + private void SendNotification() + { + try + { + var parsedSynopsis = synopsis.Deserialize(SynopsisXml) ?? throw new InvalidOperationException("Unable to parse synopis"); + IntegrationRequest request = new IntegrationRequest(IntegrationType.Eurovision, TransmissionNumber, parsedSynopsis.Serialize()); + + string serializedRequest = JsonConvert.SerializeObject(request); + + var scriptOptions = helpers.Engine.PrepareSubScript("HandleIntegrationUpdate"); + scriptOptions.Synchronous = true; + scriptOptions.SelectScriptParam("update", serializedRequest); + scriptOptions.StartScript(); + + ShowRequestResult(TransmissionNumber, serializedRequest); + } + catch (Exception e) + { + ShowRequestResult($"{TransmissionNumber} [{DateTime.Now}]", $"Failed to send notification: {e}"); + GenerateUi(); + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendEvsNotificationDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendEvsNotificationDialog.cs new file mode 100644 index 0000000..177b80d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendEvsNotificationDialog.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Skyline.DataMiner.ConnectorAPI.EVS.IPD_VIA.Model; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.EVS; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; +using Skyline.DataMiner.Utils.InteractiveAutomationScript; +using Label = Skyline.DataMiner.Utils.InteractiveAutomationScript.Label; + +namespace Debug_2.Debug.Integrations +{ + public class SendEvsNotificationDialog : Dialog + { + private readonly EvsManager evsManager; + + private readonly Label evsLabel = new Label("EVS") { Style = TextStyle.Heading }; + + private readonly Label idLabel = new Label("ID"); + private readonly YleTextBox idTextBox = new YleTextBox { ValidationText = "Required field", ValidationPredicate = text => !String.IsNullOrWhiteSpace(text), Text = Guid.NewGuid().ToString() }; + private readonly Button randomIdButton = new Button("Enter Random Guid") { Width = 150 }; + + private readonly Label nameLabel = new Label("Name"); + private readonly TextBox nameTextBox = new TextBox(); + + private readonly Label startLabel = new Label("Start"); + private readonly DateTimePicker startDateTimePicker = new DateTimePicker(DateTime.Now.AddDays(1)); + + private readonly Label endLabel = new Label("End"); + private readonly DateTimePicker endDateTimePicker = new DateTimePicker(DateTime.Now.AddDays(1).AddHours(1)); + + private readonly Label recorderRefLabel = new Label("Recorder Reference"); + private readonly TextBox recorderRefTextBox = new TextBox { Text = "XS-TEST IN-1" }; + + private readonly Label targetRefLabel = new Label("Target Reference"); + private readonly TextBox targetRefTextbox = new TextBox { Text = "Ingest to Nearline" }; + + private readonly Button metadataTemplateButton = new Button("Use Metadata Template"); + + private readonly ListSection metaDataProfileFqnSection = new ListSection("Metadata Profile Fqns"); + private readonly DictionarySection valuesSection = new DictionarySection("Values") { Value = new Dictionary + { + { "yle-id", "987654" }, + { "subtitle-proxy", "False" }, + { "plasma-id", "132456" }, + { "order-name", "Order Name" }, + { "fast-rerun-copy", "False" }, + { "areena-copy", "True" }, + { "additional-information", "Some random info" }, + }}; + + private readonly ListSection contextSection = new ListSection("Contexts"); + + private readonly Button sendNotificationButton = new Button("Send Notification") { Width = 200 }; + + private readonly List responseSections = new List(); + + public SendEvsNotificationDialog(Helpers helpers) : base(helpers.Engine) + { + this.evsManager = new EvsManager(helpers); + + Title = "EVS"; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private void Initialize() + { + metaDataProfileFqnSection.SetValue(new List { "yle-nameandid" }); + + randomIdButton.Pressed += (s, e) => idTextBox.Text = Guid.NewGuid().ToString(); + + metadataTemplateButton.Pressed += MetadataTemplateButton_Pressed; + metaDataProfileFqnSection.RegenerateUi += (s, e) => GenerateUi(); + valuesSection.RegenerateUi += (s, e) => GenerateUi(); + contextSection.RegenerateUi += (s, e) => GenerateUi(); + + sendNotificationButton.Pressed += SendNotificationButton_Pressed; + } + + private void MetadataTemplateButton_Pressed(object sender, EventArgs e) + { + string defaultMetaDataProfileFqn = "ylebasicprogrammemetadata"; + + var defaultMetaDataProfileFieldNames = new List + { + "finnish-main-title", + "plasma-id", + "yle-id", + "audio-tracks-1-2", + "content-1-2", + "original-language", + "qc-needed", + "additional-information", + "status", + }; + + var dict = new Dictionary + { + { "_type", "MetadataProfileField" } + }; + + foreach (var metadataProfileFieldName in defaultMetaDataProfileFieldNames) + { + dict.Add($"metadata[{defaultMetaDataProfileFqn}].{metadataProfileFieldName}", string.Empty); + } + + metaDataProfileFqnSection.SetValue(new List { defaultMetaDataProfileFqn }); + valuesSection.Value = dict; + } + + private void SendNotificationButton_Pressed(object sender, EventArgs e) + { + var recordingSession = new RecordingSession + { + Id = idTextBox.Text, + Name = nameTextBox.Text, + Start = startDateTimePicker.DateTime.Truncate(TimeSpan.FromMinutes(1)), + End = endDateTimePicker.DateTime.Truncate(TimeSpan.FromMinutes(1)), + Recorder = recorderRefTextBox.Text, + Targets = new[] { targetRefTextbox.Text }, + Metadata = metaDataProfileFqnSection.GetValue().Select(x => new Metadata { Profile = x, Values = valuesSection.Value }).ToArray() + }; + + try + { + var debugRecordingService = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.DisplayedService { Name = "Test Recording Service" }; + + evsManager.AddOrUpdateRecordingSession(debugRecordingService, recordingSession); + + ShowRequestResult($"Sent notification", JsonConvert.SerializeObject(recordingSession) + "\n" + "Received ID: " + debugRecordingService.EvsId); + idTextBox.Text = debugRecordingService.EvsId; + } + catch (Exception ex) + { + ShowRequestResult($"Sent notification and got exception", JsonConvert.SerializeObject(recordingSession) + "\n" + "Exception: " + ex); + } + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(evsLabel, ++row, 0, 1, 2); + + AddWidget(idLabel, ++row, 0); + AddWidget(idTextBox, row, 1); + AddWidget(randomIdButton, row, 2); + + AddWidget(nameLabel, ++row, 0); + AddWidget(nameTextBox, row, 1); + + AddWidget(startLabel, ++row, 0); + AddWidget(startDateTimePicker, row, 1); + + AddWidget(endLabel, ++row, 0); + AddWidget(endDateTimePicker, row, 1); + + AddWidget(recorderRefLabel, ++row, 0); + AddWidget(recorderRefTextBox, row, 1); + + AddWidget(targetRefLabel, ++row, 0); + AddWidget(targetRefTextbox, row, 1); + + //AddWidget(new WhiteSpace(), ++row, 0); + //AddWidget(metadataTemplateButton, ++row, 0); + + AddSection(metaDataProfileFqnSection, new SectionLayout(++row, 0)); + row += metaDataProfileFqnSection.RowCount; + + AddSection(valuesSection, new SectionLayout(++row, 0)); + row += valuesSection.RowCount; + + //AddSection(contextSection, new SectionLayout(++row, 0)); + //row += contextSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(sendNotificationButton, ++row, 0, 1, 2); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendFeenixIntegrationNotificationDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendFeenixIntegrationNotificationDialog.cs new file mode 100644 index 0000000..bae49b3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendFeenixIntegrationNotificationDialog.cs @@ -0,0 +1,184 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations +{ + using System; + using Newtonsoft.Json; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Feenix; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.Utils.YLE.Integrations.Feenix; + + public class SendFeenixIntegrationNotificationDialog : DebugDialog + { + private readonly Label feenixLabel = new Label("Feenix") { Style = TextStyle.Heading }; + + private readonly Label feenixIdLabel = new Label("ID"); + private readonly YleTextBox feenixIdTextBox = new YleTextBox { ValidationText = "Invalid Guid", ValidationPredicate = text => Guid.TryParse(text, out var result) }; + private readonly Button randomIdButton = new Button("Enter Random Guid") { Width = 150 }; + + private readonly Label finnishTitleLabel = new Label("Finnish Title"); + private readonly YleTextBox finnishTitleTextBox = new YleTextBox(); + + private readonly Label swedishTitleLabel = new Label("Swedish Title"); + private readonly YleTextBox swedishTitleTextBox = new YleTextBox(); + + private readonly Label samiTitleLabel = new Label("Sami Title"); + private readonly YleTextBox samiTitleTextBox = new YleTextBox(); + + private readonly Label startLabel = new Label("Start"); + private readonly DateTimePicker startDateTimePicker = new DateTimePicker(DateTime.Now.AddHours(1)); + + private readonly Label endLabel = new Label("End"); + private readonly DateTimePicker endDateTimePicker = new DateTimePicker(DateTime.Now.AddHours(2)); + + private readonly Label sourceResourceLabel = new Label("Source Resource Name"); + private readonly TextBox sourceResourceTextBox = new TextBox(); + + private readonly Label destinationResourceLabel = new Label("Destination Resource Name"); + private readonly TextBox destinationResourceTextBox = new TextBox(); + + private readonly Label ceitonProjectIdLabel = new Label("Ceiton Project ID"); + private readonly TextBox ceitonProjectIdTextBox = new TextBox(); + + private readonly Label ceitonProductIdLabel = new Label("Ceiton Product ID"); + private readonly TextBox ceitonProductIdTextBox = new TextBox(); + + private readonly Button sendNotificationButton = new Button("Send Notification") { Width = 200 }; + + private readonly Button sendStopNotificationButton = new Button("Send Stop Notification") { Width = 200 }; + + private readonly Button deleteLiveStreamOrderButton = new Button("Delete Live Stream Order") { Width = 200 }; + + public SendFeenixIntegrationNotificationDialog(Utilities.Helpers helpers) : base(helpers) + { + Title = "Send Feenix Integration Notification"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + randomIdButton.Pressed += (s, e) => feenixIdTextBox.Text = Guid.NewGuid().ToString(); + sendNotificationButton.Pressed += SendNotificationButton_Pressed; + sendStopNotificationButton.Pressed += SendStopNotificationButton_Pressed; + deleteLiveStreamOrderButton.Pressed += DeleteLiveStreamOrderButton_Pressed; + } + + private void SendNotificationButton_Pressed(object sender, EventArgs e) + { + if (!feenixIdTextBox.IsValid) return; + + var notification = new FeenixNotification + { + Id = Guid.Parse(feenixIdTextBox.Text), + FinnishTitle = finnishTitleTextBox.Text, + SwedishTitle = swedishTitleTextBox.Text, + SamiTitle = samiTitleTextBox.Text, + Start = startDateTimePicker.DateTime, + End = endDateTimePicker.DateTime, + SourceResourceName = sourceResourceTextBox.Text, + DestinationResourceName = destinationResourceTextBox.Text, + CeitonProjectId = ceitonProjectIdTextBox.Text, + CeitonProductId = ceitonProductIdTextBox.Text, + }; + + string notficationString = notification.ToString(); + DataMinerInterface.IDmsElement.SetParameter(helpers, helpers.OrderManagerElement.FeenixElement, FeenixProtocol.LastReceivedNotificationParameterId, notficationString); + + ShowRequestResult($"Sent Notification {notification.Id}", JsonConvert.SerializeObject(notification, Formatting.Indented), notficationString); + } + + private void SendStopNotificationButton_Pressed(object sender, EventArgs e) + { + if (!feenixIdTextBox.IsValid) return; + + var notification = new FeenixStopNotification(feenixIdTextBox.Text); + + string notficationString = notification.ToString(); + DataMinerInterface.IDmsElement.SetParameter(helpers, helpers.OrderManagerElement.FeenixElement, FeenixProtocol.LastReceivedNotificationParameterId, notficationString); + + ShowRequestResult($"Sent Notification {notification.Id}", JsonConvert.SerializeObject(notification, Formatting.Indented), notficationString); + } + + private void DeleteLiveStreamOrderButton_Pressed(object sender, EventArgs e) + { + if (!feenixIdTextBox.IsValid) return; + + OrderManagerElement orderManagerElement = new OrderManagerElement(helpers); + if (orderManagerElement.FeenixElement == null || orderManagerElement.FeenixElement.State != ElementState.Active) + { + ShowRequestResult($"Unable to remove Live Stream Order {feenixIdTextBox.Text}", "Feenix element was not linked with order manager or not active"); + return; + } + + // Remove entry from Feenix element + var liveStreamOrdersTable = orderManagerElement.FeenixElement.GetTable(FeenixElement.LiveStreamOrdersTableParameterId); + if (liveStreamOrdersTable.RowExists(feenixIdTextBox.Text)) + { + liveStreamOrdersTable.DeleteRow(feenixIdTextBox.Text); + } + + // Trigger integration update + orderManagerElement.Element.SetParameter(150, feenixIdTextBox.Text); + + ShowRequestResult($"Removed Live Stream Order {feenixIdTextBox.Text}", "Removed"); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 5); + + AddWidget(feenixLabel, ++row, 0, 1, 5); + + AddWidget(feenixIdLabel, ++row, 0); + AddWidget(feenixIdTextBox, row, 1); + AddWidget(randomIdButton, row, 2); + + AddWidget(finnishTitleLabel, ++row, 0); + AddWidget(finnishTitleTextBox, row, 1); + + AddWidget(swedishTitleLabel, ++row, 0); + AddWidget(swedishTitleTextBox, row, 1); + + AddWidget(samiTitleLabel, ++row, 0); + AddWidget(samiTitleTextBox, row, 1); + + AddWidget(startLabel, ++row, 0); + AddWidget(startDateTimePicker, row, 1); + + AddWidget(endLabel, ++row, 0); + AddWidget(endDateTimePicker, row, 1); + + AddWidget(sourceResourceLabel, ++row, 0); + AddWidget(sourceResourceTextBox, row, 1); + + AddWidget(destinationResourceLabel, ++row, 0); + AddWidget(destinationResourceTextBox, row, 1); + + AddWidget(ceitonProjectIdLabel, ++row, 0); + AddWidget(ceitonProjectIdTextBox, row, 1); + + AddWidget(ceitonProductIdLabel, ++row, 0); + AddWidget(ceitonProductIdTextBox, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(sendNotificationButton, ++row, 0, 1, 5); + + AddWidget(sendStopNotificationButton, ++row, 0, 1, 5); + + AddWidget(deleteLiveStreamOrderButton, ++row, 0, 1, 5); + + AddResponseSections(row + 1); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendIntegrationNotificationDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendIntegrationNotificationDialog.cs new file mode 100644 index 0000000..01559c8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendIntegrationNotificationDialog.cs @@ -0,0 +1,90 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations +{ + using System; + using Debug_2.Debug.Integrations; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class SendIntegrationNotificationDialog : Dialog + { + public SendIntegrationNotificationDialog(Utilities.Helpers helpers) : base(helpers.Engine) + { + Title = "Send Integration Notification"; + + Initialize(helpers); + GenerateUi(); + } + + private void Initialize(Utilities.Helpers helpers) + { + FeenixNotificationDialog = new SendFeenixIntegrationNotificationDialog(helpers); + CeitonNotificationDialog = new SendCeitonIntegrationNotificationDialog(helpers); + PlasmaNotificationDialog = new SendPlasmaIntegrationNotificationDialog(helpers); + PlasmaNotificationOldDialog = new SendPlasmaIntegrationNotificationOldDialog(helpers); + EurovisionNotificationDialog = new SendEurovisionIntegrationNotificationDialog(helpers); + PbsNotificationDialog = new SendPbsIntegrationNotificationDialog(helpers); + + try + { + EvsNotificationDialog = new SendEvsNotificationDialog(helpers); + } + catch(Exception e) + { + helpers.Log(nameof(SendIntegrationNotificationDialog), nameof(Initialize), $"Exception occurred: {e}"); + EvsButton.IsEnabled = false; + } + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(FeenixButton, ++row, 0); + AddWidget(PlasmaButton, ++row, 0); + AddWidget(CeitonButton, ++row, 0); + AddWidget(EurovisionButton, ++row, 0); + AddWidget(PebbleBeachButton, ++row, 0); + AddWidget(EvsButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(PlasmaOldButton, ++row, 0); + } + + public Button FeenixButton { get; } = new Button("Feenix...") { Width = 150 }; + + public Button PlasmaButton { get; } = new Button("Plasma...") { Width = 150 }; + + public Button PlasmaOldButton { get; } = new Button("Plasma Old...") { Width = 150 }; + + public Button CeitonButton { get; } = new Button("Ceiton...") { Width = 150 }; + + public Button EurovisionButton { get; } = new Button("Eurovision...") { Width = 150 }; + + public Button PebbleBeachButton { get; } = new Button("Pebble Beach...") { Width = 150 }; + + public Button EvsButton { get; } = new Button("EVS...") { Width = 150 }; + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + public SendFeenixIntegrationNotificationDialog FeenixNotificationDialog { get; private set; } + + public SendCeitonIntegrationNotificationDialog CeitonNotificationDialog { get; private set; } + + public SendEurovisionIntegrationNotificationDialog EurovisionNotificationDialog { get; private set; } + + public SendPlasmaIntegrationNotificationDialog PlasmaNotificationDialog { get; private set; } + + public SendPlasmaIntegrationNotificationOldDialog PlasmaNotificationOldDialog { get; private set; } + + public SendEvsNotificationDialog EvsNotificationDialog { get; private set; } + + public SendPbsIntegrationNotificationDialog PbsNotificationDialog { get; private set; } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendPbsIntegrationNotificationDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendPbsIntegrationNotificationDialog.cs new file mode 100644 index 0000000..8c6b55f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendPbsIntegrationNotificationDialog.cs @@ -0,0 +1,479 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations +{ + using System; + using System.Linq; + using System.Collections.Generic; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + + public class SendPbsIntegrationNotificationDialog : Dialog + { + private readonly Utilities.Helpers helpers; + private readonly OrderManagerElement orderManagerElement; + private readonly IDmsElement pbsElement; + + private readonly Label pebbleBeachLabel = new Label("Pebble Beach") { Style = TextStyle.Heading }; + + private readonly Label pbsTitleLabel = new Label("Title"); + private readonly TextBox pbsTitleTextBox = new TextBox(); + + private readonly Label pbsUidLabel = new Label("Pebble Beach UID"); + private readonly TextBox pbsUidTextBox = new TextBox(); + private readonly Button randomUidButton = new Button("Enter Random UID") { Width = 150 }; + + private readonly Label pbsPlasmaIdLabel = new Label("Plasma ID"); + private readonly TextBox pbsPlasmaIdTextBox = new TextBox(); + private readonly CheckBox pbsPlasmaIdNaCheckBox = new CheckBox("N/A") { IsChecked = false }; + + private readonly Label pbsPlaylistIdLabel = new Label("Playlist ID"); + private readonly TextBox pbsPlaylistIdTextBox = new TextBox("5000"); + + private readonly Label pbsTypeLabel = new Label("Type"); + private readonly DropDown pbsTypeDropDown = new DropDown { Options = new string[] { "Live", "PrimaryVideo" }, Selected = "Live" }; + + private readonly Label pbsEstimatedStartTimeLabel = new Label("Estimated Start Time"); + private readonly DateTimePicker pbsEstimatedStartTimeDateTimePicker = new DateTimePicker { DateTime = DateTime.Now }; + + private readonly Label pbsActualStartTimeLabel = new Label("Actual Start Time"); + private readonly DateTimePicker pbsActualStartTimeDateTimePicker = new DateTimePicker { DateTime = DateTime.Now, IsEnabled = false }; + private readonly CheckBox pbsActualStartTimeNaCheckBox = new CheckBox ("N/A") { IsChecked = true }; + + private readonly Label pbsEstimatedEndTimeLabel = new Label("Estimated End Time"); + private readonly DateTimePicker pbsEstimatedEndTimeDateTimePicker = new DateTimePicker { DateTime = DateTime.Now.AddHours(1) }; + + private readonly Label pbsActualEndTimeLabel = new Label("Actual End Time"); + private readonly DateTimePicker pbsActualEndTimeDateTimePicker = new DateTimePicker { DateTime = DateTime.Now.AddHours(1), IsEnabled = false }; + private readonly CheckBox pbsActualEndTimeNaCheckBox = new CheckBox("N/A") { IsChecked = true }; + + private readonly Label pbsSourceLabel = new Label("Source"); + private readonly TextBox pbsSourceTextBox = new TextBox(); + private readonly CheckBox pbsSourceNaCheckBox = new CheckBox("N/A") { IsChecked = false }; + + private readonly Label pbsBackupSourceLabel = new Label("Backup Source"); + private readonly TextBox pbsBackupSourceTextBox = new TextBox(); + private readonly CheckBox pbsBackupSourceNaCheckBox = new CheckBox("N/A") { IsChecked = false }; + + private readonly Button sendNotificationButton = new Button("Send Notification") { Width = 200 }; + + private readonly List notificationSections = new List(); + + public SendPbsIntegrationNotificationDialog(Utilities.Helpers helpers) : base(helpers.Engine) + { + this.helpers = helpers; + orderManagerElement = new OrderManagerElement(helpers); + + try + { + pbsElement = orderManagerElement.PebbleBeachElement; + + Title = "Send Pebble Beach Integration Notification"; + + Initialize(); + GenerateUi(); + } + catch (Exception e) + { + helpers.Log(nameof(SendPbsIntegrationNotificationDialog), nameof(SendPbsIntegrationNotificationDialog), $"Unable to construct dialog: {e}"); + + Title = "Something went wrong :'("; + } + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private void Initialize() + { + randomUidButton.Pressed += (s, e) => pbsUidTextBox.Text = Guid.NewGuid().ToString(); + pbsPlasmaIdNaCheckBox.Changed += (s, e) => pbsPlasmaIdTextBox.IsEnabled = !pbsPlasmaIdNaCheckBox.IsChecked; + pbsActualStartTimeNaCheckBox.Changed += (s, e) => pbsActualStartTimeDateTimePicker.IsEnabled = !pbsActualStartTimeNaCheckBox.IsChecked; + pbsActualEndTimeNaCheckBox.Changed += (s, e) => pbsActualEndTimeDateTimePicker.IsEnabled = !pbsActualEndTimeNaCheckBox.IsChecked; + pbsSourceNaCheckBox.Changed += (s, e) => pbsSourceTextBox.IsEnabled = !pbsSourceNaCheckBox.IsChecked; + pbsBackupSourceNaCheckBox.Changed += (s, e) => pbsBackupSourceTextBox.IsEnabled = !pbsBackupSourceNaCheckBox.IsChecked; + + sendNotificationButton.Pressed += SendNotificationButton_Pressed; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(pebbleBeachLabel, ++row, 0, 1, 2); + + AddWidget(pbsTitleLabel, ++row, 0); + AddWidget(pbsTitleTextBox, row, 1); + + AddWidget(pbsUidLabel, ++row, 0); + AddWidget(pbsUidTextBox, row, 1); + AddWidget(randomUidButton, row, 2); + + AddWidget(pbsPlasmaIdLabel, ++row, 0); + AddWidget(pbsPlasmaIdTextBox, row, 1); + AddWidget(pbsPlasmaIdNaCheckBox, row, 2); + + AddWidget(pbsPlaylistIdLabel, ++row, 0); + AddWidget(pbsPlaylistIdTextBox, row, 1); + + AddWidget(pbsTypeLabel, ++row, 0); + AddWidget(pbsTypeDropDown, row, 1); + + AddWidget(pbsEstimatedStartTimeLabel, ++row, 0); + AddWidget(pbsEstimatedStartTimeDateTimePicker, row, 1); + + AddWidget(pbsActualStartTimeLabel, ++row, 0); + AddWidget(pbsActualStartTimeDateTimePicker, row, 1); + AddWidget(pbsActualStartTimeNaCheckBox, row, 2); + + AddWidget(pbsEstimatedEndTimeLabel, ++row, 0); + AddWidget(pbsEstimatedEndTimeDateTimePicker, row, 1); + + AddWidget(pbsActualEndTimeLabel, ++row, 0); + AddWidget(pbsActualEndTimeDateTimePicker, row, 1); + AddWidget(pbsActualEndTimeNaCheckBox, row, 2); + + AddWidget(pbsSourceLabel, ++row, 0); + AddWidget(pbsSourceTextBox, row, 1); + AddWidget(pbsSourceNaCheckBox, row, 2); + + AddWidget(pbsBackupSourceLabel, ++row, 0); + AddWidget(pbsBackupSourceTextBox, row, 1); + AddWidget(pbsBackupSourceNaCheckBox, row, 2); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(sendNotificationButton, ++row, 0, 1, 3); + + foreach (var notificationSection in notificationSections) + { + AddSection(notificationSection, ++row, 0); + row += notificationSection.RowCount; + } + } + + private void SendNotificationButton_Pressed(object sender, EventArgs e) + { + var notification = new PbsNotification + { + Title = pbsTitleTextBox.Text, + Uid = pbsUidTextBox.Text, + PlaylistId = pbsPlaylistIdTextBox.Text, + PlasmaId = pbsPlasmaIdNaCheckBox.IsChecked ? null : pbsPlasmaIdTextBox.Text, + Type = pbsTypeDropDown.Selected, + EstimatedStartTime = pbsEstimatedStartTimeDateTimePicker.DateTime, + ActualStartTime = pbsActualStartTimeNaCheckBox.IsChecked ? null : (DateTime?)pbsActualStartTimeDateTimePicker.DateTime, + EstimatedEndTime = pbsEstimatedEndTimeDateTimePicker.DateTime, + ActualEndTime = pbsActualEndTimeNaCheckBox.IsChecked ? null : (DateTime?)pbsActualEndTimeDateTimePicker.DateTime, + Source = pbsSourceNaCheckBox.IsChecked ? null : pbsSourceTextBox.Text, + BackupSource = pbsBackupSourceNaCheckBox.IsChecked ? null : pbsBackupSourceTextBox.Text + }; + + // check if playlist exists (optionally add playlist) + if (!DataMinerInterface.DataMinerInterface.IDmsElement.TableContainsPrimaryKey(helpers, pbsElement, Utils.YLE.Integrations.PebbleBeach.PebbleBeach.PlaylistsTablePid, notification.PlaylistId)) + { + AddPlaylist(notification); + } + + // add or update event entry in events table + string key = AddOrUpdateEvent(notification); + + // update subscription parameter with id of new or updated event + DataMinerInterface.DataMinerInterface.IDmsElement.SetParameter(helpers, pbsElement, Utils.YLE.Integrations.PebbleBeach.PebbleBeach.UpdatedEventIdsParameterPid, key); + + // Generate section + var pbsNotificationSection = new PbsNotificationSection(notification); + pbsNotificationSection.LoadButton.Pressed += NotificationSection_LoadButton_Pressed; + notificationSections.Add(pbsNotificationSection); + GenerateUi(); + } + + private void NotificationSection_LoadButton_Pressed(object sender, EventArgs e) + { + var section = notificationSections.FirstOrDefault(x => x.LoadButton.Equals(sender)); + if (section == null) return; + + // Load values in form + pbsTitleTextBox.Text = section.Notification.Title; + pbsUidTextBox.Text = section.Notification.Uid; + pbsPlaylistIdTextBox.Text = section.Notification.PlaylistId; + pbsPlasmaIdTextBox.Text = section.Notification.PlasmaId; + pbsPlasmaIdNaCheckBox.IsChecked = String.IsNullOrEmpty(section.Notification.PlasmaId); + pbsTypeDropDown.Selected = section.Notification.Type; + pbsEstimatedStartTimeDateTimePicker.DateTime = section.Notification.EstimatedStartTime; + pbsEstimatedEndTimeDateTimePicker.DateTime = section.Notification.EstimatedEndTime; + pbsActualStartTimeDateTimePicker.DateTime = section.Notification.ActualStartTime.HasValue ? section.Notification.ActualStartTime.Value : section.Notification.EstimatedStartTime; + pbsActualStartTimeNaCheckBox.IsChecked = !section.Notification.ActualStartTime.HasValue; + pbsActualEndTimeDateTimePicker.DateTime = section.Notification.ActualEndTime.HasValue ? section.Notification.ActualEndTime.Value : section.Notification.EstimatedEndTime; + pbsActualEndTimeNaCheckBox.IsChecked = !section.Notification.ActualEndTime.HasValue; + pbsSourceTextBox.Text = section.Notification.Source; + pbsSourceNaCheckBox.IsChecked = String.IsNullOrEmpty(section.Notification.Source); + pbsBackupSourceTextBox.Text = section.Notification.BackupSource; + pbsBackupSourceNaCheckBox.IsChecked = String.IsNullOrEmpty(section.Notification.BackupSource); + } + + private void AddPlaylist(PbsNotification notification) + { + object[] playlistRow = notification.GeneratePbsPlaylistRow(); + IDmsTable playlistTable = pbsElement.GetTable(Utils.YLE.Integrations.PebbleBeach.PebbleBeach.PlaylistsTablePid); + playlistTable.AddRow(playlistRow); + } + + private string AddOrUpdateEvent(PbsNotification notification) + { + object[] eventRow = notification.GeneratePbsEventRow(); + IDmsTable eventsTable = pbsElement.GetTable(Utils.YLE.Integrations.PebbleBeach.PebbleBeach.EventsTablePid); + if (eventsTable.GetPrimaryKeys().Contains(notification.Key)) + { + eventsTable.SetRow(notification.Key, eventRow); + } + else + { + eventsTable.AddRow(eventRow); + } + + return notification.Key; + } + + private sealed class PbsNotification + { + public string Key + { + get + { + return $"{PlaylistId}.{Uid}"; + } + } + + public string Title { get; set; } + + public string Uid { get; set; } + + public string PlasmaId { get; set; } + + public string PlaylistId { get; set; } + + public string Type { get; set; } + + public DateTime EstimatedStartTime { get; set; } + + public DateTime? ActualStartTime { get; set; } + + public DateTime EstimatedEndTime { get; set; } + + public DateTime? ActualEndTime { get; set; } + + public string Source { get; set; } + + public string BackupSource { get; set; } + + public object[] GeneratePbsPlaylistRow() + { + object[] playlistRow = new object[] + { + PlaylistId, // ID + $"Playlist {PlaylistId}", // Name [IDX] + 1, // Redundant Object + "-1", // Redundant Component ID + "-1", // Redundant Component Name + "-1" // Health Flag + }; + + return playlistRow; + } + + public object[] GeneratePbsEventRow() + { + double duration = EstimatedEndTime.Subtract(EstimatedStartTime).TotalSeconds; + double estimatedStartTime = EstimatedStartTime.ToOADate(); + double actualStartTime = ActualStartTime.HasValue ? ((DateTime)ActualStartTime).ToOADate() : -1; + double actualEndTime = ActualEndTime.HasValue ? ((DateTime)ActualEndTime).ToOADate() : -1; + string plasmaId = String.IsNullOrEmpty(PlasmaId) ? "-1" : PlasmaId; + string source = String.IsNullOrEmpty(Source) ? "-1" : Source; + string backupSource = String.IsNullOrEmpty(BackupSource) ? "-1" : BackupSource; + + object[] eventRow = new object[] + { + Key, // ID + Uid, // UID + PlaylistId, // Playlist ID + Title, // Title + plasmaId, // House ID + 1, // Status + Type, // Type + estimatedStartTime, // Scheduled start time + duration, // Duration + String.Empty, // Reconcile Keys + source, // Source + backupSource, // Backup Source + "-1", // Destination Auto Type + "-1", // Backup Destination Auto Type + "-1", // Block ID + "-1", // Running State + String.Empty, // Response + String.Empty, // Possible Sources + actualStartTime, // Actual start time + estimatedStartTime, // Estimated start time + 0, // End Type + 2, // Start Type + actualEndTime, // Actual end time + 0, // Actual start time frame + 0 // Actual end time frame + }; + + return eventRow; + } + } + + private sealed class PbsNotificationSection : Section + { + private readonly PbsNotification notification; + + private readonly CollapseButton collapseButton = new CollapseButton { CollapseText = "-", ExpandText = "+", Width = 44 }; + private readonly Label notificationTitleLabel = new Label { Style = TextStyle.Heading }; + + private readonly Label pbsTitleLabel = new Label("Title"); + private readonly Label pbsTitleValueLabel = new Label(); + + private readonly Label pbsKeyLabel = new Label("Event Table Key"); + private readonly Label pbsKeyValueLabel = new Label(); + + private readonly Label pbsUidLabel = new Label("Pebble Beach UID"); + private readonly Label pbsUidValueLabel = new Label(); + + private readonly Label pbsPlasmaIdLabel = new Label("Plasma ID"); + private readonly Label pbsPlasmaIdValueLabel = new Label(); + + private readonly Label pbsPlaylistIdLabel = new Label("Playlist ID"); + private readonly Label pbsPlaylistIdValueLabel = new Label(); + + private readonly Label pbsTypeLabel = new Label("Type"); + private readonly Label pbsTypeValueLabel = new Label(); + + private readonly Label pbsEstimatedStartTimeLabel = new Label("Estimated Start Time"); + private readonly Label pbsEstimatedStartTimeValueLabel = new Label(); + + private readonly Label pbsActualStartTimeLabel = new Label("Actual Start Time"); + private readonly Label pbsActualStartTimeValueLabel = new Label(); + + private readonly Label pbsEstimatedEndTimeLabel = new Label("Estimated End Time"); + private readonly Label pbsEstimatedEndTimeValueLabel = new Label(); + + private readonly Label pbsActualEndTimeLabel = new Label("Actual End Time"); + private readonly Label pbsActualEndTimeValueLabel = new Label(); + + private readonly Label pbsSourceLabel = new Label("Source"); + private readonly Label pbsSourceValueLabel = new Label(); + + private readonly Label pbsBackupSourceLabel = new Label("Backup Source"); + private readonly Label pbsBackupSourceValueLabel = new Label(); + + public PbsNotificationSection(PbsNotification notification) + { + this.notification = notification; + + notificationTitleLabel.Text = $"Sent notification {notification.Title} - {notification.Key}"; + + pbsTitleValueLabel.Text = notification.Title; + pbsKeyValueLabel.Text = notification.Key; + pbsUidValueLabel.Text = notification.Uid; + pbsTypeValueLabel.Text = notification.Type; + pbsPlasmaIdValueLabel.Text = notification.PlasmaId; + pbsPlasmaIdValueLabel.Text = notification.PlaylistId; + pbsEstimatedStartTimeValueLabel.Text = Convert.ToString(notification.EstimatedStartTime); + pbsEstimatedEndTimeValueLabel.Text = Convert.ToString(notification.EstimatedEndTime); + pbsActualStartTimeValueLabel.Text = Convert.ToString(notification.ActualStartTime); + pbsActualEndTimeValueLabel.Text = Convert.ToString(notification.ActualEndTime); + pbsSourceValueLabel.Text = notification.Source; + pbsBackupSourceValueLabel.Text = notification.BackupSource; + + collapseButton.LinkedWidgets.Add(pbsTitleLabel); + collapseButton.LinkedWidgets.Add(pbsTitleValueLabel); + collapseButton.LinkedWidgets.Add(pbsKeyLabel); + collapseButton.LinkedWidgets.Add(pbsKeyValueLabel); + collapseButton.LinkedWidgets.Add(pbsUidLabel); + collapseButton.LinkedWidgets.Add(pbsUidValueLabel); + collapseButton.LinkedWidgets.Add(pbsPlasmaIdLabel); + collapseButton.LinkedWidgets.Add(pbsPlasmaIdValueLabel); + collapseButton.LinkedWidgets.Add(pbsPlaylistIdLabel); + collapseButton.LinkedWidgets.Add(pbsPlaylistIdValueLabel); + collapseButton.LinkedWidgets.Add(pbsTypeLabel); + collapseButton.LinkedWidgets.Add(pbsTypeValueLabel); + collapseButton.LinkedWidgets.Add(pbsEstimatedStartTimeLabel); + collapseButton.LinkedWidgets.Add(pbsEstimatedStartTimeValueLabel); + collapseButton.LinkedWidgets.Add(pbsActualStartTimeLabel); + collapseButton.LinkedWidgets.Add(pbsActualStartTimeValueLabel); + collapseButton.LinkedWidgets.Add(pbsEstimatedEndTimeLabel); + collapseButton.LinkedWidgets.Add(pbsEstimatedEndTimeValueLabel); + collapseButton.LinkedWidgets.Add(pbsActualEndTimeLabel); + collapseButton.LinkedWidgets.Add(pbsActualEndTimeValueLabel); + collapseButton.LinkedWidgets.Add(pbsSourceLabel); + collapseButton.LinkedWidgets.Add(pbsSourceValueLabel); + collapseButton.LinkedWidgets.Add(pbsBackupSourceLabel); + collapseButton.LinkedWidgets.Add(pbsBackupSourceValueLabel); + collapseButton.Collapse(); + + GenerateUi(); + } + + public Button LoadButton { get; private set; } = new Button("Load"); + + public PbsNotification Notification + { + get + { + return notification; + } + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(collapseButton, ++row, 0); + AddWidget(notificationTitleLabel, row, 1, 1, 2); + AddWidget(LoadButton, row, 3); + + AddWidget(pbsTitleLabel, ++row, 1); + AddWidget(pbsTitleValueLabel, row, 2); + + AddWidget(pbsKeyLabel, ++row, 1); + AddWidget(pbsKeyValueLabel, row, 2); + + AddWidget(pbsUidLabel, ++row, 1); + AddWidget(pbsUidValueLabel, row, 2); + + AddWidget(pbsPlasmaIdLabel, ++row, 1); + AddWidget(pbsPlasmaIdValueLabel, row, 2); + + AddWidget(pbsPlaylistIdLabel, ++row, 1); + AddWidget(pbsPlaylistIdValueLabel, row, 2); + + AddWidget(pbsTypeLabel, ++row, 1); + AddWidget(pbsTypeValueLabel, row, 2); + + AddWidget(pbsEstimatedStartTimeLabel, ++row, 1); + AddWidget(pbsEstimatedStartTimeValueLabel, row, 2); + + AddWidget(pbsActualStartTimeLabel, ++row, 1); + AddWidget(pbsActualStartTimeValueLabel, row, 2); + + AddWidget(pbsEstimatedEndTimeLabel, ++row, 1); + AddWidget(pbsEstimatedEndTimeValueLabel, row, 2); + + AddWidget(pbsActualEndTimeLabel, ++row, 1); + AddWidget(pbsActualEndTimeValueLabel, row, 2); + + AddWidget(pbsSourceLabel, ++row, 1); + AddWidget(pbsSourceValueLabel, row, 2); + + AddWidget(pbsBackupSourceLabel, ++row, 1); + AddWidget(pbsBackupSourceValueLabel, row, 2); + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendPlasmaIntegrationNotificationDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendPlasmaIntegrationNotificationDialog.cs new file mode 100644 index 0000000..13a3f81 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendPlasmaIntegrationNotificationDialog.cs @@ -0,0 +1,175 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations +{ + using System; + using System.Linq; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.JsonObjects; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.YLE.Integrations.Integrations.Plasma.ParsedObjects; + using Skyline.DataMiner.Utils.YLE.Integrations.Plasma; + using Skyline.DataMiner.Utils.YLE.Integrations.Plasma.VCM; + using Newtonsoft.Json; + + public class SendPlasmaIntegrationNotificationDialog : DebugDialog + { + private YleCollapseButton parsedProgramCollapseButton; + private readonly Label parsedProgramHeaderLabel = new Label("Parsed Program") { Style = TextStyle.Heading }; + private readonly ParsedProgram parsedProgram = new ParsedProgram(); + private JsonObjectSection parsedProgramSection; + private readonly Button sendParsedProgramNotificationButton = new Button("Send Parsed Program") { Width = 200 }; + + private YleCollapseButton editorialObjectCollapseButton; + private readonly Label editorialObjectHeaderLabel = new Label("Editorial Object") { Style = TextStyle.Heading }; + private readonly EditorialObject editorialObject = new EditorialObject(); + private JsonObjectSection editorialObjectSection; + private readonly Button sendEditorialObjectNotificationButton = new Button("Send Editorial Object") { Width = 200 }; + + private YleCollapseButton publicationEventCollapseButton; + private readonly Label publicationEventHeaderLabel = new Label("Publication Event") { Style = TextStyle.Heading }; + private readonly PublicationEvent publicationEvent = new PublicationEvent(); + private JsonObjectSection publicationEventSection; + private readonly Button sendPublicationEventNotificationButton = new Button("Send Publication Event") { Width = 200 }; + + private YleCollapseButton parsedPublicationEventCollapseButton; + private readonly Label parsedPublicationEventHeaderLabel = new Label("Parsed Publication Event") { Style = TextStyle.Heading }; + private readonly ParsedPublicationEvent parsedPublicationEvent = new ParsedPublicationEvent(); + private JsonObjectSection parsedPublicationEventSection; + private readonly Button sendParsedPublicationEventNotificationButton = new Button("Send Parsed PublicationEvent") { Width = 200 }; + + public SendPlasmaIntegrationNotificationDialog(Utilities.Helpers helpers) : base(helpers) + { + Title = "Send Plasma Integration Notification"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + editorialObjectSection = new JsonObjectSection(editorialObject); + editorialObjectSection.RegenerateUi += RegenerateUi; + sendEditorialObjectNotificationButton.Pressed += SendEditorialObjectNotificationButton_Pressed; + editorialObjectCollapseButton = new YleCollapseButton(editorialObjectSection.Widgets.Concat(sendEditorialObjectNotificationButton.Yield()), true); + + publicationEventSection = new JsonObjectSection(publicationEvent); + publicationEventSection.RegenerateUi += RegenerateUi; + sendPublicationEventNotificationButton.Pressed += SendPublicationEventNotificationButton_Pressed; + publicationEventCollapseButton = new YleCollapseButton(publicationEventSection.Widgets.Concat(sendPublicationEventNotificationButton.Yield()), true); + + parsedProgramSection = new JsonObjectSection(parsedProgram); + parsedProgramSection.RegenerateUi += RegenerateUi; + sendParsedProgramNotificationButton.Pressed += SendParsedProgramNotificationButton_Pressed; + parsedProgramCollapseButton = new YleCollapseButton(parsedProgramSection.Widgets.Concat(sendParsedProgramNotificationButton.Yield()), true); + + parsedPublicationEventSection = new JsonObjectSection(parsedPublicationEvent); + parsedPublicationEventSection.RegenerateUi += RegenerateUi; + sendParsedPublicationEventNotificationButton.Pressed += SendParsedPublicationEventNotificationButton_Pressed; + parsedPublicationEventCollapseButton = new YleCollapseButton(parsedPublicationEventSection.Widgets.Concat(sendParsedPublicationEventNotificationButton.Yield()), true); + } + + private void SendParsedProgramNotificationButton_Pressed(object sender, EventArgs e) + { + parsedProgramSection.UpdateJsonObjectWithUiValues(); + + helpers.Log(nameof(SendPlasmaIntegrationNotificationDialog), nameof(SendParsedProgramNotificationButton_Pressed), $"Parsed program: {JsonConvert.SerializeObject(parsedProgram)}"); + + string notification = parsedProgram.ToNotification(); + + DataMinerInterface.IDmsElement.SetParameter(helpers, helpers.OrderManagerElement.PlasmaElement, MediagenixWhatsOnProtocol.RabbitMqMessagePid, notification); + + ShowRequestResult($"Sent editorial object notification", notification); + GenerateUi(); + } + + private void SendPublicationEventNotificationButton_Pressed(object sender, EventArgs e) + { + publicationEventSection.UpdateJsonObjectWithUiValues(); + + string publicationEventNotification = publicationEvent.ToNotification(); + + DataMinerInterface.IDmsElement.SetParameter(helpers, helpers.OrderManagerElement.PlasmaElement, MediagenixWhatsOnProtocol.RabbitMqMessagePid, publicationEventNotification); + + ShowRequestResult($"Sent publication event notification", publicationEventNotification); + GenerateUi(); + } + + private void SendParsedPublicationEventNotificationButton_Pressed(object sender, EventArgs e) + { + parsedPublicationEventSection.UpdateJsonObjectWithUiValues(); + + helpers.Log(nameof(SendPlasmaIntegrationNotificationDialog), nameof(SendParsedPublicationEventNotificationButton_Pressed), $"Parsed publication event: {JsonConvert.SerializeObject(parsedPublicationEvent)}"); + + string publicationEventNotification = parsedPublicationEvent.ToNotification(); + + DataMinerInterface.IDmsElement.SetParameter(helpers, helpers.OrderManagerElement.PlasmaElement, MediagenixWhatsOnProtocol.RabbitMqMessagePid, publicationEventNotification); + + ShowRequestResult($"Sent publication event notification", publicationEventNotification); + GenerateUi(); + } + + private void RegenerateUi(object sender, EventArgs e) + { + GenerateUi(); + } + + private void SendEditorialObjectNotificationButton_Pressed(object sender, EventArgs e) + { + editorialObjectSection.UpdateJsonObjectWithUiValues(); + + string programNotification = editorialObject.ToNotification(); + + DataMinerInterface.IDmsElement.SetParameter(helpers, helpers.OrderManagerElement.PlasmaElement, MediagenixWhatsOnProtocol.RabbitMqMessagePid, programNotification); + + ShowRequestResult($"Sent editorial object notification", programNotification); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 5); + + AddWidget(parsedProgramCollapseButton, ++row, 0); + AddWidget(parsedProgramHeaderLabel, row, 1, 1, 5); + AddSection(parsedProgramSection, new SectionLayout(++row, 0)); + row += parsedProgramSection.RowCount; + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(sendParsedProgramNotificationButton, ++row, 0, 1, 5); + + AddWidget(editorialObjectCollapseButton, ++row, 0); + AddWidget(editorialObjectHeaderLabel, row, 1, 1, 5); + AddSection(editorialObjectSection, new SectionLayout(++row, 0)); + row += editorialObjectSection.RowCount; + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(sendEditorialObjectNotificationButton, ++row, 0, 1, 5); + + AddWidget(parsedPublicationEventCollapseButton, ++row, 0); + AddWidget(parsedPublicationEventHeaderLabel, row, 1, 1, 5); + AddSection(parsedPublicationEventSection, new SectionLayout(++row, 0)); + row += parsedPublicationEventSection.RowCount; + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(sendParsedPublicationEventNotificationButton, ++row, 0, 1, 5); + + AddWidget(publicationEventCollapseButton, ++row, 0); + AddWidget(publicationEventHeaderLabel, row, 1, 1, 5); + AddSection(publicationEventSection, new SectionLayout(++row, 0)); + row += publicationEventSection.RowCount; + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(sendPublicationEventNotificationButton, ++row, 0, 1, 5); + + AddResponseSections(++row); + + foreach (var yleWidget in Widgets.OfType()) + { + // To enable logging of user input + yleWidget.Helpers = helpers; + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendPlasmaIntegrationNotificationOldDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendPlasmaIntegrationNotificationOldDialog.cs new file mode 100644 index 0000000..cf5bdda --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Integrations/SendPlasmaIntegrationNotificationOldDialog.cs @@ -0,0 +1,371 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations +{ + using System; + using System.Linq; + using System.Collections.Generic; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.Utils.YLE.Integrations.Plasma; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.Utils.YLE.Integrations.Integrations.Plasma.ParsedObjects; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + using ColumnFilter = Core.DataMinerSystem.Common.ColumnFilter; + using ComparisonOperator = Core.DataMinerSystem.Common.ComparisonOperator; + using Skyline.DataMiner.Utils.YLE.Integrations.Integrations.Plasma.Enums; + + public class SendPlasmaIntegrationNotificationOldDialog : DebugDialog + { + private readonly Label plasmaLabel = new Label("Plasma") { Style = TextStyle.Heading }; + + private readonly Label programLabel = new Label("Program Information") { Style = TextStyle.Heading }; + private readonly Label transmissionsLabel = new Label("Transmissions") { Style = TextStyle.Heading }; + + private readonly Label noTransmissionsLabel = new Label("No Transmissions"); + + private readonly Label idLabel = new Label("ID"); + private readonly YleTextBox idTextBox = new YleTextBox { ValidationText = "Required field", ValidationPredicate = text => !String.IsNullOrWhiteSpace(text), Text = Guid.NewGuid().ToString() }; + private readonly Button randomIdButton = new Button("Enter Random Guid") { Width = 150 }; + + private readonly Label plasmaIdLabel = new Label("Plasma ID"); + private readonly YleTextBox plasmaIdTextBox = new YleTextBox { ValidationText = "Required field", ValidationPredicate = text => !String.IsNullOrWhiteSpace(text), Text = Guid.NewGuid().ToString() }; + private readonly Button randomPlasmaIdButton = new Button("Enter Random Guid") { Width = 150 }; + + private readonly Label categoryLabel = new Label("Category"); + private readonly DropDown categoryDropDown = new DropDown { Options = Enum.GetNames(typeof(Category)), Selected = Enum.GetName(typeof(Category), Category.Uutiset) }; + + private readonly Label subcategoryLabel = new Label("Sub Category"); + private readonly DropDown subcategoryDropDown = new DropDown { Options = Enum.GetNames(typeof(SubCategory)), Selected = Enum.GetName(typeof(SubCategory), SubCategory.Uutisbulletiini) }; + + private readonly Label projectNumberLabel = new Label("Project Number"); + private readonly TextBox projectNumberTextBox = new TextBox(); + + private readonly Label productNumberLabel = new Label("Product Number"); + private readonly TextBox productNumberTextBox = new TextBox(); + + private readonly Label yleIdLabel = new Label("YLE ID"); + private readonly TextBox yleIdTextBox = new TextBox(); + + private readonly Label finnishPublicationNameLabel = new Label("Finnish Publication Name"); + private readonly TextBox finnishPublicationNameTextBox = new TextBox(); + + private readonly Button sendProgramNotificationButton = new Button("Send Program Notification") { Width = 200 }; + private readonly Button deleteProgramInfoButton = new Button("Delete Program Info") { Width = 200 }; + + private readonly Button addTransmissionButton = new Button("Add Transmission"); + + private readonly List transmissionSections = new List(); + + public SendPlasmaIntegrationNotificationOldDialog(Utilities.Helpers helpers) : base(helpers) + { + Title = "Send Plasma Integration Notification"; + + Initialize(); + GenerateUi(); + + AddTransmissionSection(); + } + + private void Initialize() + { + randomIdButton.Pressed += (s, e) => + { + idTextBox.Text = Guid.NewGuid().ToString(); + foreach (var section in transmissionSections) section.ProgramId = idTextBox.Text; + }; + + randomPlasmaIdButton.Pressed += (s, e) => plasmaIdTextBox.Text = Guid.NewGuid().ToString(); + + idTextBox.Changed += (s, e) => + { + foreach (var section in transmissionSections) section.ProgramId = idTextBox.Text; + }; + + sendProgramNotificationButton.Pressed += (s, e) => SendProgramNotificationButton_Pressed(); + deleteProgramInfoButton.Pressed += (s, e) => DeleteProgramInfo(); + addTransmissionButton.Pressed += (sender, args) => AddTransmissionSection(); + } + + private void AddTransmissionSection() + { + var section = new TransmissionSection(helpers, idTextBox.Text); + section.RemoveButton.Pressed += RemoveTransmissionSectionButton_Pressed; + section.UiUpdated += (s, e) => GenerateUi(); + section.ShowRequestResult += (s, e) => + { + ShowRequestResult($"Sent publication event notification", e); + GenerateUi(); + }; + + transmissionSections.Add(section); + GenerateUi(); + } + + private void RemoveTransmissionSectionButton_Pressed(object sender, EventArgs e) + { + transmissionSections.RemoveAll(x => x.RemoveButton.Equals(sender)); + GenerateUi(); + } + + private void SendProgramNotificationButton_Pressed() + { + Category category = (Category)Enum.Parse(typeof(Category), categoryDropDown.Selected); + SubCategory subcategory = (SubCategory)Enum.Parse(typeof(SubCategory), subcategoryDropDown.Selected); + + var parsedProgram = new ParsedProgram() + { + Id = idTextBox.Text, + PlasmaId = plasmaIdTextBox.Text, + FinnishPublicationName = finnishPublicationNameTextBox.Text, + ProjectNumber = projectNumberTextBox.Text, + ProductNumber = productNumberTextBox.Text, + YleId = yleIdTextBox.Text, + YleMainCategory = (int)category, + YleSubCategory = subcategory.GetDescription() + }; + + string notification = parsedProgram.ToNotification(); + + DataMinerInterface.IDmsElement.SetParameter(helpers, helpers.OrderManagerElement.PlasmaElement, MediagenixWhatsOnProtocol.RabbitMqMessagePid, notification); + + ShowRequestResult($"Sent Parsed Program object notification", notification); + GenerateUi(); + } + + private void DeleteProgramInfo() + { + if (!plasmaIdTextBox.IsValid) return; + + OrderManagerElement orderManagerElement = new OrderManagerElement(helpers); + if (orderManagerElement.PlasmaElement == null || orderManagerElement.PlasmaElement.State != ElementState.Active) + { + ShowRequestResult($"Unable to remove Program {plasmaIdTextBox.Text}", "Plasma element was not linked with order manager or not active"); + return; + } + + // Remove entry from Feenix element + var programTable = orderManagerElement.PlasmaElement.GetTable(MediagenixWhatsOnProtocol.ProgramsTable.TablePid); + var programKeys = programTable.QueryData(new ColumnFilter[] { new ColumnFilter + { + Pid = MediagenixWhatsOnProtocol.ProgramsTable.Pid.PlasmaId, + ComparisonOperator = ComparisonOperator.Equal, + Value = plasmaIdTextBox.Text + } + }).Select(x => Convert.ToString(x[0])).ToList(); + + foreach (var key in programKeys) + { + programTable.DeleteRow(key); + orderManagerElement.Element.SetParameter(130, key); + ShowRequestResult($"Removed Live Stream Order {key}", "Removed"); + } + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(plasmaLabel, ++row, 0, 1, 2); + + AddWidget(programLabel, ++row, 0, 1, 2); + + AddWidget(idLabel, ++row, 0); + AddWidget(idTextBox, row, 1); + AddWidget(randomIdButton, row, 2); + + AddWidget(plasmaIdLabel, ++row, 0); + AddWidget(plasmaIdTextBox, row, 1); + AddWidget(randomPlasmaIdButton, row, 2); + + AddWidget(finnishPublicationNameLabel, ++row, 0); + AddWidget(finnishPublicationNameTextBox, row, 1); + + AddWidget(projectNumberLabel, ++row, 0); + AddWidget(projectNumberTextBox, row, 1); + + AddWidget(productNumberLabel, ++row, 0); + AddWidget(productNumberTextBox, row, 1); + + AddWidget(yleIdLabel, ++row, 0); + AddWidget(yleIdTextBox, row, 1); + + AddWidget(categoryLabel, ++row, 0); + AddWidget(categoryDropDown, row, 1); + + AddWidget(subcategoryLabel, ++row, 0); + AddWidget(subcategoryDropDown, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + row = GenerateUi_AddTransmissionSections(row); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(sendProgramNotificationButton, ++row, 0, 1, 5); + + AddWidget(deleteProgramInfoButton, ++row, 0, 1, 5); + + AddResponseSections(row + 1); + } + + private int GenerateUi_AddTransmissionSections(int row) + { + AddWidget(transmissionsLabel, ++row, 0, 1, 2); + if (transmissionSections.Any()) + { + foreach (var section in transmissionSections) + { + AddSection(section, new SectionLayout(++row, 0)); + row += section.RowCount; + } + } + else + { + AddWidget(noTransmissionsLabel, ++row, 0, 1, 2); + } + + AddWidget(addTransmissionButton, ++row, 0, 1, 2); + + return row; + } + + private sealed class TransmissionSection : Section + { + private readonly Utilities.Helpers helpers; + + private readonly Label idLabel = new Label("Transmission ID"); + private readonly YleTextBox idTextBox = new YleTextBox { ValidationText = "Required field", ValidationPredicate = text => !String.IsNullOrWhiteSpace(text), Text = Guid.NewGuid().ToString() }; + private readonly Button randomIdButton = new Button("Enter Random Guid") { Width = 150 }; + + private readonly Label startLabel = new Label("Start"); + private readonly DateTimePicker startDateTimePicker = new DateTimePicker(); + + private readonly Label endLabel = new Label("End"); + private readonly DateTimePicker endDateTimePicker = new DateTimePicker(); + + private readonly Label sourceLabel = new Label("Source"); + private readonly TextBox sourceTextBox = new TextBox(); + + private readonly Label channelLabel = new Label("Channel"); + private readonly TextBox channelTextBox = new TextBox(); + + private readonly Label originalTxLabel = new Label("Original Tx"); + private readonly TextBox originalTxTextBox = new TextBox(); + + private readonly Label typeLabel = new Label("Type"); + private readonly DropDown typeDropDown = new DropDown { Options = Enum.GetNames(typeof(TransmissionType)), Selected = TransmissionType.Linear.ToString() }; + + private readonly Label isLiveLabel = new Label("Is Live"); + private readonly CheckBox isLiveCheckBox = new CheckBox { IsChecked = true }; + + private readonly Button sendTransmissionNotificationButton = new Button("Send Transmission Notification") { Width = 200 }; + + public Button RemoveButton { get; private set; } = new Button("Remove Transmission"); + + public string ProgramId { get; set; } + + public TransmissionSection(Utilities.Helpers helpers, string programId) + { + this.helpers = helpers; + ProgramId = programId; + + Initialize(); + GenerateUi(); + } + + public event EventHandler ShowRequestResult; + + public event EventHandler UiUpdated; + + //public Transmission ToAsset() + //{ + // TransmissionType type = (TransmissionType)Enum.Parse(typeof(TransmissionType), typeDropDown.Selected); + + // return new Transmission(idTextBox.Text) + // { + // IsLive = isLiveCheckBox.IsChecked, + // Start = startDateTimePicker.DateTime, + // End = endDateTimePicker.DateTime, + // OriginalTx = originalTxTextBox.Text, + // Channel = channelTextBox.Text, + // Type = type, + // Source = sourceTextBox.Text + // }; + //} + + private void Initialize() + { + randomIdButton.Pressed += (s, e) => idTextBox.Text = Guid.NewGuid().ToString(); + sendTransmissionNotificationButton.Pressed += SendTransmissionNotificationButton_Pressed; + } + + private void SendTransmissionNotificationButton_Pressed(object sender, EventArgs e) + { + var parsedPublicationEvent = new ParsedPublicationEvent + { + Channel = channelTextBox.Text, + Id = idTextBox.Text, + ProgramId = ProgramId, + Live = Convert.ToInt32(isLiveCheckBox.IsChecked), + Source = sourceTextBox.Text, + Start = startDateTimePicker.DateTime, + End = endDateTimePicker.DateTime, + Type = typeDropDown.Selected, + Status = "Created" + }; + + string publicationEventNotification = parsedPublicationEvent.ToNotification(); + + DataMinerInterface.IDmsElement.SetParameter(helpers, helpers.OrderManagerElement.PlasmaElement, MediagenixWhatsOnProtocol.RabbitMqMessagePid, publicationEventNotification); + + ShowRequestResult?.Invoke(this, publicationEventNotification); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(idLabel, ++row, 0); + AddWidget(idTextBox, row, 1); + AddWidget(randomIdButton, row, 2); + + AddWidget(startLabel, ++row, 0); + AddWidget(startDateTimePicker, row, 1); + + AddWidget(endLabel, ++row, 0); + AddWidget(endDateTimePicker, row, 1); + + AddWidget(typeLabel, ++row, 0); + AddWidget(typeDropDown, row, 1); + + AddWidget(isLiveLabel, ++row, 0); + AddWidget(isLiveCheckBox, row, 1); + + AddWidget(sourceLabel, ++row, 0); + AddWidget(sourceTextBox, row, 1); + + AddWidget(channelLabel, ++row, 0); + AddWidget(channelTextBox, row, 1); + + AddWidget(originalTxLabel, ++row, 0); + AddWidget(originalTxTextBox, row, 1); + + AddWidget(sendTransmissionNotificationButton, ++row, 0, 1, 2); + AddWidget(RemoveButton, row + 1, 0, 1, 2); + + // Call event to update parent dialog + UiUpdated?.Invoke(this, EventArgs.Empty); + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Jobs/FindReservationsWithoutJobDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Jobs/FindReservationsWithoutJobDialog.cs new file mode 100644 index 0000000..b2354af --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Jobs/FindReservationsWithoutJobDialog.cs @@ -0,0 +1,202 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Jobs +{ + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Jobs; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + + public class FindReservationsWithoutJobDialog : Dialog + { + private readonly Helpers helpers; + private readonly JobManagerHelper jobManager; + private readonly Button FindReservations = new Button("Find Reservations"); + private static readonly string description = "This will search all video orders on the system and check if the job id is filled out and the job is available."; + private readonly List reservationInstancesWithoutJob = new List(); + private bool hasRun = false; + + public FindReservationsWithoutJobDialog(Helpers helpers) : base(helpers.Engine) + { + this.helpers = helpers; + jobManager = new JobManagerHelper(m => helpers.Engine.SendSLNetMessages(m)); + + Title = "Find Reservations Without Jobs"; + + GenerateUI(); + FindReservations.Pressed += FindReservations_Pressed; + FixAllButton.Pressed += FixAllButton_Pressed; + } + + private void GenerateUI() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 4); + AddWidget(new WhiteSpace(), ++row, 0, 1, 4); + + AddWidget(FindReservations, ++row, 0, 1, 4); + AddWidget(new Label(description), ++row, 0, 1, 4); + + if (!hasRun) return; + AddWidget(new WhiteSpace(), ++row, 0, 1, 4); + if (reservationInstancesWithoutJob.Any()) + { + AddWidget(new Label("Reservation ID") { Style = TextStyle.Heading }, ++row, 0); + AddWidget(new Label("Reservation Name") { Style = TextStyle.Heading }, row, 1); + AddWidget(new Label("Reason") { Style = TextStyle.Heading }, row, 2); + AddWidget(FixAllButton, row, 3); + + foreach (var reservation in reservationInstancesWithoutJob) + { + AddWidget(new Label(reservation.ReservationInstance.ID.ToString()), ++row, 0); + AddWidget(new Label(reservation.ReservationInstance.Name), row, 1); + AddWidget(new Label(reservation.Reason), row, 2); + AddWidget(reservation.FixButton, row, 3); + } + } + else + { + AddWidget(new Label("No Reservations without job"), ++row, 0, 1, 4); + } + } + + private void FindReservations_Pressed(object sender, EventArgs e) + { + var reservations = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, ReservationInstanceExposers.Properties.DictStringField("Type").Equal("Video")); + foreach (var reservation in reservations) + { + ReservationWithoutJob reservationWithoutJob; + if (!reservation.Properties.ContainsKey(LiteOrder.PropertyNameEventId)) + { + reservationWithoutJob = new ReservationWithoutJob + { + ReservationInstance = reservation, + Reason = "No event ID property", + EventId = String.Empty + }; + + reservationWithoutJob.FixButton.Pressed += FixButton_Pressed; + reservationInstancesWithoutJob.Add(reservationWithoutJob); + continue; + } + + string rawEventId = Convert.ToString(reservation.Properties.Dictionary[LiteOrder.PropertyNameEventId]); + if (String.IsNullOrWhiteSpace(rawEventId)) + { + reservationWithoutJob = new ReservationWithoutJob + { + ReservationInstance = reservation, + Reason = "Empty event ID property", + EventId = rawEventId + }; + + reservationWithoutJob.FixButton.Pressed += FixButton_Pressed; + reservationInstancesWithoutJob.Add(reservationWithoutJob); + continue; + } + + Guid eventId; + if (!Guid.TryParse(rawEventId, out eventId)) + { + reservationWithoutJob = new ReservationWithoutJob + { + ReservationInstance = reservation, + Reason = "Invalid event ID property", + EventId = rawEventId + }; + + reservationWithoutJob.FixButton.Pressed += FixButton_Pressed; + reservationInstancesWithoutJob.Add(reservationWithoutJob); + continue; + } + + var job = jobManager.Jobs.Read(JobExposers.ID.Equal(eventId)).FirstOrDefault(); + if (job == null) + { + reservationWithoutJob = new ReservationWithoutJob + { + ReservationInstance = reservation, + Reason = "Unable to find job", + EventId = rawEventId + }; + + reservationWithoutJob.FixButton.Pressed += FixButton_Pressed; + reservationInstancesWithoutJob.Add(reservationWithoutJob); + } + } + + hasRun = true; + GenerateUI(); + } + + private void FixButton_Pressed(object sender, EventArgs e) + { + var reservationInstanceWithoutJob = reservationInstancesWithoutJob.FirstOrDefault(x => x.FixButton.Equals(sender)); + if (reservationInstancesWithoutJob == null) return; + + if (!reservationInstanceWithoutJob.Fix(helpers)) return; + + reservationInstancesWithoutJob.Remove(reservationInstanceWithoutJob); + GenerateUI(); + } + + private void FixAllButton_Pressed(object sender, EventArgs e) + { + List fixedOrders = new List(); + foreach (var reservationWithoutJob in reservationInstancesWithoutJob) + { + if (!reservationWithoutJob.Fix(helpers)) continue; + fixedOrders.Add(reservationWithoutJob); + } + + reservationInstancesWithoutJob.RemoveAll(x => fixedOrders.Contains(x)); + GenerateUI(); + } + + public Button BackButton { get; private set; } = new Button("Back..."); + + private Button FixAllButton { get; } = new Button("Fix All"); + } + + class ReservationWithoutJob + { + public ReservationInstance ReservationInstance { get; set; } + + public string Reason { get; set; } + + public string EventId { get; set; } + + public Button FixButton { get; } = new Button("Fix"); + + public bool Fix(Helpers helpers) + { + try + { + helpers.Log(nameof(ReservationWithoutJob), nameof(Fix), $"Fixing event for reservationInstance with ID {ReservationInstance.ID}..."); + LiteOrder order = helpers.OrderManager.GetLiteOrder(ReservationInstance); + order.Event = new Event.Event(helpers, order); + + helpers.EventManager.AddOrUpdateEvent(order.Event); + order.UpdateEventReference(helpers); + + helpers.Log(nameof(ReservationWithoutJob), nameof(Fix), $"Fixing event for reservationInstance with ID {ReservationInstance.ID} was successful"); + return true; + } + catch (Exception exception) + { + helpers.Log(nameof(ReservationWithoutJob), nameof(Fix), $"Fixing event for reservationInstance with ID {ReservationInstance.ID} failed: {exception}"); + return false; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Jobs/ManageSectionDefinitionsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Jobs/ManageSectionDefinitionsDialog.cs new file mode 100644 index 0000000..1eb90be --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Jobs/ManageSectionDefinitionsDialog.cs @@ -0,0 +1,196 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Jobs +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Cryptography; + using System.Text; + using System.Threading.Tasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net; + using Skyline.DataMiner.Net.Correlation; + using Skyline.DataMiner.Net.Jobs; + using Skyline.DataMiner.Net.Sections; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Section = Utils.InteractiveAutomationScript.Section; + + public class ManageSectionDefinitionsDialog : DebugDialog + { + private readonly Label titleLabel = new Label("Manage Section Definitions") { Style = TextStyle.Heading }; + private readonly Button listSectionDefinitionsButton = new Button("List Section Definitions"); + private readonly List sections = new List(); + private readonly Button removeSelectedFieldDescriptorsButton = new Button("Remove Selected Field Descriptors"); + + public ManageSectionDefinitionsDialog(Helpers helpers) : base(helpers) + { + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + listSectionDefinitionsButton.Pressed += (s, e) => ListSectionDefinitions(); + removeSelectedFieldDescriptorsButton.Pressed += (s, e) => + { + JobManagerHelper jobManager = new JobManagerHelper(msg => Automation.Engine.SLNet.SendMessages(msg)); + foreach (var section in sections) + { + if (!section.SelectedFieldDescriptors.Any()) continue; + var retrievedSection = jobManager.SectionDefinitions.Read(SectionDefinitionExposers.ID.Equal(section.SectionDefinition.GetID())).FirstOrDefault(); + if (retrievedSection == null) + { + Engine.GenerateInformation($"Unable to retrieve section: {section.SectionDefinition.GetName()}"); + continue; + } + + if (!(retrievedSection is CustomSectionDefinition customSectionDefinition)) + { + Engine.GenerateInformation($"Section: {section.SectionDefinition.GetName()} is not a custom section"); + continue; + } + + foreach (var fieldDescriptorId in section.SelectedFieldDescriptors.Select(x => x.ID)) + { + customSectionDefinition.RemoveFieldDescriptor(fieldDescriptorId); + customSectionDefinition = (CustomSectionDefinition)jobManager.SectionDefinitions.Update(customSectionDefinition); + Engine.GenerateInformation($"section definition {customSectionDefinition.Name} contains {customSectionDefinition.GetAllFieldDescriptors().Count} field descriptors"); + } + } + + GenerateUi(); + }; + } + + private void ListSectionDefinitions() + { + sections.Clear(); + sections.Add(new SectionDefinitionSection(helpers.EventManager.StaticEventSectionDefinition)); + sections.Add(new SectionDefinitionSection(helpers.EventManager.CustomEventSectionDefinition)); + sections.Add(new SectionDefinitionSection(helpers.EventManager.OrderSectionDefinition)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(titleLabel, ++row, 0); + + AddWidget(listSectionDefinitionsButton, ++row, 0); + + foreach (var section in sections) + { + AddSection(section, new SectionLayout(++row, 1)); + row += section.RowCount; + } + + AddWidget(removeSelectedFieldDescriptorsButton, ++row, 0); + } + + private sealed class SectionDefinitionSection : Section + { + private readonly SectionDefinition sectionDefinition; + private readonly List sections = new List(); + private readonly CheckBox selectCheckBox = new CheckBox { IsChecked = false }; + + public SectionDefinitionSection(SectionDefinition sectionDefinition) + { + this.sectionDefinition = sectionDefinition ?? throw new ArgumentNullException(nameof(sectionDefinition)); + + Initialize(); + GenerateUi(); + + if (!(sectionDefinition is CustomSectionDefinition)) + { + this.IsEnabled = false; + } + } + + private void Initialize() + { + foreach (var fieldDescriptor in sectionDefinition.GetAllFieldDescriptors()) + { + var fieldDescriptorSection = new FieldDescriptorSection(fieldDescriptor); + fieldDescriptorSection.SelectCheckBox.Changed += (s, e) => + { + selectCheckBox.IsChecked = sections.Where(x => x.IsEnabled).ToList().TrueForAll(x => x.SelectCheckBox.IsChecked); + }; + + sections.Add(fieldDescriptorSection); + } + + selectCheckBox.Changed += (s, e) => + { + foreach (var section in sections.Where(x => x.IsEnabled)) + { + section.SelectCheckBox.IsChecked = e.IsChecked; + } + }; + } + + public SectionDefinition SectionDefinition => sectionDefinition; + + public IEnumerable SelectedFieldDescriptors => sections.Where(x => x.SelectCheckBox.IsChecked).Select(x => x.FieldDescriptor); + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(new Label($"Section Definition {sectionDefinition.GetName()} [{sections.Count}]") { Style = TextStyle.Bold }, ++row, 0); + AddWidget(selectCheckBox, row, 1); + + foreach (var section in sections.OrderBy(x => x.Name)) + { + AddSection(section, new SectionLayout(++row, 0)); + row += section.RowCount; + } + } + } + + private sealed class FieldDescriptorSection : Section + { + private readonly FieldDescriptor fieldDescriptor; + + public FieldDescriptorSection(FieldDescriptor fieldDescriptor) + { + this.fieldDescriptor = fieldDescriptor ?? throw new ArgumentNullException(nameof(fieldDescriptor)); + + GenerateUi(); + + string[] fixedFieldDescriptors = new string[] { Event.OrderReservationFieldDescriptorName, Event.OrderIsIntegrationFieldDescriptorName }; + if (fixedFieldDescriptors.Contains(fieldDescriptor.Name) || Guid.TryParse(fieldDescriptor.Name, out _)) + { + SelectCheckBox.IsChecked = false; + this.IsEnabled = false; + } + } + + public string Name => fieldDescriptor.Name; + + public string ID => fieldDescriptor.ID.Id.ToString(); + + public FieldDescriptor FieldDescriptor => fieldDescriptor; + + public CheckBox SelectCheckBox { get; private set; } = new CheckBox { IsChecked = false }; + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(new Label($"{Name} [{ID}]"), ++row, 0); + AddWidget(SelectCheckBox, row, 1); + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Jobs/ReassignJobDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Jobs/ReassignJobDialog.cs new file mode 100644 index 0000000..efade37 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Jobs/ReassignJobDialog.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Skyline.DataMiner.Utils.InteractiveAutomationScript; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; +using Skyline.DataMiner.Library.Solutions.SRM; +using Skyline.DataMiner.Net.Messages.SLDataGateway; +using Skyline.DataMiner.Net.ResourceManager.Objects; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Jobs +{ + public class ReassignJobDialog : DebugDialog + { + private readonly Label titleLabel = new Label("Reassign Job") { Style = TextStyle.Heading }; + + private TextBox originalJobIdTextBox = new TextBox() { PlaceHolder = "old job id", Width = 300 }; + private TextBox newJobIdTextBox = new TextBox() { PlaceHolder = "new job id", Width = 300 }; + private Button retrieveReservationsButton = new Button("Retrieve Reservations with Old Job ID"); + private Button updateReservationsButton = new Button("Reassign Reservations"); + private Label foundReservationsLabel = new Label(String.Empty); + private TextBox reservationsTextBox = new TextBox { IsMultiline = true, Height = 400 }; + private TextBox statusTextBox = new TextBox { IsMultiline = true, Height = 400 }; + + private List reservations = new List(); + + public ReassignJobDialog(Helpers helpers) : base(helpers) + { + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + retrieveReservationsButton.Pressed += (s, e) => + { + reservations.Clear(); + reservationsTextBox.Text = String.Empty; + + if (!Guid.TryParse(originalJobIdTextBox.Text, out Guid originalJobId)) + { + foundReservationsLabel.Text = "Invalid GUID"; + return; + } + + reservations = SrmManagers.ResourceManager.GetReservationInstances(ReservationInstanceExposers.Properties.DictStringField(LiteOrder.PropertyNameEventId).Equal(originalJobIdTextBox.Text)).ToList(); + + foundReservationsLabel.Text = $"Found {reservations.Count} reservations"; + reservationsTextBox.Text = String.Join(Environment.NewLine, reservations.Select(x => $"{x.Name} [{x.ID}]")); + }; + + updateReservationsButton.Pressed += (s, e) => + { + if (!reservations.Any()) return; + if (!Guid.TryParse(newJobIdTextBox.Text, out Guid newJobId)) + { + statusTextBox.Text = "Invalid GUID"; + return; + } + + var newEvent = helpers.EventManager.GetEvent(newJobId); + if (newEvent == null) + { + statusTextBox.Text = $"Event with ID {newJobId} does not exist"; + return; + } + + statusTextBox.Text = $"Updating {reservations.Count} orders..."; + foreach (var reservation in reservations) + { + try + { + statusTextBox.Text += $"{Environment.NewLine}Moving order {reservation.Name}..."; + + var liteOrder = helpers.OrderManager.GetLiteOrder(reservation, true); + newEvent.AddOrUpdateOrder(liteOrder, helpers, true); + + statusTextBox.Text += $"{Environment.NewLine}Moving order succeeded"; + } + catch(Exception exception) + { + statusTextBox.Text += $"{Environment.NewLine}Moving order failed due to {exception}"; + } + } + + reservations.Clear(); + reservationsTextBox.Text = String.Empty; + }; + } + + private void GenerateUi() + { + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(titleLabel, ++row, 0); + + AddWidget(new Label("Old Job Id"), ++row, 0); + AddWidget(originalJobIdTextBox, row, 1); + + AddWidget(retrieveReservationsButton, ++row, 0, 1, 2); + + AddWidget(foundReservationsLabel, ++row, 0, 1, 2); + AddWidget(reservationsTextBox, ++row, 0, 1, 2); + + AddWidget(new Label("New Job Id"), ++row, 0); + AddWidget(newJobIdTextBox, row, 1); + + AddWidget(updateReservationsButton, ++row, 0, 1, 2); + + AddWidget(statusTextBox, ++row, 0, 1, 2); + + AddResponseSections(++row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/LogCollector/LogCollectorDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/LogCollector/LogCollectorDialog.cs new file mode 100644 index 0000000..5ef179b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/LogCollector/LogCollectorDialog.cs @@ -0,0 +1,92 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.LogCollector +{ + using System; + using System.Collections.Generic; + using System.Text; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class LogCollectorDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label runLogCollectorLabel = new Label("Run Log Collector") { Style = TextStyle.Heading }; + + private readonly Button getMostRecentLogCollectionTimeStampButton = new Button("Get Most Recent Log Collection Timestamp"); + private readonly Label mostRecentLogCollectionTimestampLabel = new Label(String.Empty); + + private readonly Button runOnThisDmaButton = new Button("Run sync on this DMA"); + private readonly Button runAsyncOnMasterDmaButton = new Button("Run async on this and master DMA"); + + private readonly List responseSections = new List(); + + public LogCollectorDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Run Log Collector"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void Initialize() + { + getMostRecentLogCollectionTimeStampButton.Pressed += (s, e) => mostRecentLogCollectionTimestampLabel.Text = $"{helpers.LogCollectorHelper.GetMostRecentLogCollectionTimeStamp()} on current DMA {Automation.Engine.SLNetRaw.ServerDetails.AgentID}"; + + runOnThisDmaButton.Pressed += RunOnThisDmaButton_Pressed; + + runAsyncOnMasterDmaButton.Pressed += RunAsyncOnMasterDmaButton_Pressed; + } + + private void RunAsyncOnMasterDmaButton_Pressed(object sender, EventArgs e) + { + helpers.LogCollectorHelper.RunLogCollectorAsync(); + + ShowRequestResult($"Log Collection at {DateTime.Now}", "Triggered async"); + } + + private void RunOnThisDmaButton_Pressed(object sender, EventArgs e) + { + helpers.LogCollectorHelper.RunLogCollectorOnThisDma(); + + ShowRequestResult($"Log Collection at {DateTime.Now}", "Succeeded"); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(runLogCollectorLabel, ++row, 0, 1, 5); + + AddWidget(getMostRecentLogCollectionTimeStampButton, ++row, 0); + AddWidget(mostRecentLogCollectionTimestampLabel, row, 1, 1, 4); + + AddWidget(runOnThisDmaButton, ++row, 0); + AddWidget(runAsyncOnMasterDmaButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Metrics/MetricsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Metrics/MetricsDialog.cs new file mode 100644 index 0000000..e09de03 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Metrics/MetricsDialog.cs @@ -0,0 +1,197 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Metrics +{ + using System; + using System.Linq; + using System.Collections.Generic; + using Newtonsoft.Json; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Metrics; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Metrics.MethodCalls; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using System.IO; + + public class MetricsDialog : Dialog + { + private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Serialize, + Formatting = Formatting.Indented + }; + + private const string MetricLoggingDirectory = @"C:\Skyline_Data\MetricLogging\"; + + private readonly Helpers helpers; + private readonly MetricAggregator metricAggregator; + + private readonly Label metricsPerOrderLabel = new Label("Metrics per Order") { Style = TextStyle.Heading }; + private readonly Label orderIdLabel = new Label("Order ID"); + private readonly TextBox orderIdTextBox = new TextBox(); + private readonly Button getMetricsButton = new Button("Get Metrics") { Width = 200 }; + private readonly Button enterCurrentIdButton = new Button("Enter Current ID") { Width = 250 }; + + private readonly Label dataMinerInterfaceMetricsLabel = new Label("DataMiner Interface Metrics") { Style = TextStyle.Heading }; + private readonly Button getAllDataMinerInterfaceMetricsButton = new Button("Get All DataMiner Interface Metrics") { Width = 250 }; + + private readonly Button getDataMinerInterfaceMethodCallMetricSummaryButton = new Button("Get Metric Summary for"); + private readonly DropDown dataMinerInterfaceMethodsDropDown = new DropDown(DataMinerInterface.GetWrappedMethods().Select(wm => wm.ToString())); + + private readonly Label performanceLabel = new Label("Performance") { Style= TextStyle.Heading }; + private readonly Button getPerformanceDropTimestampsButton = new Button("Get Performance Drop Timestamps"); + private readonly Button getScriptExecutionTimestampsButton = new Button("Get Script Execution Timestamps"); + + private readonly Label filtersLabel = new Label("Filters") { Style = TextStyle.Heading }; + private readonly Label startLabel = new Label("Start"); + private readonly DateTimePicker startDateTimePicker = new DateTimePicker(DateTime.Now.AddDays(-1)); + private readonly Label endLabel = new Label("End"); + private readonly DateTimePicker endDateTimePicker = new DateTimePicker(DateTime.Now); + private readonly CheckBox limitAmountOfFilesToProcessCheckBox = new CheckBox("Limit Amount of Files to Process to") { IsChecked = true }; + private readonly Numeric maxAmountOfFilesToProcessNumeric = new Numeric(50) { Minimum = 1, StepSize = 1, Decimals = 0 }; + private readonly Label totalAmountOfFilesLabel = new Label(String.Empty); + + private readonly List responseSections = new List(); + + public MetricsDialog(Helpers helpers) : base(helpers.Engine) + { + this.helpers = helpers; + this.metricAggregator = new MetricAggregator(helpers); + + Title = "Metrics"; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private int MaxAmountOfFilesToProcess => limitAmountOfFilesToProcessCheckBox.IsChecked ? (int)maxAmountOfFilesToProcessNumeric.Value : Int32.MaxValue; + + private void Initialize() + { + var numberOfFiles = Directory.GetFiles(MetricLoggingDirectory).Length; + totalAmountOfFilesLabel.Text = $"Out of {numberOfFiles} Files"; + + limitAmountOfFilesToProcessCheckBox.Changed += (s, e) => maxAmountOfFilesToProcessNumeric.IsEnabled = limitAmountOfFilesToProcessCheckBox.IsChecked; + + getMetricsButton.Pressed += GetMetricsButtonPressed; + + enterCurrentIdButton.Pressed += (sender, args) => orderIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + + getAllDataMinerInterfaceMetricsButton.Pressed += GetAllDataMinerInterfaceMetricsButton_Pressed; + + getDataMinerInterfaceMethodCallMetricSummaryButton.Pressed += GetDataMinerInterfaceMethodCallMetricSummaryButton_Pressed; + + getPerformanceDropTimestampsButton.Pressed += GetPerformanceDropTimestampsButton_Pressed; + + getScriptExecutionTimestampsButton.Pressed += GetScriptExecutionTimestampsButton_Pressed; + } + + private void GetScriptExecutionTimestampsButton_Pressed(object sender, EventArgs e) + { + var summary = metricAggregator.GetMetricsSummary(MetricLoggingDirectory, out var filesToRemove, out var amountOfProcessedFiles, startDateTimePicker.DateTime, endDateTimePicker.DateTime, MaxAmountOfFilesToProcess); + + ShowRequestResult($"Script Metric Summaries (taken from {amountOfProcessedFiles} files)", string.Join("\n", summary.ScriptMetricSummaries.Select(x => JsonConvert.SerializeObject(x, JsonSerializerSettings)))); + } + + private void GetPerformanceDropTimestampsButton_Pressed(object sender, EventArgs e) + { + var timestamps = metricAggregator.GetPerformanceDropTimeStamps(MetricLoggingDirectory, out var processedFiles, MaxAmountOfFilesToProcess).OrderBy(x => x); + + ShowRequestResult($"Performance Drop Timestamps (taken from {processedFiles.Count} files)", string.Join("\n", timestamps)); + } + + private void GetDataMinerInterfaceMethodCallMetricSummaryButton_Pressed(object sender, EventArgs e) + { + var summary = metricAggregator.GetDataMinerInterfaceMethodCallSummary(MetricLoggingDirectory, dataMinerInterfaceMethodsDropDown.Selected, out var processedFiles, MaxAmountOfFilesToProcess); + + ShowRequestResult($"{dataMinerInterfaceMethodsDropDown.Selected} Summary (taken from {processedFiles.Count} files)", JsonConvert.SerializeObject(summary, JsonSerializerSettings)); + } + + private void GetAllDataMinerInterfaceMetricsButton_Pressed(object sender, EventArgs e) + { + var summary = metricAggregator.GetMetricsSummary(MetricLoggingDirectory, out var filesToRemove, out var amountOfProcessedFiles, startDateTimePicker.DateTime, endDateTimePicker.DateTime, MaxAmountOfFilesToProcess); + + ShowRequestResult($"All DataMiner Interface Summaries (taken from {amountOfProcessedFiles} files)", JsonConvert.SerializeObject(summary.DataMinerInterfaceMethodCallSummaries, JsonSerializerSettings)); + } + + private void GetMetricsButtonPressed(object sender, EventArgs e) + { + var scriptExecutionMetrics = metricAggregator.ReadMetricFile($"{MetricLoggingDirectory}{orderIdTextBox.Text}.txt"); + + foreach (var scriptExecutionMetric in scriptExecutionMetrics) + { + ShowRequestResult($"Script Execution {scriptExecutionMetric.ScriptName} at {scriptExecutionMetric.StartTime} by {scriptExecutionMetric.UserDisplayName} on DMA {scriptExecutionMetric.DmaId}", JsonConvert.SerializeObject(scriptExecutionMetric, JsonSerializerSettings)); + } + + var scriptExecutionMetricSummaries = metricAggregator.GetScriptExecutionMetricSummaries(scriptExecutionMetrics.ToArray()); + + foreach (var summary in scriptExecutionMetricSummaries) + { + ShowRequestResult($"Script Execution Summary {summary.ScriptName}", $@"Metrics are valid = {summary.ScriptMetricsAreValid}\nTotal Execution Time = {summary.ExecutionTime}\nMethod Call Summaries:\n{string.Join("\n", JsonConvert.SerializeObject(summary.MethodCallSummaries, JsonSerializerSettings))}"); + } + + var summaries = MetricAggregator.GetDataMinerInterfaceMetricSummaries(scriptExecutionMetricSummaries.ToArray()); + + ShowRequestResult("DataMiner Interface Summaries", JsonConvert.SerializeObject(summaries, JsonSerializerSettings)); + } + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(metricsPerOrderLabel, ++row, 0, 1, 5); + AddWidget(orderIdLabel, ++row, 0, 1, 2); + AddWidget(orderIdTextBox, row, 2, 1, 2); + AddWidget(getMetricsButton, row, 4); + AddWidget(enterCurrentIdButton, ++row, 2, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + AddWidget(dataMinerInterfaceMetricsLabel, ++row, 0, 1, 5); + AddWidget(getAllDataMinerInterfaceMetricsButton, ++row, 2, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + AddWidget(getDataMinerInterfaceMethodCallMetricSummaryButton, ++row, 2); + AddWidget(dataMinerInterfaceMethodsDropDown, row, 3); + + AddWidget(new WhiteSpace(), ++row, 1); + + AddWidget(performanceLabel, ++row, 0, 1, 5); + AddWidget(getPerformanceDropTimestampsButton, ++row, 2); + AddWidget(getScriptExecutionTimestampsButton, ++row, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + AddWidget(filtersLabel, ++row, 0, 1, 5); + AddWidget(limitAmountOfFilesToProcessCheckBox, ++row, 2); + AddWidget(maxAmountOfFilesToProcessNumeric, row, 3); + AddWidget(totalAmountOfFilesLabel, row, 4); + AddWidget(startLabel, ++row, 0, 1, 2); + AddWidget(startDateTimePicker, row, 2); + AddWidget(endLabel, ++row, 0, 1, 2); + AddWidget(endDateTimePicker, row, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLive/GetNonLiveOrdersSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLive/GetNonLiveOrdersSection.cs new file mode 100644 index 0000000..5128105 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLive/GetNonLiveOrdersSection.cs @@ -0,0 +1,94 @@ +namespace Debug_2.Debug.NonLive +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Debug_2.Debug.Tickets; + using Skyline.DataMiner.DeveloperCommunityLibrary.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class GetNonLiveOrdersSection : YleSection + { + private readonly GetTicketSection getTicketSection; + private readonly HowToSection howToSection; + + private readonly Label additionalFilteringLabel = new Label("Additional filtering") { Style = TextStyle.Title }; + + private readonly CheckBox withoutDeleteTasksCheckBox = new CheckBox("Only Non-Live Orders without delete tasks"); + + private readonly Button getSelectedNonLiveOrdersButton = new Button("Get Selected Non-Live Orders") { Style = ButtonStyle.CallToAction }; + private readonly CollapseButton showSelectedNonLiveOrdersButton; + private readonly TextBox selectedNonLiveOrdersTextBox = new TextBox { IsMultiline = true, MinWidth = 500 }; + + public GetNonLiveOrdersSection(Helpers helpers) : base(helpers) + { + howToSection = new HowToSection(helpers); + + getTicketSection = new GetTicketSection(helpers); + + getTicketSection.RegenerateUiRequired += HandleRegenerateUiRequired; + getTicketSection.UiEnabledStateChangeRequired += HandleUiEnabledStateChangeRequired; + + getSelectedNonLiveOrdersButton.Pressed += GetSelectedNonLiveOrdersButton_Pressed; + + showSelectedNonLiveOrdersButton = new CollapseButton(selectedNonLiveOrdersTextBox.Yield(), true) { CollapseText = "Hide Selected Non-Live Orders", ExpandText = "Show Selected Non-Live Orders" }; + + GenerateUi(); + } + + public IEnumerable SelectedNonLiveOrders { get; private set; } = new List(); + + public override void RegenerateUi() + { + Clear(); + getTicketSection.RegenerateUi(); + GenerateUi(); + } + + protected override void HandleVisibilityAndEnabledUpdate() + { + getTicketSection.IsEnabled = IsEnabled; + } + + private void GetSelectedNonLiveOrdersButton_Pressed(object sender, EventArgs e) + { + using (UiDisabler.StartNew(this)) + { + var nonLiveOrders = getTicketSection.SelectedTickets.Select(t => NonLiveOrderManager.GetNonLiveOrder(t)).ToList(); + + if (withoutDeleteTasksCheckBox.IsChecked) + { + nonLiveOrders = nonLiveOrders.Where(nlo => !helpers.NonLiveUserTaskManager.GetNonLiveUserTasks(nlo).Any()).ToList(); + } + + SelectedNonLiveOrders = nonLiveOrders; + + selectedNonLiveOrdersTextBox.Text = string.Join("\n", SelectedNonLiveOrders.Select(nlo => nlo.OrderDescription)); + } + } + + private void GenerateUi() + { + int row = -1; + + row++; + + AddSection(getTicketSection, new SectionLayout(row, 0)); + + AddSection(howToSection, new SectionLayout(row, getTicketSection.ColumnCount + 1)); + + row += new[] { getTicketSection.RowCount, howToSection.RowCount }.Max(); + + AddWidget(additionalFilteringLabel, ++row, 0, 1, 5); + + AddWidget(withoutDeleteTasksCheckBox, ++row, 0); + + AddWidget(getSelectedNonLiveOrdersButton, ++row, 0); + AddWidget(showSelectedNonLiveOrdersButton, row, 1); + AddWidget(selectedNonLiveOrdersTextBox, ++row, 1); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLive/HowToSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLive/HowToSection.cs new file mode 100644 index 0000000..3851c9d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLive/HowToSection.cs @@ -0,0 +1,51 @@ +namespace Debug_2.Debug.NonLive +{ + using System; + using System.Linq; + using Skyline.DataMiner.DeveloperCommunityLibrary.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class HowToSection : YleSection + { + private readonly YleCollapseButton howToCollapseButton; + private readonly Label howToLabel = new Label("How To") { Style = TextStyle.Title }; + + private readonly YleCollapseButton howToRetrieveTicketsForCertainNonLiveOrderTypeCollapseButton; + private readonly Label howToRetrieveTicketsForCertainNonLiveOrderTypeHeaderLabel = new Label("Retrieve tickets for certain Non-Live order type") { Style = TextStyle.Heading }; + private readonly Label howToRetrieveTicketsForCertainNonLiveOrderTypeTextLabel = new Label($"1. Add an enum property value filter\n2. As property name, fill in 'Type'\n3. As property values, fill in one of these combinations:\n{string.Join("\n", Enum.GetValues(typeof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.Type)).Cast().Select(e => $"{e} , {(int)e}"))}"); + + public HowToSection(Helpers helpers) : base(helpers) + { + howToRetrieveTicketsForCertainNonLiveOrderTypeCollapseButton = new YleCollapseButton(howToRetrieveTicketsForCertainNonLiveOrderTypeTextLabel.Yield(), true); + + howToCollapseButton = new YleCollapseButton(new Widget[] { howToRetrieveTicketsForCertainNonLiveOrderTypeCollapseButton, howToRetrieveTicketsForCertainNonLiveOrderTypeHeaderLabel }, true); + + GenerateUi(); + } + + public override void RegenerateUi() + { + Clear(); + GenerateUi(); + } + + protected override void HandleVisibilityAndEnabledUpdate() + { + // no actions required + } + + private void GenerateUi() + { + int row = -1; + + AddWidget(howToCollapseButton, ++row, 0); + AddWidget(howToLabel, row, 1, 1, 5); + + AddWidget(howToRetrieveTicketsForCertainNonLiveOrderTypeCollapseButton, ++row, 1); + AddWidget(howToRetrieveTicketsForCertainNonLiveOrderTypeHeaderLabel, row, 2, 1, 5); + AddWidget(howToRetrieveTicketsForCertainNonLiveOrderTypeTextLabel, ++row, 2, 9, 1, verticalAlignment: VerticalAlignment.Top); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLive/NonLiveOrdersDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLive/NonLiveOrdersDialog.cs new file mode 100644 index 0000000..25f2233 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLive/NonLiveOrdersDialog.cs @@ -0,0 +1,81 @@ +namespace Debug_2.Debug.NonLive +{ + using System; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class NonLiveOrdersDialog : DebugDialog + { + private readonly Label actionsLabel = new Label("Actions") { Style = TextStyle.Title }; + + private readonly GetNonLiveOrdersSection getNonLiveOrdersSection; + + private readonly YleButton addOrUpdateUserTasksButton = new YleButton("Add or Update User Tasks") { Style = ButtonStyle.CallToAction }; + + public NonLiveOrdersDialog(Helpers helpers) : base(helpers) + { + Title = "Non-Live Orders"; + + getNonLiveOrdersSection = new GetNonLiveOrdersSection(helpers); + + getNonLiveOrdersSection.RegenerateUiRequired += (o, e) => RegenerateUi(); + getNonLiveOrdersSection.UiEnabledStateChangeRequired += Section_UiEnabledStateChangeRequired; + + addOrUpdateUserTasksButton.Pressed += AddOrUpdateUserTasksButton_Pressed; + + GenerateUi(); + } + + private void AddOrUpdateUserTasksButton_Pressed(object sender, YleValueWidgetChangedEventArgs e) + { + try + { + var nonLiveOrders = getNonLiveOrdersSection.SelectedNonLiveOrders; + + foreach (var nonLiveOrder in nonLiveOrders) + { + helpers.NonLiveUserTaskManager.AddOrUpdateUserTasks(nonLiveOrder); + } + + ShowRequestResult("Added or Updated user tasks"); + RegenerateUi(); + } + catch(Exception ex) + { + ShowRequestResult("Exception occurred", ex.ToString()); + RegenerateUi(); + } + } + + private void RegenerateUi() + { + Clear(); + getNonLiveOrdersSection.RegenerateUi(); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 5); + + AddSection(getNonLiveOrdersSection, ++row, 0); + + row += getNonLiveOrdersSection.RowCount; + + AddWidget(actionsLabel, ++row, 0, 1, 5); + AddWidget(addOrUpdateUserTasksButton, ++row, 0); + + foreach (var responseSection in responseSections) + { + AddSection(responseSection, ++row, 0); + row += responseSection.RowCount; + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLiveUserTasks/UpdateNonLiveOrderUserTasksDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLiveUserTasks/UpdateNonLiveOrderUserTasksDialog.cs new file mode 100644 index 0000000..2fc398b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/NonLiveUserTasks/UpdateNonLiveOrderUserTasksDialog.cs @@ -0,0 +1,135 @@ +namespace Debug_2.Debug.NonLiveUserTasks +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Debug_2.Debug.Tickets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.Ingest; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.Project; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.NonLiveUserTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class UpdateNonLiveOrderUserTasksDialog : DebugDialog + { + private readonly Label header = new Label("Update Non-Live Order User Tasks") { Style = TextStyle.Title }; + + private readonly GetTicketSection getTicketSection; + + private readonly Button updateUserTasksAndPropertiesForCompletedNonLiveOrders = new Button("Update user tasks and properties for completed non-live orders"); + private readonly Label explanationLabel = new Label("Feature created for DCP195594"); + + private readonly Button updateSpecificUserTaskValuesButton = new Button("Update certain user task values"); + private readonly Label updateSpecificUserTaskValuesLabel = new Label("Feature created for DCP212455"); + + public UpdateNonLiveOrderUserTasksDialog(Helpers helpers) : base(helpers) + { + getTicketSection = new GetTicketSection(helpers); + + getTicketSection.RegenerateUiRequired += (s, e) => + { + getTicketSection.RegenerateUi(); + GenerateUi(); + }; + + getTicketSection.AddPropertyExistenceFilter("Non Live Order Name", true); + + getTicketSection.UiEnabledStateChangeRequired += Section_UiEnabledStateChangeRequired; + + updateUserTasksAndPropertiesForCompletedNonLiveOrders.Pressed += UpdateUserTasksAndPropertiesForCompletedNonLiveOrders_Pressed; + + updateSpecificUserTaskValuesButton.Pressed += UpdateSpecificUserTaskValuesButton_Pressed; + + GenerateUi(); + } + + private void UpdateSpecificUserTaskValuesButton_Pressed(object sender, EventArgs e) + { + using (UiDisabler.StartNew(this)) + { + var nonLiveUserTaskTickets = getTicketSection.SelectedTickets.ToList(); + + var userTasks = helpers.NonLiveUserTaskManager.CreateNonLiveUserTasks(nonLiveUserTaskTickets); + + var notFoundNonLiveOrders = new List(); + var succeededUpdatedUserTasks = new List(); + + foreach (var userTask in userTasks) + { + if (!Int32.TryParse(userTask.IngestExportForeignKey.Split('/').FirstOrDefault(), out int nonLiveOrderAgentId) || !Int32.TryParse(userTask.IngestExportForeignKey.Split('/').LastOrDefault(), out int nonLiveOrderTicketId) || !helpers.NonLiveOrderManager.TryGetNonLiveOrder(nonLiveOrderAgentId, nonLiveOrderTicketId, out var nonLiveOrder)) + { + notFoundNonLiveOrders.Add(userTask.IngestExportForeignKey); + continue; + } + + userTask.DeadlineDate = nonLiveOrder.Deadline; + + if (nonLiveOrder is Project projectOrder) + { + userTask.DeliveryDate = projectOrder.MaterialDeliveryTime; + } + else if (nonLiveOrder is Ingest ingestOrder) + { + userTask.DeliveryDate = ingestOrder.DeliveryTime; + } + + userTask.AddOrUpdate(helpers); + + succeededUpdatedUserTasks.Add(userTask); + } + + ShowRequestResult($"Updated deadline and delivery time on non-live user tasks", $"Updated deadline and delivery time on non-live user tasks:\n{string.Join("\n", succeededUpdatedUserTasks.Select(u => u.ID))}"); + ShowRequestResult($"Unable to find Non-Live orders for user tasks", string.Join("\n", notFoundNonLiveOrders)); + GenerateUi(); + } + } + + private void UpdateUserTasksAndPropertiesForCompletedNonLiveOrders_Pressed(object sender, EventArgs e) + { + var completedNonLiveOrders = helpers.NonLiveOrderManager.GetAllCompletedNonLiveOrders(); + + foreach (var nonLiveOrder in completedNonLiveOrders) + { + helpers.NonLiveUserTaskManager.AddOrUpdateUserTasks(nonLiveOrder); + } + + ShowRequestResult($"Updated user tasks for {completedNonLiveOrders.Count()} completed non-live orders", string.Join("\n", completedNonLiveOrders.Select(u => $"{u.ShortDescription}"))); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(header, ++row, 0, 1, 5); + + AddSection(getTicketSection, ++row, 0); + row += getTicketSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + + //AddWidget(updateUserTasksAndPropertiesForCompletedNonLiveOrders, ++row, 0); + //AddWidget(explanationLabel, row, 1); + + AddWidget(updateSpecificUserTaskValuesButton, ++row, 0); + AddWidget(updateSpecificUserTaskValuesLabel, row, 1); + + AddResponseSections(row); + } + + protected override void HandleEnabledUpdate() + { + base.HandleEnabledUpdate(); + + getTicketSection.IsEnabled = IsEnabled; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/AutoUpdateOrderPropertiesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/AutoUpdateOrderPropertiesDialog.cs new file mode 100644 index 0000000..12eab00 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/AutoUpdateOrderPropertiesDialog.cs @@ -0,0 +1,103 @@ +namespace Debug_2.Debug.Orders +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Debug_2.Debug.Reservations; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class AutoUpdateOrderPropertiesDialog : DebugDialog + { + private readonly Label headerLabel = new Label("Automatically Update Order Properties") { Style = TextStyle.Title }; + + private readonly List orderBookingManagerProperties; + + private readonly GetReservationsSection getReservationsSection; + + private readonly Label propertiesToUpdateLabel = new Label("Properties to Update"); + private readonly CheckBoxList propertiesToUpdateCheckBoxList; + + private readonly Button updatePropertiesButton = new Button("Update selected properties for selected orders") { Style = ButtonStyle.CallToAction }; + + public AutoUpdateOrderPropertiesDialog(Helpers helpers) : base(helpers) + { + Title = "Update Order Properties"; + + getReservationsSection = new GetReservationsSection(helpers); + + getReservationsSection.AddDefaultPropertyFilter("Type", "Video"); // to ensure we are retrieving order reservations + getReservationsSection.RegenerateUiRequired += (o, e) => RegenerateUi(); + + var bookingManagerElement = helpers.Engine.FindElement("Order Booking Manager") ?? throw new NotFoundException("Could not find Order Booking Manager element"); + var bookingManager = new BookingManager((Engine)helpers.Engine, bookingManagerElement) { CustomProperties = true }; + + orderBookingManagerProperties = bookingManager.Properties.ToList(); + + propertiesToUpdateCheckBoxList = new CheckBoxList(orderBookingManagerProperties.Select(p => p.Name).ToList()); + + updatePropertiesButton.Pressed += UpdatePropertiesButton_Pressed; + + GenerateUi(); + } + + private void RegenerateUi() + { + getReservationsSection.RegenerateUi(); + GenerateUi(); + } + + private void UpdatePropertiesButton_Pressed(object sender, EventArgs e) + { + using (UiDisabler.StartNew(this)) + { + var enabledProperties = orderBookingManagerProperties.Where(p => propertiesToUpdateCheckBoxList.Checked.Contains(p.Name)).ToList(); + + var orders = getReservationsSection.SelectedReservations.Select(r => helpers.OrderManager.GetOrder(r)).ToList(); + + foreach (var order in orders) + { + var propertiesToUpdate = order.GetPropertiesFromBookingManager(helpers, enabledProperties).ToDictionary(p => p.Name, p => (object)p.Value); + + order.TryUpdateCustomProperties(helpers, propertiesToUpdate); + } + + ShowRequestResult("Updated order properties", $"Updated properties\n{string.Join(", ", enabledProperties.Select(p => p.Name))}\nfor orders\n{string.Join("\n", orders.Select(o => o.Name))}"); + GenerateUi(); + } + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(headerLabel, ++row, 0, 1, 3); + + AddSection(getReservationsSection, ++row, 0); + row += getReservationsSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(propertiesToUpdateLabel, ++row, 0, verticalAlignment: VerticalAlignment.Top); + AddWidget(propertiesToUpdateCheckBoxList, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(updatePropertiesButton, ++row, 0, 1, 3); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/DeleteOrdersDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/DeleteOrdersDialog.cs new file mode 100644 index 0000000..1543e43 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/DeleteOrdersDialog.cs @@ -0,0 +1,330 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Orders +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Debug_2.Debug.Reservations; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net; + using Skyline.DataMiner.Net.Jobs; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.Advanced; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Net.Ticketing; + + public class DeleteOrdersDialog : DebugDialog + { + private readonly Label deleteOrdersLabel = new Label("Delete Orders") { Style = TextStyle.Heading }; + + private readonly GetReservationsSection getOrderReservationsSection; + + private readonly Button deleteOrdersButton = new Button("Delete Orders") { Width = 200 }; + + public DeleteOrdersDialog(Helpers helpers) : base(helpers) + { + Title = "Delete Orders"; + + getOrderReservationsSection = new GetReservationsSection(helpers); + + Initialize(); + GenerateUi(); + + getOrderReservationsSection.AddDefaultPropertyFilter("Type", "Video"); + } + + private void Initialize() + { + getOrderReservationsSection.RegenerateUiRequired += GetOrderReservationsSection_RegenerateUi; + + deleteOrdersButton.Pressed += DeleteOrdersButton_Pressed; + } + + private void GetOrderReservationsSection_RegenerateUi(object sender, EventArgs e) + { + getOrderReservationsSection.RegenerateUi(); + GenerateUi(); + } + + private void DeleteOrdersButton_Pressed(object sender, EventArgs e) + { + using (UiDisabler.StartNew(this)) + { + var orderReservations = getOrderReservationsSection.SelectedReservations.Where(r => r.Properties.Dictionary.TryGetValue("Type", out var typeValue) && typeValue.Equals("Video")); + + var sb = new StringBuilder(); + + var ticketingHelper = new TicketingGatewayHelper { HandleEventsAsync = false }; + ticketingHelper.RequestResponseEvent += (s, args) => args.responseMessage = Automation.Engine.SLNet.SendSingleResponseMessage(args.requestMessage); + + var resourceManagerHelper = new ResourceManagerHelper(); + resourceManagerHelper.RequestResponseEvent += (s, ea) => ea.responseMessage = Automation.Engine.SLNet.SendSingleResponseMessage(ea.requestMessage); + + var serviceHelper = new ServiceManagerHelper(); + serviceHelper.RequestResponseEvent += (s, args) => args.responseMessage = Automation.Engine.SLNet.SendSingleResponseMessage(args.requestMessage); + + try + { + var serviceReservationsToRemove = new HashSet(); + var servicesToRemove = new List(); + var ticketsToRemove = new List(); + + CollectThingsToDelete(orderReservations, sb, ticketingHelper, serviceReservationsToRemove, servicesToRemove, ticketsToRemove); + + var removedOrderReservations = RemoveReservationInstances(orderReservations); + var removedServiceReservations = RemoveReservationInstances(serviceReservationsToRemove); + + RemoveOrdersFromEvent(removedOrderReservations); + RemoveOrdersFromOrderManager(removedOrderReservations); + RemoveServices(servicesToRemove); + RemoveTickets(ticketingHelper, ticketsToRemove); + + sb.AppendLine($"Removed reservations:"); + foreach (var removedReservation in removedOrderReservations.Union(removedServiceReservations)) + { + sb.AppendLine($"{removedReservation.Name}({removedReservation.ID})"); + } + + ShowRequestResult($"Successfully deleted orders {DateTime.Now}", sb.ToString()); + } + catch (Exception ex) + { + sb.AppendLine(ex.ToString()); + ShowRequestResult("Exception while deleting", sb.ToString()); + } + } + } + + private void CollectThingsToDelete(IEnumerable orderReservations, StringBuilder sb, TicketingGatewayHelper ticketingHelper, HashSet serviceReservationsToRemove, List servicesToRemove, List ticketsToRemove) + { + foreach (var orderReservationInstance in orderReservations.Cast()) + { + var orderId = orderReservationInstance.ID; + + try + { + if (orderReservationInstance.ServiceID != null) servicesToRemove.Add(orderReservationInstance.ServiceID); + + foreach (var resourceUsage in orderReservationInstance.ResourcesInReservationInstance) + { + var serviceReservationInstance = DataMinerInterface.ResourceManager.GetReservationInstance(helpers, resourceUsage.GUID) as ServiceReservationInstance ?? throw new ServiceNotFoundException(resourceUsage.GUID); + serviceReservationsToRemove.Add(serviceReservationInstance); + + if (serviceReservationInstance.ServiceID != null) servicesToRemove.Add(serviceReservationInstance.ServiceID); + + var userTaskTickets = ticketingHelper.GetTickets(filter: TicketingExposers.CustomTicketFields.DictStringField("Service ID").Equal(resourceUsage.GUID.ToString())); + ticketsToRemove.AddRange(userTaskTickets); + } + } + catch (Exception ex1) + { + sb.AppendLine($"Exception while finding order ID {orderId} and its contributing resources: {ex1}"); + } + + try + { + var reservationsLinkedToOrder = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, ReservationInstanceExposers.Properties.DictStringField(ServicePropertyNames.OrderIdsPropertyName).Equal(orderId.ToString())); + + foreach (var serviceReservation in reservationsLinkedToOrder) + { + serviceReservationsToRemove.Add(serviceReservation); + } + } + catch (Exception ex2) + { + sb.AppendLine($"Exception while finding reservations with OrderIds property equal to {orderId}: {ex2}"); + } + } + } + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private List RemoveReservationInstances(IEnumerable reservationInstances) + { + var removedReservations = new List(); + try + { + DataMinerInterface.ResourceManager.RemoveReservationInstances(helpers, reservationInstances.ToArray()); + removedReservations.AddRange(reservationInstances); + } + catch (Exception e) + { + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveReservationInstances), $"Exception removing reservations: {e}"); + } + + return removedReservations; + } + + private void RemoveServices(List services) + { + foreach (var serviceId in services) + { + try + { + helpers.Engine.SendSLNetMessage(new SetDataMinerInfoMessage + { + Uia1 = new UIA(new[] { (uint)serviceId.DataMinerID, (uint)serviceId.SID }), + What = 74 + }); + } + catch (Exception e) + { + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveServices), $"Exception removing service {serviceId}: {e}"); + } + } + } + + private void RemoveTickets(TicketingGatewayHelper ticketingHelper, List tickets) + { + if (tickets.Any()) + { + try + { + if (!ticketingHelper.RemoveTickets(out var error, tickets.ToArray())) + { + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveTickets), String.Format("Error removing tickets: {0}", error)); + } + } + catch (Exception e) + { + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveTickets), String.Format("Exception removing tickets: {0}", e)); + } + } + } + + private void RemoveOrdersFromEvent(List orderReservationInstances) + { + var helper = new JobManagerHelper(m => helpers.Engine.SendSLNetMessages(m)); + + foreach (var orderReservationInstance in orderReservationInstances) + { + var eventIdPropertyValue = orderReservationInstance.Properties.FirstOrDefault(p => p.Key == "EventId").Value; + if (eventIdPropertyValue == null) + { + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveOrdersFromEvent), "Order EventId property is null"); + continue; + } + + if (!Guid.TryParse(Convert.ToString(eventIdPropertyValue), out var eventId)) + { + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveOrdersFromEvent), String.Format("Order EventId property is not a valid Guid: {0}", eventIdPropertyValue)); + continue; + } + + if (!TryGetJob(helper, eventId, out var job)) + { + continue; + } + + TryRemoveOrderSection(helper, orderReservationInstance, eventId, job); + } + } + + private bool TryGetJob(JobManagerHelper helper, Guid eventId, out Job job) + { + try + { + job = helper.Jobs.Read(JobExposers.ID.Equal(eventId)).FirstOrDefault(); + if (job == null) + { + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveOrdersFromEvent), String.Format("Job {0} not found", eventId)); + return false; + } + + return true; + } + catch (Exception e) + { + job = null; + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveOrdersFromEvent), String.Format("Exception retrieving job '{0}': {1}", eventId, e)); + return false; + } + } + + private void TryRemoveOrderSection(JobManagerHelper helper, ReservationInstance orderReservationInstance, Guid eventId, Job job) + { + try + { + var sectionsToRemove = new List(); + foreach (var section in job.Sections) + { + foreach (var fieldValue in section.FieldValues) + { + bool sectionContainsOrderId = fieldValue.Value.Type == typeof(Guid); + if (sectionContainsOrderId && (Guid)fieldValue.Value.Value == orderReservationInstance.ID) + { + sectionsToRemove.Add(section); + + } + } + } + + foreach (var sectionToRemove in sectionsToRemove) + { + job.Sections.Remove(sectionToRemove); + } + + helper.Jobs.Update(job); + } + catch (Exception e) + { + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveOrdersFromEvent), String.Format("Exception removing order '{0}' from job '{1}': {2}", orderReservationInstance.ID, eventId, e)); + } + } + + private void RemoveOrdersFromOrderManager(List orderReservationInstances) + { + var orderManagerElement = helpers.Engine.FindElementsByProtocol("Finnish Broadcasting Company Order Manager").FirstOrDefault(); + + foreach (var orderReservationInstance in orderReservationInstances) + { + try + { + orderManagerElement.SetParameterByPrimaryKey(2006, orderReservationInstance.ID.ToString(), "Delete"); + } + catch (Exception e) + { + helpers.Log(nameof(DeleteOrdersDialog), nameof(RemoveOrdersFromOrderManager), String.Format("Exception removing order '{0}' from order manager element: {1}", orderReservationInstance.ID, e)); + } + } + + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(deleteOrdersLabel, ++row, 0, 1, 5); + + AddSection(getOrderReservationsSection, ++row, 0); + row += getOrderReservationsSection.RowCount; + + AddWidget(deleteOrdersButton, ++row, 0, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/OrderHistoryDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/OrderHistoryDialog.cs new file mode 100644 index 0000000..1773f8a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/OrderHistoryDialog.cs @@ -0,0 +1,144 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.ServiceConfigurations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking; + + public class OrderHistoryDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label findServiceConfigurationsLabel = new Label("Find Service Configuration") { Style = TextStyle.Heading }; + + private readonly Label orderNameLabel = new Label("Order Name"); + private readonly TextBox orderNameTextBox = new TextBox(string.Empty); + private readonly Button findByNameButton = new Button("Find by Name") { Width = 150 }; + + private readonly Label orderIdLabel = new Label("Order ID"); + private readonly TextBox orderIdTextBox = new TextBox(string.Empty); + private readonly Button findByIdButton = new Button("Find by ID") { Width = 150 }; + private readonly Button enterCurrentIdButton = new Button("Enter Current ID") { Width = 200 }; + + private readonly List responseSections = new List(); + + public OrderHistoryDialog(Helpers helpers) : base(helpers.Engine) + { + this.helpers = helpers; + + Title = "Order History"; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private void Initialize() + { + findByNameButton.Pressed += FindByNameButton_Pressed; + + findByIdButton.Pressed += FindByIdButton_Pressed; + + enterCurrentIdButton.Pressed += (sender, args) => orderIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + } + + private void FindByIdButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(orderIdTextBox.Text, out var guid)) return; + + string serializedOrderHistory = string.Empty; + var deserializedOrderHistory = new List(); + + try + { + serializedOrderHistory = helpers.OrderManagerElement.GetSerializedOrderHistory(guid); + + deserializedOrderHistory = JsonConvert.DeserializeObject>(serializedOrderHistory); + } + catch(Exception ex) + { + serializedOrderHistory = ex.Message; + } + + ShowRequestResult($"Order {guid} history (serialized)", $"'{serializedOrderHistory}'"); + + ShowRequestResult($"Order {guid} history (deserialized)", $"'{JsonConvert.SerializeObject(deserializedOrderHistory)}'"); + } + + private void FindByNameButton_Pressed(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(orderNameTextBox.Text)) + { + orderNameTextBox.Text = String.Empty; + orderNameTextBox.ValidationText = "Fill out the Name of a reservation"; + orderNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstances = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(ReservationInstanceExposers.Name.Contains(orderNameTextBox.Text))); + if (!reservationInstances.Any()) + { + orderNameTextBox.Text = String.Empty; + orderNameTextBox.ValidationText = "Unable to find a reservation with the specified Name"; + orderNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstance = reservationInstances.First(); + + orderNameTextBox.Text = reservationInstance.Name; + orderIdTextBox.Text = reservationInstance.ID.ToString(); + orderNameTextBox.ValidationState = UIValidationState.Valid; + + ShowRequestResult($"Order {reservationInstance.Name} [{reservationInstance.ID}] history", $"'{helpers.OrderManagerElement.GetSerializedOrderHistory(reservationInstance.ID)}'"); + } + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(findServiceConfigurationsLabel, ++row, 0, 1, 5); + + AddWidget(orderNameLabel, ++row, 0, 1, 2); + AddWidget(orderNameTextBox, row, 2, 1, 2); + AddWidget(findByNameButton, row, 4); + + AddWidget(orderIdLabel, ++row, 0, 1, 2); + AddWidget(orderIdTextBox, row, 2, 1, 2); + AddWidget(findByIdButton, row, 4); + AddWidget(enterCurrentIdButton, ++row, 2, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/StopOrderNowDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/StopOrderNowDialog.cs new file mode 100644 index 0000000..bdf3c3f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/StopOrderNowDialog.cs @@ -0,0 +1,162 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Debug_2.Debug.Reservations; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Helpers = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers; + + public class StopOrderNowDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label findReservationsLabel = new Label("Stop Order Now") { Style = TextStyle.Heading }; + private readonly Label orderNameLabel = new Label("Name"); + private readonly Label orderIdLabel = new Label("GUID"); + private readonly Button enterCurrentOrderIdButton = new Button("Enter Current ID") { Width = 200 }; + private readonly List responseSections = new List(); + + public StopOrderNowDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Stop Order Now"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private TextBox OrderNameTextBox { get; set; } + + private TextBox OrderIdTextBox { get; set; } + + private Button FindByOrderNameButton { get; set; } + + private Button FindByOrderIdButton { get; set; } + + private void Initialize() + { + OrderNameTextBox = new TextBox { PlaceHolder = "Name", Width = 400 }; + OrderIdTextBox = new TextBox { PlaceHolder = "GUID", ValidationText = "Invalid GUID", Width = 400 }; + + FindByOrderNameButton = new Button("Stop By Name") { Width = 150 }; + FindByOrderNameButton.Pressed += StopOrderByNameButton_Pressed; + + FindByOrderIdButton = new Button("Stop By GUID") { Width = 150 }; + FindByOrderIdButton.Pressed += StopOrderByIdButton_Pressed; + + enterCurrentOrderIdButton.Pressed += (sender, args) => OrderIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(findReservationsLabel, ++row, 0, 1, 5); + + AddWidget(orderNameLabel, ++row, 0, 1, 2); + AddWidget(OrderNameTextBox, row, 2); + AddWidget(FindByOrderNameButton, row, 3); + + AddWidget(orderIdLabel, ++row, 0, 1, 2); + AddWidget(OrderIdTextBox, row, 2); + AddWidget(FindByOrderIdButton, row, 3); + AddWidget(enterCurrentOrderIdButton, ++row, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void StopOrderByNameButton_Pressed(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(OrderNameTextBox.Text)) + { + OrderIdTextBox.Text = String.Empty; + OrderNameTextBox.ValidationText = "Fill out the Name of a reservation"; + OrderNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstances = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(ReservationInstanceExposers.Name.Contains(OrderNameTextBox.Text))); + if (!reservationInstances.Any()) + { + OrderIdTextBox.Text = String.Empty; + OrderNameTextBox.ValidationText = "Unable to find a reservation with the specified Name"; + OrderNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstance = reservationInstances.First(); + + OrderNameTextBox.Text = reservationInstance.Name; + OrderIdTextBox.Text = reservationInstance.ID.ToString(); + OrderNameTextBox.ValidationState = UIValidationState.Valid; + + var order = helpers.OrderManager.GetOrder(reservationInstance, false, true); + + order.StopNow = true; + var tasks = order.StopOrderAndLinkedServices(helpers).Tasks; + + ShowRequestResult($"Stopping order {order.Name}", string.Join("\n", tasks.Select(t => $"{t.Description} {t.Status}"))); + } + + private void StopOrderByIdButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(OrderIdTextBox.Text, out var guid)) + { + OrderNameTextBox.Text = String.Empty; + OrderNameTextBox.ValidationText = "Unable to parse the GUID"; + OrderIdTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstance = DataMinerInterface.ResourceManager.GetReservationInstance(helpers, guid); + if (reservationInstance == null) + { + OrderNameTextBox.Text = String.Empty; + OrderNameTextBox.ValidationText = "No reservations found with the given ID"; + OrderIdTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + OrderNameTextBox.Text = reservationInstance.Name; + OrderIdTextBox.Text = reservationInstance.ID.ToString(); + OrderIdTextBox.ValidationState = UIValidationState.Valid; + + var order = helpers.OrderManager.GetOrder(reservationInstance, false, true); + + order.StopNow = true; + var tasks = order.StopOrderAndLinkedServices(helpers).Tasks; + + ShowRequestResult($"Stopping order {order.Name}", string.Join("\n", tasks.Select(t => $"{t.Description} {t.Status}"))); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/UpdateOrderUiPropertiesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/UpdateOrderUiPropertiesDialog.cs new file mode 100644 index 0000000..37e2ebf --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Orders/UpdateOrderUiPropertiesDialog.cs @@ -0,0 +1,189 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Orders +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.ResourceManager.Objects; + + public class UpdateOrderUiPropertiesDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label updateUiPropertiesLabel = new Label("Update UI Properties") { Style = TextStyle.Heading }; + + private GetOrderReservationsSection getOrderReservationsSection; + + private readonly Button updateUiPropertiesButton = new Button("Update UI Properties") { Width = 200 }; + + private readonly CheckBox updateRecordingServicesCheckBox = new CheckBox("Update UI Properties of Services") { IsChecked = false }; + + private readonly List responseSections = new List(); + + public UpdateOrderUiPropertiesDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Update Order UI Properties"; + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + public event EventHandler ShowConfirmationDialog; + + public event EventHandler ShowProgressDialog; + + public event EventHandler OrdersUpdated; + + private void Initialize() + { + getOrderReservationsSection = new GetOrderReservationsSection(helpers); + + updateUiPropertiesButton.Pressed += UpdateUiPropertiesButton_Pressed; + } + + private void UpdateUiPropertiesButton_Pressed(object sender, EventArgs e) + { + if (!getOrderReservationsSection.IsValid) + { + ShowRequestResult("Invalid order IDs", "Invalid Order IDs"); + } + + var orderReservations = getOrderReservationsSection.GetOrderReservations(); + if (!orderReservations.Any()) return; + + StringBuilder sb = new StringBuilder(); + sb.AppendLine($"Are you sure you want to update the UI properties on the following {orderReservations.Count} order(s):"); + foreach (var orderReservation in orderReservations) sb.AppendLine($"\t-{orderReservation.Name}[{orderReservation.ID}]"); + + ConfirmationDialog confirmationDialog = new ConfirmationDialog(helpers.Engine, sb.ToString()); + + confirmationDialog.YesButton.Pressed += (s, args) => UpdateUiProperties(orderReservations, updateRecordingServicesCheckBox.IsChecked); + + ShowConfirmationDialog?.Invoke(this, confirmationDialog); + } + + private void UpdateUiProperties(IEnumerable orderReservations, bool updateServices) + { + ProgressDialog progressDialog = new ProgressDialog(helpers.Engine) { Title = "Updating UI Properties" }; + progressDialog.OkButton.Pressed += (sender, args) => OrdersUpdated?.Invoke(this, EventArgs.Empty); + progressDialog.Show(false); + + var succeededGuids = new List(); + var failedGuids = new List(); + foreach (var orderReservation in orderReservations) + { + try + { + progressDialog.AddProgressLine($"Retrieving order {orderReservation.Name}[{orderReservation.ID}]..."); + var order = helpers.OrderManager.GetOrder(orderReservation); + progressDialog.AddProgressLine($"Order Retrieved"); + + progressDialog.AddProgressLine($"Updating UI properties for Order {orderReservation.Name}[{orderReservation.ID}]..."); + order.UpdateUiProperties(helpers); + progressDialog.AddProgressLine($"Order UI properties updated"); + + bool serviceConfigUpdateRequired = false; + if (updateServices) + { + foreach (var service in order.AllServices) + { + if (service.RecordingConfiguration.IsConfigured && String.IsNullOrWhiteSpace(service.RecordingConfiguration.RecordingName)) + { + progressDialog.AddProgressLine($"Updating Recording Configuration for Recording {service.Name}[{service.Id}]..."); + service.RecordingConfiguration.RecordingName = order.Name; + service.RecordingConfiguration.IsConfigured = true; + + if (service.UpdateRecordingConfigurationProperty(helpers, order)) + { + progressDialog.AddProgressLine($"Recording Configuration updated"); + } + else + { + progressDialog.AddProgressLine($"Failed to update Recording Configuration"); + } + + serviceConfigUpdateRequired = true; + } + + progressDialog.AddProgressLine($"Updating UI properties for {service.Name}[{service.Id}]..."); + if (service.UpdateUiProperties(helpers, order)) + { + progressDialog.AddProgressLine($"UI properties updated"); + } + else + { + progressDialog.AddProgressLine($"Failed to update UI properties"); + } + } + } + + if (serviceConfigUpdateRequired) + { + progressDialog.AddProgressLine($"Updating Service Configuration for Order {orderReservation.Name}[{orderReservation.ID}]..."); + if (order.UpdateServiceConfigurationProperty(helpers)) + { + progressDialog.AddProgressLine($"Order Service Configuration updated"); + } + else + { + progressDialog.AddProgressLine($"Failed to update Order Service Configuration"); + } + } + + succeededGuids.Add(order.Id); + } + catch (Exception e) + { + progressDialog.AddProgressLine($"Something went wrong with updating order {orderReservation.ID} {e}"); + failedGuids.Add(orderReservation.ID); + } + } + + ShowRequestResult($"Updated UI Properties {DateTime.Now.ToShortTimeString()}", $"Succeeded Guids:\n{string.Join("\n", succeededGuids)}\n\nFailed Guids:\n{string.Join("\n", failedGuids)}"); + + progressDialog.Finish(); + ShowProgressDialog?.Invoke(this, progressDialog); + } + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(updateUiPropertiesLabel, ++row, 0, 1, 5); + + AddSection(getOrderReservationsSection, ++row, 0); + row += getOrderReservationsSection.RowCount; + + AddWidget(updateRecordingServicesCheckBox, ++row, 0, 1, 5); + + AddWidget(updateUiPropertiesButton, ++row, 0, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/OverviewDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/OverviewDialog.cs new file mode 100644 index 0000000..b608b97 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/OverviewDialog.cs @@ -0,0 +1,378 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug +{ + using System; + using Debug_2.Debug.NonLive; + using Debug_2.Debug.NonLiveUserTasks; + using Debug_2.Debug.Orders; + using Debug_2.Debug.Reservations; + using Debug_2.Debug.Resources; + using Debug_2.Debug.ServiceDefinitions; + using Debug_2.Debug.Tickets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Debug.VIZREM; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.BookingManagers; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Debug.Services; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Functions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Integrations; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Jobs; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.LogCollector; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Metrics; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Orders; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.ProfileParameters; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Resources; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.ServiceConfigurations; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Templates; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Tickets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class OverviewDialog : Dialog + { + private readonly Helpers helpers; + + public TextBox CurrentIdTextBox { get; private set; } = new TextBox(); + + private readonly Label localTimeZoneLabel = new Label(TimeZoneInfo.Local.DisplayName); + private readonly Label reservationsLabel = new Label("Reservations") { Style = TextStyle.Heading }; + private readonly Label ordersLabel = new Label("Orders") { Style = TextStyle.Heading }; + private readonly Label servicesLabel = new Label("Services") { Style = TextStyle.Heading }; + private readonly Label nonLiveUserTasksLabel = new Label("Non-Live Order User Tasks") { Style = TextStyle.Heading }; + private readonly Label nonLiveOrdersLabel = new Label("Non-Live Orders") { Style = TextStyle.Heading }; + private readonly Label serviceConfigurationsLabel = new Label("Service Configurations") { Style = TextStyle.Heading }; + private readonly Label integrationsLabel = new Label("Integrations") { Style = TextStyle.Heading }; + private readonly Label resourcesLabel = new Label("Resources") { Style = TextStyle.Heading }; + private readonly Label ticketsLabel = new Label("Tickets") { Style = TextStyle.Heading }; + private readonly Label loggingLabel = new Label("Logging") { Style = TextStyle.Heading }; + private readonly Label templatesLabel = new Label("Templates") { Style = TextStyle.Heading }; + private readonly Label functionsLabel = new Label("Functions") { Style = TextStyle.Heading }; + private readonly Label serviceDefinitionsLabel = new Label("Service Definitions") { Style = TextStyle.Heading }; + private readonly Label bookingManagersLabel = new Label("Booking Managers") { Style = TextStyle.Heading }; + private readonly Label eventsLabel = new Label("Events") { Style = TextStyle.Heading }; + + private readonly Button printLoggingButton = new Button("Print Logging") { Width = 300 }; + + public OverviewDialog(Helpers helpers) : base(helpers.Engine) + { + this.helpers = helpers; + + Title = "Overview"; + + CurrentIdTextBox.Text = Engine.GetScriptParam(1).Value; + + FindReservationsDialog = new FindReservationsDialog(helpers); + FindReservationLoggingDialog = new FindReservationLoggingDialog(helpers); + EditReservationPropertiesDialog = new EditReservationPropertiesDialog(helpers); + ServiceConfigurationsDialog = new GetServiceConfigurationsDialog(helpers); + RetriggerIntegrationUpdatesDialog = new RetriggerIntegrationUpdatesDialog(helpers); + ResourceOccupancyDialog = new ResourceOccupancyDialog(helpers); + FindReservationsWithoutJobDialog = new FindReservationsWithoutJobDialog(helpers); + MetricsDialog = new MetricsDialog(helpers); + SendIntegrationNotificationDialog = new SendIntegrationNotificationDialog(helpers); + UpdateOrderUiPropertiesDialog = new UpdateOrderUiPropertiesDialog(helpers); + LogCollectorDialog = new LogCollectorDialog(helpers); + GetEligibleResourcesDialog = new GetEligibleResourcesDialog(helpers); + MoveToQuarantinedStateDialog = new MoveToQuarantinedStateDialog(helpers); + FindQuarantinedOrdersDialog = new FindQuarantinedOrdersDialog(helpers); + FindProfileParameterDialog = new FindProfileParameterDialog(helpers); + FindTicketsDialog = new FindTicketsDialog(helpers); + StopOrderNowDialog = new StopOrderNowDialog(helpers); + OrderHistoryDialog = new OrderHistoryDialog(helpers); + AddOrUpdateServiceConfigurationsDialog = new AddOrUpdateServiceConfigurationsDialog(helpers); + FixServiceConfigurationsDialog = new FixServiceConfigurationsDialog(helpers); + DeleteOrdersDialog = new DeleteOrdersDialog(helpers); + FixResourceConfigurationDialog = new FixResourceConfigurationDialog(helpers); + DeleteTemplatesDialog = new DeleteTemplatesDialog(helpers); + EditOrderTemplatesDialog = new EditOrderTemplatesDialog(helpers); + EditEventTemplatesDialog = new EditEventTemplatesDialog(helpers); + AnalyzePlasmaRecordingsDialog = new AnalyzePlasmaRecordingsDialog(helpers); + VizremDialog = new VizremDialog(helpers); + ActiveFunctionsDialog = new ActiveFunctionsDialog(helpers); + GetServiceDefinitionDialog = new GetServiceDefinitionDialog(helpers); + UpdateServiceDefinitionsDialog = new UpdateServiceDefinitionsDialog(helpers); + FindResourcesWithFiltersDialog = new FindResourcesWithFiltersDialog(helpers); + FindReservationsWithFiltersDialog = new FindReservationsWithFiltersDialog(helpers); + RemoveDuplicatePropertiesDialog = new RemoveDuplicatePropertiesDialog(helpers); + FindTicketsWithFiltersDialog = new FindTicketsWithFiltersDialog(helpers); + UpdateNonLiveOrderUserTasksDialog = new UpdateNonLiveOrderUserTasksDialog(helpers); + TestDataMinerInterfaceDialog = new TestDataMinerInterfaceDialog(helpers); + FixMissingServiceDefinitionsDialog = new FixMissingServiceDefinitionsDialog(helpers); + AddOrUpdateResourcesDialog = new AddOrUpdateResourcesDialog(helpers); + ReassignJobDialog = new ReassignJobDialog(helpers); + ManageSectionDefinitionsDialog = new ManageSectionDefinitionsDialog(helpers); + ProfileLoadLoggingDialog = new ProfileLoadLoggingDialog(helpers); + AutoUpdateOrderPropertiesDialog = new AutoUpdateOrderPropertiesDialog(helpers); + NonLiveOrdersDialog = new NonLiveOrdersDialog(helpers); + + printLoggingButton.Pressed += (sender, args) => helpers.Dispose(); + + GenerateUi(); + } + + public Button DownloadLoggingButton { get; private set; } = new Button("Download Logging") { Width = 150 }; + + public Button FindReservationsButton { get; } = new Button("Find Reservations...") { Width = 300 }; + + public FindReservationsDialog FindReservationsDialog { get; } + + public Button FindReservationOrderLoggingButton { get; } = new Button("Find Reservation Order Logging...") { Width = 300 }; + + public FindReservationLoggingDialog FindReservationLoggingDialog { get; } + + public Button EditReservationPropertiesButton { get; } = new Button("Edit Reservation Properties...") { Width = 300 }; + + public EditReservationPropertiesDialog EditReservationPropertiesDialog { get; } + + public Button GetServiceConfigurationsButton { get; } = new Button("Get Service Configurations...") { Width = 300 }; + + public GetServiceConfigurationsDialog ServiceConfigurationsDialog { get; } + + public Button RetriggerIntegrationUpdatesButton { get; } = new Button("Retrigger Integrations...") { Width = 300 }; + + public RetriggerIntegrationUpdatesDialog RetriggerIntegrationUpdatesDialog { get; } + + public Button ResourceOccupancyButton { get; } = new Button("Resource Occupancy...") { Width = 300 }; + + public ResourceOccupancyDialog ResourceOccupancyDialog { get; } + + public Button ReservationsWithoutJobsButton { get; } = new Button("Reservations Without Events...") { Width = 300 }; + + public MoveToQuarantinedStateDialog MoveToQuarantinedStateDialog { get; } + + public Button MoveToQuarantinedStateButton { get; } = new Button("Move to Quarantined State...") { Width = 300 }; + + public FindQuarantinedOrdersDialog FindQuarantinedOrdersDialog { get; } + + public Button FindQuarantinedOrdersButton { get; } = new Button("Find Quarantined Orders...") { Width = 300 }; + + public FindReservationsWithoutJobDialog FindReservationsWithoutJobDialog { get; } + + public Button MetricsButton { get; } = new Button("Metrics...") { Width = 300 }; + + public MetricsDialog MetricsDialog { get; } + + public SendIntegrationNotificationDialog SendIntegrationNotificationDialog { get; } + + public Button SendIntegrationNotificationButton { get; } = new Button("Send Integration Notification...") { Width = 300 }; + + public Button UpdateOrderUiPropertiesButton { get; } = new Button("Update Order UI Properties...") { Width = 300 }; + + public UpdateOrderUiPropertiesDialog UpdateOrderUiPropertiesDialog { get; } + + public Button LogCollectorButton { get; } = new Button("Log Collector...") { Width = 300 }; + + public LogCollectorDialog LogCollectorDialog { get; } + + public Button EligibleResourcesButton { get; } = new Button("Eligible Resources...") { Width = 300 }; + + public GetEligibleResourcesDialog GetEligibleResourcesDialog { get; } + + public Button FindProfileParameterButton { get; } = new Button("Find Profile Parameter...") { Width = 300 }; + + public FindProfileParameterDialog FindProfileParameterDialog { get; } + + public FindTicketsDialog FindTicketsDialog { get; } + + public Button FindTicketsButton { get; } = new Button("Find Tickets...") { Width = 300 }; + + public OrderHistoryDialog OrderHistoryDialog { get; } + + public Button OrderHistoryButton { get; } = new Button("Order History...") { Width = 300 }; + + public StopOrderNowDialog StopOrderNowDialog { get; } + + public Button StopOrderNowButton { get; } = new Button("Stop Order Now...") { Width = 300 }; + + public AddOrUpdateServiceConfigurationsDialog AddOrUpdateServiceConfigurationsDialog { get; } + + public Button AddOrUpdateServiceConfigurationsButton { get; } = new Button("Add or Update Service Configurations...") { Width = 300 }; + + public FixServiceConfigurationsDialog FixServiceConfigurationsDialog { get; } + + public Button FixServiceConfigurationsButton = new Button("Fix Service Configurations...") { Width = 300 }; + + public DeleteOrdersDialog DeleteOrdersDialog { get; } + + public Button DeleteOrdersButton { get; } = new Button("Delete Orders...") { Width = 300 }; + + public FixResourceConfigurationDialog FixResourceConfigurationDialog { get; } + + public Button FixResourceConfigurationButton { get; } = new Button("Fix Resource Configuration...") { Width = 300 }; + + public DeleteTemplatesDialog DeleteTemplatesDialog { get; } + + public Button DeleteTemplatesButton { get; } = new Button("Delete Templates...") { Width = 300 }; + + public EditOrderTemplatesDialog EditOrderTemplatesDialog { get; } + + public Button EditOrderTemplateButton { get; } = new Button("Edit Order Templates...") { Width = 300 }; + + public EditEventTemplatesDialog EditEventTemplatesDialog { get; } + + public Button EditEventTemplateButton { get; } = new Button("Edit Event Templates...") { Width = 300 }; + + public AnalyzePlasmaRecordingsDialog AnalyzePlasmaRecordingsDialog { get; } + + public Button AnalyzePlasmaRecordingsButton { get; } = new Button("Analyze Plasma Recordings...") { Width = 300 }; + + public Button GenerateFieldsFileButton { get; } = new Button("Generate Tooltip file") { Width = 300 }; + + public VizremDialog VizremDialog { get; } + + public Button VizremButton { get; } = new Button("VIZREM...") { Width = 300, IsVisible = false }; + + public ActiveFunctionsDialog ActiveFunctionsDialog { get; } + + public Button ActiveFunctionsButton { get; } = new Button("View Active Functions...") { Width = 300 }; + + public GetServiceDefinitionDialog GetServiceDefinitionDialog { get; } + + public Button GetServiceDefinitionButton { get; } = new Button("Get Service Definitions...") { Width = 300 }; + + public UpdateServiceDefinitionsDialog UpdateServiceDefinitionsDialog { get; } + + public Button UpdateServiceDefinitionsButton { get; } = new Button("Update Service Definition...") { Width = 300 }; + + public FindResourcesWithFiltersDialog FindResourcesWithFiltersDialog { get; } + + public Button FindResourcesWithFiltersButton { get; } = new Button("Find Resources With Filters...") { Width = 300 }; + + public FindReservationsWithFiltersDialog FindReservationsWithFiltersDialog { get; } + + public Button FindReservationsWithFiltersButton { get; } = new Button("Find Reservations with Filters...") { Width = 300 }; + + public RemoveDuplicatePropertiesDialog RemoveDuplicatePropertiesDialog { get; } + + public Button RemoveDuplicatePropertiesButton { get; } = new Button("Remove Duplicate Booking Manager Properties...") { Width = 300 }; + + public FindTicketsWithFiltersDialog FindTicketsWithFiltersDialog { get; } + + public Button FindTicketsWithFiltersButton { get; } = new Button("Find Tickets With Filters...") { Width = 300 }; + + public UpdateNonLiveOrderUserTasksDialog UpdateNonLiveOrderUserTasksDialog { get; set; } + + public Button UpdateNonLiveOrderUserTasksButton { get; } = new Button("Update Non-Live Order User Tasks...") { Width = 300 }; + + public TestDataMinerInterfaceDialog TestDataMinerInterfaceDialog { get; } + + public Button TestDataMinerInterfaceButton { get; } = new Button("Test DataMiner Interface...") { Width = 300 }; + + public FixMissingServiceDefinitionsDialog FixMissingServiceDefinitionsDialog { get; } + + public Button FixMissingServiceDefinitionsButton { get; } = new Button("Fix Missing Service Definitions...") { Width = 300 }; + + public AddOrUpdateResourcesDialog AddOrUpdateResourcesDialog { get; } + + public Button AddOrUpdateResourcesButton { get; } = new Button("Add or Update Resources...") { Width = 300 }; + + public ReassignJobDialog ReassignJobDialog { get; } + + public Button ReassignJobButton { get; } = new Button("Reassign Job...") { Width = 300 }; + + public ManageSectionDefinitionsDialog ManageSectionDefinitionsDialog { get; } + + public Button ManageSectionDefinitionsButton { get; } = new Button("Manage Section Definitions...") { Width = 300 }; + + public ProfileLoadLoggingDialog ProfileLoadLoggingDialog { get; set; } + + public Button ProfileLoadLoggingButton { get; } = new Button("Profile Load Logging...") { Width = 300 }; + + public AutoUpdateOrderPropertiesDialog AutoUpdateOrderPropertiesDialog { get; set; } + + public Button AutoUpdateOrderPropertiesButton { get; } = new Button("Automatically Update Order Properties...") { Width = 300 }; + + public NonLiveOrdersDialog NonLiveOrdersDialog { get; set; } + + public Button NonLiveOrdersButton { get; } = new Button("Non-Live Orders...") { Width = 300 }; + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(localTimeZoneLabel, ++row, 0, 1, 5); + AddWidget(CurrentIdTextBox, ++row, 0, 1, 5); + AddWidget(DownloadLoggingButton, row, 5); + + AddWidget(reservationsLabel, ++row, 0); + AddWidget(FindReservationsButton, ++row, 0); + AddWidget(FindReservationsWithFiltersButton, ++row, 0); + AddWidget(TestDataMinerInterfaceButton, ++row, 0); + + AddWidget(ordersLabel, ++row, 0, 1, 5); + AddWidget(UpdateOrderUiPropertiesButton, ++row, 0); + AddWidget(AutoUpdateOrderPropertiesButton, ++row, 0); + AddWidget(MoveToQuarantinedStateButton, ++row, 0); + AddWidget(FindQuarantinedOrdersButton, ++row, 0); + AddWidget(FindProfileParameterButton, ++row, 0); + AddWidget(EditReservationPropertiesButton, ++row, 0); + AddWidget(OrderHistoryButton, ++row, 0); + AddWidget(StopOrderNowButton, ++row, 0); + AddWidget(DeleteOrdersButton, ++row, 0); + + AddWidget(servicesLabel, ++row, 0, 1, 5); + AddWidget(ProfileLoadLoggingButton, ++row, 0); + + AddWidget(eventsLabel, ++row, 0, 1, 5); + AddWidget(ReservationsWithoutJobsButton, ++row, 0); + AddWidget(ReassignJobButton, ++row, 0); + AddWidget(ManageSectionDefinitionsButton, ++row, 0); + + AddWidget(serviceDefinitionsLabel, ++row, 0, 1, 5); + AddWidget(GetServiceDefinitionButton, ++row, 0); + AddWidget(UpdateServiceDefinitionsButton, ++row, 0); + AddWidget(FixMissingServiceDefinitionsButton, ++row, 0); + + AddWidget(functionsLabel, ++row, 0); + AddWidget(ActiveFunctionsButton, ++row, 0); + + AddWidget(serviceConfigurationsLabel, ++row, 0, 1, 5); + AddWidget(GetServiceConfigurationsButton, ++row, 0); + AddWidget(AddOrUpdateServiceConfigurationsButton, ++row, 0); + AddWidget(FixServiceConfigurationsButton, ++row, 0); + + AddWidget(integrationsLabel, ++row, 0, 1, 5); + AddWidget(RetriggerIntegrationUpdatesButton, ++row, 0); + AddWidget(SendIntegrationNotificationButton, ++row, 0); + AddWidget(AnalyzePlasmaRecordingsButton, ++row, 0); + AddWidget(VizremButton, ++row, 0); + + AddWidget(resourcesLabel, ++row, 0, 1, 5); + AddWidget(FindResourcesWithFiltersButton, ++row, 0); + AddWidget(EligibleResourcesButton, ++row, 0); + AddWidget(ResourceOccupancyButton, ++row, 0); + AddWidget(FixResourceConfigurationButton, ++row, 0); + AddWidget(AddOrUpdateResourcesButton, ++row, 0); + + AddWidget(ticketsLabel, ++row, 0, 1, 5); + AddWidget(FindTicketsButton, ++row, 0); + AddWidget(FindTicketsWithFiltersButton, ++row, 0); + + AddWidget(nonLiveOrdersLabel, ++row, 0, 1, 5); + AddWidget(NonLiveOrdersButton, ++row, 0); + + AddWidget(nonLiveUserTasksLabel, ++row, 0, 1, 5); + AddWidget(UpdateNonLiveOrderUserTasksButton, ++row, 0); + + AddWidget(templatesLabel, ++row, 0, 1, 5); + AddWidget(EditOrderTemplateButton, ++row, 0); + AddWidget(EditEventTemplateButton, ++row, 0); + AddWidget(DeleteTemplatesButton, ++row, 0); + + AddWidget(loggingLabel, ++row, 0, 1, 5); + AddWidget(FindReservationOrderLoggingButton, ++row, 0); + AddWidget(MetricsButton, ++row, 0); + AddWidget(LogCollectorButton, ++row, 0); + + AddWidget(bookingManagersLabel, ++row, 0, 1, 5); + AddWidget(RemoveDuplicatePropertiesButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(GenerateFieldsFileButton, ++row, 0); + + AddWidget(printLoggingButton, ++row, 0); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ProfileParameters/FindProfileParameterDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ProfileParameters/FindProfileParameterDialog.cs new file mode 100644 index 0000000..0bcbdec --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ProfileParameters/FindProfileParameterDialog.cs @@ -0,0 +1,82 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.ProfileParameters +{ + using System; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class FindProfileParameterDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label findParameterLabel = new Label("Find Profile Parameter") { Style = TextStyle.Heading }; + private readonly Label parameterIdLabel = new Label("GUID"); + private readonly Label parameterNameLabel = new Label(String.Empty); + + public FindProfileParameterDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Find Profile Parameter"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private TextBox ParameterIdTextBox { get; set; } + + private Button FindByParameterIdButton { get; set; } + + private void Initialize() + { + ParameterIdTextBox = new TextBox { PlaceHolder = "GUID", ValidationText = "Invalid GUID", Width = 400 }; + + FindByParameterIdButton = new Button("Find By GUID") { Width = 150 }; + FindByParameterIdButton.Pressed += FindByParameterIdButton_Pressed; + } + + private void FindByParameterIdButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(ParameterIdTextBox.Text, out var guid)) + { + parameterNameLabel.Text = String.Empty; + ParameterIdTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + try + { + var parameter = helpers.ProfileManager.GetProfileParameter(guid); + parameterNameLabel.Text = parameter.Name; + } + catch (ProfileParameterNotFoundException) + { + parameterNameLabel.Text = "No profile parameter found with given ID"; + } + + ParameterIdTextBox.ValidationState = UIValidationState.Valid; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(findParameterLabel, ++row, 0, 1, 5); + + AddWidget(parameterIdLabel, ++row, 0, 1, 2); + AddWidget(ParameterIdTextBox, row, 2); + AddWidget(FindByParameterIdButton, row, 3); + + AddWidget(new WhiteSpace(), ++row, 1); + + AddWidget(parameterNameLabel, ++row, 0, 1, 3); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/RequestResultSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/RequestResultSection.cs new file mode 100644 index 0000000..85a9535 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/RequestResultSection.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using Skyline.DataMiner.Utils.InteractiveAutomationScript; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug +{ + public class RequestResultSection : ResponseSection + { + private readonly CollapseButton collapseButton; + private readonly Label header; + private readonly List contentTextBoxes = new List(); + + public RequestResultSection(string header, params string[] results) + { + this.header = new Label(header) { Style = TextStyle.Heading }; + + foreach (var result in results) + { + contentTextBoxes.Add(new TextBox(result) { IsEnabled = true, IsVisible = true, IsMultiline = true, MinWidth = 600 }); + } + + this.collapseButton = new CollapseButton(contentTextBoxes, true) { CollapseText = "-", ExpandText = "+", Width = 44 }; + + GenerateUi(); + } + + public override void Collapse() + { + collapseButton.IsCollapsed = true; + } + + public void SetContentTextBoxWidth(int width) + { + foreach (var contentTextBox in contentTextBoxes) + { + contentTextBox.Width = width; + } + } + + public void SetContentTextBoxHeight(int height) + { + foreach (var contentTextBox in contentTextBoxes) + { + contentTextBox.Height = height; + } + } + + private void GenerateUi() + { + int row = -1; + + AddWidget(collapseButton, ++row, 0); + AddWidget(header, row, 1, 1, 2); + + row++; + int column = 0; + foreach (var contentTextBox in contentTextBoxes) + { + AddWidget(contentTextBox, row, column, 1, 5); + column += 5; + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/EditReservationPropertiesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/EditReservationPropertiesDialog.cs new file mode 100644 index 0000000..afcadd7 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/EditReservationPropertiesDialog.cs @@ -0,0 +1,161 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations +{ + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Text; + + public class EditReservationPropertiesDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label findReservationsLabel = new Label("Find Reservation") { Style = TextStyle.Heading }; + private readonly Label reservationNameLabel = new Label("Name"); + private readonly Label reservationIdLabel = new Label("GUID"); + private readonly Button enterCurrentOrderIdButton = new Button("Enter Current ID") { Width = 200 }; + private readonly List propertiesSections = new List(); + + public EditReservationPropertiesDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Find Reservation"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private TextBox ReservationNameTextBox { get; set; } + + private TextBox ReservationIdTextBox { get; set; } + + private Button FindByReservationNameButton { get; set; } + + private Button FindByReservationIdButton { get; set; } + + private void Initialize() + { + ReservationNameTextBox = new TextBox { PlaceHolder = "Name", Width = 400 }; + ReservationIdTextBox = new TextBox { PlaceHolder = "GUID", ValidationText = "Invalid GUID", Width = 400 }; + + FindByReservationNameButton = new Button("Find By Name") { Width = 150 }; + FindByReservationNameButton.Pressed += FindByReservationNameButton_Pressed; + + FindByReservationIdButton = new Button("Find By GUID") { Width = 150 }; + FindByReservationIdButton.Pressed += FindByReservationIdButton_Pressed; + + enterCurrentOrderIdButton.Pressed += (sender, args) => ReservationIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(findReservationsLabel, ++row, 0, 1, 5); + + AddWidget(reservationNameLabel, ++row, 0, 1, 2); + AddWidget(ReservationNameTextBox, row, 2); + AddWidget(FindByReservationNameButton, row, 3); + + AddWidget(reservationIdLabel, ++row, 0, 1, 2); + AddWidget(ReservationIdTextBox, row, 2); + AddWidget(FindByReservationIdButton, row, 3); + AddWidget(enterCurrentOrderIdButton, ++row, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var section in propertiesSections) + { + AddSection(section, row, 0); + row += section.RowCount; + } + } + + private void ShowOrderDetails(ReservationInstance reservationInstance) + { + propertiesSections.Clear(); + + if (reservationInstance != null) + { + foreach (var property in reservationInstance.Properties.OrderBy(x => x.Key)) + { + propertiesSections.Add(new ReservationPropertySection(helpers, reservationInstance, property)); + } + } + + GenerateUi(); + } + + private void FindByReservationNameButton_Pressed(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(ReservationNameTextBox.Text)) + { + ReservationIdTextBox.Text = String.Empty; + ShowOrderDetails(null); + ReservationNameTextBox.ValidationText = "Fill out the Name of a reservation"; + ReservationNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstances = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(ReservationInstanceExposers.Name.Contains(ReservationNameTextBox.Text))); + if (!reservationInstances.Any()) + { + ReservationIdTextBox.Text = String.Empty; + ShowOrderDetails(null); + ReservationNameTextBox.ValidationText = "Unable to find a reservation with the specified Name"; + ReservationNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstance = reservationInstances.First(); + + ReservationNameTextBox.Text = reservationInstance.Name; + ReservationIdTextBox.Text = reservationInstance.ID.ToString(); + ReservationNameTextBox.ValidationState = UIValidationState.Valid; + + ShowOrderDetails(reservationInstance); + } + + private void FindByReservationIdButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(ReservationIdTextBox.Text, out var guid)) + { + ReservationNameTextBox.Text = String.Empty; + ShowOrderDetails(null); + ReservationNameTextBox.ValidationText = "Unable to parse the GUID"; + ReservationIdTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstance = DataMinerInterface.ResourceManager.GetReservationInstance(helpers, guid); + if (reservationInstance == null) + { + ReservationNameTextBox.Text = String.Empty; + ShowOrderDetails(null); + ReservationNameTextBox.ValidationText = "No reservations found with the given ID"; + ReservationIdTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + ReservationNameTextBox.Text = reservationInstance.Name; + ReservationIdTextBox.Text = reservationInstance.ID.ToString(); + ReservationIdTextBox.ValidationState = UIValidationState.Valid; + + ShowOrderDetails(reservationInstance); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindQuarantinedOrdersDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindQuarantinedOrdersDialog.cs new file mode 100644 index 0000000..1dac13f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindQuarantinedOrdersDialog.cs @@ -0,0 +1,682 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + using Debug_2.Debug.Reservations; + using Skyline.DataMiner.Library.Solutions.SRM.Model; + using Skyline.DataMiner.Library.Solutions.SRM.Model.AssignProfilesAndResources; + using Skyline.DataMiner.Net.History; + using Skyline.DataMiner.Net.History.ReservationInstances; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Net.SRM.Capabilities; + using SLDataGateway.API.Querying; + using Parameter = Library.Solutions.SRM.Model.Parameter; + + public class FindQuarantinedOrdersDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label findQuarantinedOrdersLabel = new Label("Find Quarantined Orders") { Style = TextStyle.Heading }; + private readonly Label noQuarantinedOrdersFoundLabel = new Label("No Quarantined Orders Found"); + private readonly Label sortByLabel = new Label("Sort By"); + private readonly List quarantinedReservationSections = new List(); + + private bool findQuarantinedOrdersButtonWasPressed; + + public FindQuarantinedOrdersDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Find Quarantined Orders"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + FindQuarantinedOrdersButton.Pressed += FindQuarantinedReservationsButton_Pressed; + } + + private void FindQuarantinedReservationsButton_Pressed(object sender, EventArgs e) + { + findQuarantinedOrdersButtonWasPressed = true; + + FilterElement filter = new ANDFilterElement(ReservationInstanceExposers.IsQuarantined.Equal(true)) + .AND(ReservationInstanceExposers.Properties.DictStringField("Booking Manager").Equal("Order Booking Manager")); + + if (!IncludeOrdersInThePastCheckBox.IsChecked) + { + filter = filter.AND(ReservationInstanceExposers.End.GreaterThanOrEqual(DateTime.Now)); + } + + var quarantinedReservations = SrmManagers.ResourceManager.GetReservationInstances(filter); + + quarantinedReservationSections.Clear(); + ReservationInstance[] orderedQuarantinedReservations; + switch (SortByRadioButtonList.Selected) + { + case DateString: + orderedQuarantinedReservations = quarantinedReservations.OrderBy(x => x.Start).ToArray(); + break; + case NameString: + orderedQuarantinedReservations = quarantinedReservations.OrderBy(x => x.Name).ToArray(); + break; + default: + orderedQuarantinedReservations = quarantinedReservations; // No sorting specified + break; + } + + foreach (var reservation in orderedQuarantinedReservations) + { + QuarantinedReservationSection quarantinedReservationSection = new QuarantinedReservationSection(helpers, reservation); + quarantinedReservationSection.OnUiUpdateRequired += (s, args) => GenerateUi(); + quarantinedReservationSections.Add(quarantinedReservationSection); + } + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 5); + + AddWidget(findQuarantinedOrdersLabel, ++row, 0, 1, 5); + + AddWidget(IncludeOrdersInThePastCheckBox, ++row, 0, 1, 5); + + AddWidget(sortByLabel, ++row, 0, 1, 2, HorizontalAlignment.Left, VerticalAlignment.Top); + AddWidget(SortByRadioButtonList, row, 2, 1, 3); + + AddWidget(FindQuarantinedOrdersButton, ++row, 0, 1, 5); + + AddWidget(new WhiteSpace(), ++row, 1); + + if (findQuarantinedOrdersButtonWasPressed && !quarantinedReservationSections.Any()) + { + AddWidget(noQuarantinedOrdersFoundLabel, ++row, 0, 1, 5); + } + else + { + foreach (var section in quarantinedReservationSections) + { + AddSection(section, ++row, 0); + row += section.RowCount; + + } + } + + SetColumnWidth(0, 45); + SetColumnWidth(1, 45); + } + + public Button BackButton { get; private set; } = new Button("Back...") { Width = 150 }; + + public Button FindQuarantinedOrdersButton { get; private set; } = new Button("Find Quarantined Orders") { Width = 250 }; + + public CheckBox IncludeOrdersInThePastCheckBox { get; private set; } = new CheckBox("Include Orders in the Past") { IsChecked = false }; + + private const string DateString = "Date"; + private const string NameString = "Name"; + + public RadioButtonList SortByRadioButtonList { get; private set; } = new RadioButtonList(new [] { DateString, NameString }) { Selected = DateString }; + + private sealed class QuarantinedReservationSection : Section + { + private readonly Helpers helpers; + private readonly List reservationHistorySections = new List(); + private readonly List resourceHistorySections = new List(); + private readonly List quarantinedServiceSections = new List(); + private readonly ResourceAssignmentSection resourceAssignmentSection; + + private readonly CollapseButton collapseButton = new CollapseButton { Width = 44, CollapseText = "-", ExpandText = "+", IsCollapsed = true }; + + private readonly Label reservationIdTitle = new Label("ID"); + private readonly Label reservationNameTitle = new Label("Name"); + private readonly Label reservationStartTitle = new Label("Start"); + private readonly Label reservationEndTitle = new Label("End"); + private readonly Label quarantinedServicesTitle = new Label("Quarantined Services") { Style = TextStyle.Bold }; + + private readonly Label reservationTitleLabel = new Label { Style = TextStyle.Heading }; + private readonly Label reservationNameLabel = new Label(); + private readonly Label reservationIdLabel = new Label(); + private readonly Label reservationStartLabel = new Label(); + private readonly Label reservationEndLabel = new Label(); + private readonly Label reservationStateLabel = new Label(); + private readonly Label reservationQuarantinedLabel = new Label(); + + private readonly WhiteSpace whiteSpace1 = new WhiteSpace(); + private readonly WhiteSpace whiteSpace2 = new WhiteSpace(); + private readonly WhiteSpace whiteSpace3 = new WhiteSpace(); + + private readonly Label noReservationHistoryAvailableLabel = new Label("No Reservation Instance History Available"); + private readonly Label noContributingResourceHistoryAvailableLabel = new Label("No Contributing Resource History Available"); + + private readonly TextBox leaveQuarantinedStateExceptionTextBox = new TextBox { IsMultiline = true, Height = 300 }; + + private readonly bool isOrder; + + private bool servicesHaveBeenRetrieved; + + public QuarantinedReservationSection(Helpers helpers, ReservationInstance reservationInstance) + { + this.helpers = helpers; + ReservationInstance = reservationInstance; + + isOrder = reservationInstance.Properties.Any(x => x.Key.Equals("Booking Manager") && x.Value != null && x.Value.Equals("Order Booking Manager")); + if (isOrder) reservationTitleLabel.Style = TextStyle.Bold; + + reservationTitleLabel.Text = $"{reservationInstance.Name} ({reservationInstance.Start.ToUniversalTime()} - {reservationInstance.End.ToUniversalTime()} [UTC])"; + reservationNameLabel.Text = reservationInstance.Name; + reservationIdLabel.Text = reservationInstance.ID.ToString(); + reservationStartLabel.Text = $"{reservationInstance.Start.ToUniversalTime()} [UTC]"; + reservationEndLabel.Text = $"{reservationInstance.End.ToUniversalTime()} [UTC]"; + reservationStateLabel.Text = reservationInstance.Status.GetDescription(); + reservationQuarantinedLabel.Text = (reservationInstance.IsQuarantined) ? "Quarantined" : "Not Quarantined"; + + + if (!isOrder) resourceAssignmentSection = new ResourceAssignmentSection(helpers, reservationInstance as ServiceReservationInstance); + + Initialize(); + GenerateUi(); + } + + private void InitializeServiceSections() + { + string serializedConfig = helpers.OrderManagerElement.GetSerializedServiceConfigurations(ReservationInstance.ID); + if (string.IsNullOrWhiteSpace(serializedConfig) || serializedConfig == "-1" || serializedConfig.Equals("Not found", StringComparison.InvariantCultureIgnoreCase)) return; + + var serviceConfigurations = JsonConvert.DeserializeObject>(serializedConfig); + + quarantinedServiceSections.Clear(); + foreach (var serviceConfig in serviceConfigurations.Values) + { + var serviceReservation = helpers.ResourceManager.GetReservationInstance(serviceConfig.Id); + if (!serviceReservation.IsQuarantined) continue; + + helpers.Log(nameof(QuarantinedReservationSection), nameof(InitializeServiceSections), "JsonConvert.SerializeObject(serviceReservation)"); + + var quarantinedServiceSection = new QuarantinedReservationSection(helpers, serviceReservation); + collapseButton.LinkedWidgets.Add(quarantinedServiceSection.collapseButton); + collapseButton.LinkedWidgets.Add(quarantinedServiceSection.reservationTitleLabel); + + quarantinedServiceSection.OnUiUpdateRequired += (sender, args) => + { + GenerateUi(); + OnUiUpdateRequired(this, new EventArgs()); + }; + + quarantinedServiceSections.Add(quarantinedServiceSection); + } + } + + public event EventHandler OnUiUpdateRequired; + + private void Initialize() + { + collapseButton.LinkedWidgets.AddRange(new Widget[] + { + reservationIdTitle, + reservationNameTitle, + reservationNameLabel, + reservationIdLabel, + reservationStartTitle, + reservationStartLabel, + reservationEndTitle, + reservationEndLabel, + ReservationHistoryCollapseButton, + ResourceHistoryCollapseButton, + LeaveQuarantinedStateButton, + whiteSpace1, + whiteSpace2, + whiteSpace3, + quarantinedServicesTitle + }); + + if (!isOrder && resourceAssignmentSection != null) + { + collapseButton.LinkedWidgets.AddRange(resourceAssignmentSection.Widgets); + } + + collapseButton.Collapse(); + collapseButton.Pressed += CollapseButton_Pressed; + ReservationHistoryCollapseButton.Pressed += ReservationHistoryButton_Pressed; + ResourceHistoryCollapseButton.Pressed += ResourceHistoryCollapseButton_Pressed; + LeaveQuarantinedStateButton.Pressed += TryLeaveQuarantineButton_Pressed; + } + + private void CollapseButton_Pressed(object sender, EventArgs e) + { + if (!isOrder || servicesHaveBeenRetrieved) return; + + InitializeServiceSections(); + servicesHaveBeenRetrieved = true; + + GenerateUi(); + OnUiUpdateRequired(this, new EventArgs()); + } + + private void ReservationHistoryButton_Pressed(object sender, EventArgs e) + { + if (ReservationInstance == null || ReservationHistoryCollapseButton.IsCollapsed) return; + + try + { + string subjectId = $"ReservationInstanceID_{ReservationInstance.ID}"; + var filter = new ANDFilterElement(HistoryChangeExposers.SubjectID.Equal(subjectId, StringComparison.OrdinalIgnoreCase)); + var response = (ManagerStorePagingResponse)helpers.Engine.SendSLNetSingleResponseMessage(new ManagerStoreStartPagingRequest(filter.ToQuery(), 100) { ExtraTypeIdentifier = "ReservationInstance" }); + + ClearReservationHistorySections(); + foreach (var historyChange in response.Objects) + { + foreach (var change in historyChange.Changes) + { + var historySection = new HistorySection(change, historyChange.Time, historyChange.FullUsername, historyChange.DmaId, isOrder); + ReservationHistoryCollapseButton.LinkedWidgets.AddRange(historySection.Widgets); + reservationHistorySections.Add(historySection); + } + } + + ReservationHistoryCollapseButton.LinkedWidgets.Add(noReservationHistoryAvailableLabel); + } + catch (Exception exception) + { + helpers.Engine.Log($"{nameof(QuarantinedReservationSection)}|{nameof(ReservationHistoryButton_Pressed)}|{exception}"); + } + + GenerateUi(); + OnUiUpdateRequired(this, new EventArgs()); + } + + private void ResourceHistoryCollapseButton_Pressed(object sender, EventArgs e) + { + if (ReservationInstance == null || ResourceHistoryCollapseButton.IsCollapsed) return; + + try + { + string subjectId = $"ResourceID_{ReservationInstance.ID}"; + var filter = new ANDFilterElement(HistoryChangeExposers.SubjectID.Equal(subjectId, StringComparison.OrdinalIgnoreCase)); + var response = (ManagerStorePagingResponse)helpers.Engine.SendSLNetSingleResponseMessage(new ManagerStoreStartPagingRequest(filter.ToQuery(), 100) { ExtraTypeIdentifier = "Resource" }); + + ClearResourceHistorySections(); + foreach (var historyChange in response.Objects) + { + helpers.Engine.Log(JsonConvert.SerializeObject(historyChange)); + foreach (var change in historyChange.Changes) + { + var historySection = new HistorySection(change, historyChange.Time, historyChange.FullUsername, historyChange.DmaId, isOrder); + ResourceHistoryCollapseButton.LinkedWidgets.AddRange(historySection.Widgets); + resourceHistorySections.Add(historySection); + } + } + + ResourceHistoryCollapseButton.LinkedWidgets.Add(noContributingResourceHistoryAvailableLabel); + } + catch (Exception exception) + { + helpers.Engine.Log($"{nameof(QuarantinedReservationSection)}|{nameof(ResourceHistoryCollapseButton_Pressed)}|{exception}"); + } + + GenerateUi(); + OnUiUpdateRequired(this, new EventArgs()); + } + + private void TryLeaveQuarantineButton_Pressed(object sender, EventArgs e) + { + if (!ReservationInstance.Properties.Dictionary.TryGetValue("Booking Manager", out object bookingManagerElementName)) return; + try + { + var bookingManager = new BookingManager((Engine)helpers.Engine, helpers.Engine.FindElement(Convert.ToString(bookingManagerElementName))) { CustomProperties = true, CustomEvents = true }; + ReservationInstance = bookingManager.LeaveQuarantineState((Engine)helpers.Engine, ReservationInstance); + leaveQuarantinedStateExceptionTextBox.Text = String.Empty; + } + catch (Exception exception) + { + helpers.Engine.Log($"{nameof(QuarantinedReservationSection)}|{nameof(TryLeaveQuarantineButton_Pressed)}|{exception}"); + leaveQuarantinedStateExceptionTextBox.Text = $"[{DateTime.Now}] {exception}"; + } + + GenerateUi(); + OnUiUpdateRequired(this, new EventArgs()); + } + + private void ClearReservationHistorySections() + { + ReservationHistoryCollapseButton.LinkedWidgets.Clear(); + reservationHistorySections.Clear(); + } + + private void ClearResourceHistorySections() + { + ResourceHistoryCollapseButton.LinkedWidgets.Clear(); + resourceHistorySections.Clear(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + int labelColumnSpan = isOrder ? 2 : 1; + int valueColumnSpan = isOrder ? 2 : 1; + int valueColumnIdx = isOrder ? 3 : 2; + + AddWidget(collapseButton, ++row, 0); + AddWidget(reservationTitleLabel, row, 1, 1, 3); + + AddReservationInfoWidgets(ref row, labelColumnSpan, valueColumnIdx, valueColumnSpan); + + if (!isOrder) + { + // Display functions and their resource here + AddWidget(whiteSpace1, ++row, 0, 1, valueColumnSpan + 1); + AddSection(resourceAssignmentSection, new SectionLayout(++row, 1)); + row += resourceAssignmentSection.RowCount; + } + + AddWidget(whiteSpace2, ++row, 0, 1, valueColumnSpan + 1); + + AddWidget(LeaveQuarantinedStateButton, ++row, 1, 1, valueColumnSpan + 1); + if (!String.IsNullOrWhiteSpace(leaveQuarantinedStateExceptionTextBox.Text)) + { + AddWidget(leaveQuarantinedStateExceptionTextBox, ++row, 1, 1, valueColumnSpan + 1); + } + + AddWidget(ReservationHistoryCollapseButton, ++row, 1, 1, valueColumnSpan + 1); + if (!ReservationHistoryCollapseButton.IsCollapsed && !reservationHistorySections.Any()) + { + AddWidget(noReservationHistoryAvailableLabel, ++row, 1, 1, valueColumnSpan + 1); + } + else + { + foreach (var historySection in reservationHistorySections.OrderBy(x => x.Time)) + { + AddSection(historySection, new SectionLayout(++row, 1)); + row += historySection.RowCount; + } + } + + if (!isOrder) + { + AddWidget(ResourceHistoryCollapseButton, ++row, 1, 1, valueColumnSpan + 1); + if (!ResourceHistoryCollapseButton.IsCollapsed && !resourceHistorySections.Any()) + { + AddWidget(noContributingResourceHistoryAvailableLabel, ++row, 1, 1, valueColumnSpan + 1); + } + else + { + foreach (var historySection in resourceHistorySections.OrderBy(x => x.Time)) + { + AddSection(historySection, new SectionLayout(++row, 1)); + row += historySection.RowCount; + } + } + } + + if (quarantinedServiceSections.Any()) + { + AddWidget(whiteSpace3, ++row, 0, 1, valueColumnSpan + 1); + AddWidget(quarantinedServicesTitle, ++row, 1, 1, valueColumnSpan + 1); + } + + foreach (var serviceSection in quarantinedServiceSections) + { + AddSection(serviceSection, new SectionLayout(++row, 1)); + row += serviceSection.RowCount; + } + } + + private void AddReservationInfoWidgets(ref int row, int labelColumnSpan, int valueColumnIdx, int valueColumnSpan) + { + AddWidget(reservationNameTitle, ++row, 1, 1, labelColumnSpan); + AddWidget(reservationNameLabel, row, valueColumnIdx, 1, valueColumnSpan); + + AddWidget(reservationIdTitle, ++row, 1, 1, labelColumnSpan); + AddWidget(reservationIdLabel, row, valueColumnIdx, 1, valueColumnSpan); + + AddWidget(reservationStartTitle, ++row, 1, 1, labelColumnSpan); + AddWidget(reservationStartLabel, row, valueColumnIdx, 1, valueColumnSpan); + + AddWidget(reservationEndTitle, ++row, 1, 1, labelColumnSpan); + AddWidget(reservationEndLabel, row, valueColumnIdx, 1, valueColumnSpan); + } + + public ReservationInstance ReservationInstance { get; private set; } + + public CollapseButton ReservationHistoryCollapseButton { get; private set; } = new CollapseButton { IsCollapsed = true, CollapseText = "Hide Reservation History", ExpandText = "Show Reservation History" }; + + public CollapseButton ResourceHistoryCollapseButton { get; private set; } = new CollapseButton { IsCollapsed = true, CollapseText = "Hide Contributing Resource History", ExpandText = "Show Contributing Resource History" }; + + public Button LeaveQuarantinedStateButton { get; private set; } = new Button("Leave Quarantined State"); + + /// + /// Displays a line for each node in the service representing a function and the resource assigned to it. + /// + private sealed class ResourceAssignmentSection : Section + { + private readonly List functionSections = new List(); + private readonly Helpers helpers; + + private ServiceReservationInstance serviceReservationInstance; + + public ResourceAssignmentSection(Helpers helpers, ServiceReservationInstance serviceReservationInstance) + { + this.helpers = helpers ?? throw new ArgumentNullException(nameof(helpers)); + this.serviceReservationInstance = serviceReservationInstance ?? throw new ArgumentNullException(nameof(serviceReservationInstance)); + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + var serviceDefinition = SrmManagers.ServiceManager.GetServiceDefinition(serviceReservationInstance.ServiceDefinitionID); + var functions = serviceReservationInstance.GetFunctionData(); + var resourceUsageDefinitions = serviceReservationInstance.GetAllServiceResourceUsageDefinitions(); + var quarantinedResourceUsageDefinitions = serviceReservationInstance.QuarantinedResources; + foreach (var node in serviceDefinition.Diagram.Nodes) + { + string resourcePoolName = node.Properties.FirstOrDefault(x => x.Name.Equals("Resource Pool"))?.Value; + + Resource functionResource; + var resourceUsageDefinition = resourceUsageDefinitions.FirstOrDefault(x => x.ServiceDefinitionNodeID.Equals(node.ID)); + var quarantinedResourceUsage = quarantinedResourceUsageDefinitions.FirstOrDefault(x => (x.QuarantinedResourceUsage is ServiceResourceUsageDefinition srud && srud.ServiceDefinitionNodeID.Equals(node.ID))); + if (resourceUsageDefinition != null) + { + functionResource = SrmManagers.ResourceManager.GetResource(resourceUsageDefinition.GUID); + } + else if (quarantinedResourceUsage != null) + { + functionResource = SrmManagers.ResourceManager.GetResource(quarantinedResourceUsage.QuarantinedResourceUsage.GUID); + } + else + { + functionResource = null; + } + + var resourcePool = SrmManagers.ResourceManager.GetResourcePools(new ResourcePool { Name = resourcePoolName }).FirstOrDefault(); + var resourceCapabilityUsages = GetResourceCapabilityUsages(functions.FirstOrDefault(x => x.Id == node.ID)); + + var eligbleResourceResult = SrmManagers.ResourceManager.GetEligibleResources(new EligibleResourceContext + { + ContextId = node.Configuration.FunctionID, + TimeRange = new Net.Time.TimeRangeUtc(serviceReservationInstance.Start.ToUniversalTime(), serviceReservationInstance.End.ToUniversalTime()), + ResourceFilter = ResourceExposers.PoolGUIDs.Contains(resourcePool.GUID), + RequiredCapabilities = resourceCapabilityUsages + }); + + var functionSection = new FunctionSection(node.Label, node.Configuration.FunctionID, functionResource, eligbleResourceResult.EligibleResources); + functionSection.UpdateResourceButton.Pressed += UpdateResourceButton_Pressed; + functionSections.Add(functionSection); + } + } + + private void UpdateResourceButton_Pressed(object sender, EventArgs e) + { + var functionSection = functionSections.FirstOrDefault(x => x.UpdateResourceButton.Equals(sender)); + if (functionSection == null) return; + + var request = new AssignResourceRequest + { + TargetNodeLabel = functionSection.NodeLabel, + NewResourceId = (functionSection.SelectedResource == null) ? Guid.Empty : functionSection.SelectedResource.ID + }; + + helpers.Engine.Log($"{nameof(ResourceAssignmentSection)}|{nameof(UpdateResourceButton_Pressed)}|Request: {JsonConvert.SerializeObject(request)}"); + + try + { + helpers.Engine.Log($"{nameof(ResourceAssignmentSection)}|{nameof(UpdateResourceButton_Pressed)}|Assigning resource {functionSection.SelectedResource?.Name} with ID {request.NewResourceId} to node {request.TargetNodeLabel}"); + serviceReservationInstance = serviceReservationInstance.AssignResources((Engine)helpers.Engine, true, new[] { request }); + + functionSection.Update(functionSection.SelectedResource); + } + catch (Exception exception) + { + functionSection.Exception = exception; + helpers.Engine.Log($"{nameof(ResourceAssignmentSection)}|{nameof(UpdateResourceButton_Pressed)}|{exception}"); + } + } + + private List GetResourceCapabilityUsages(Function function) + { + List resourceCapabilityUsages = new List(); + if (function == null) return resourceCapabilityUsages; + + foreach (var profileParameter in function.Parameters) + { + if (!profileParameter.Capability) continue; + + helpers.Engine.Log($"{nameof(ResourceAssignmentSection)}|{nameof(ResourceAssignmentSection)}|Function {function.Name}, Profile Parameter {profileParameter.Name} has value {profileParameter.Value}"); + + var resourceCapabilityUsage = new ResourceCapabilityUsage { CapabilityProfileID = profileParameter.Id }; + switch (profileParameter.Type) + { + case ParameterType.Number: + resourceCapabilityUsage.RequiredRangePoint = Convert.ToDouble(profileParameter.Value); + break; + case ParameterType.Discrete: + resourceCapabilityUsage.RequiredDiscreet = Convert.ToString(profileParameter.Value); + break; + default: + resourceCapabilityUsage.RequiredString = Convert.ToString(profileParameter.Value); + break; + } + + resourceCapabilityUsages.Add(resourceCapabilityUsage); + } + + return resourceCapabilityUsages; + } + + private void GenerateUi() + { + int row = -1; + + foreach (var functionSection in functionSections) + { + AddSection(functionSection, new SectionLayout(++row, 0)); + row += functionSection.RowCount; + } + } + + private sealed class FunctionSection : Section + { + private const string None = "None"; + + private readonly List availableResources; + private readonly Resource originalResource; + + private readonly Label functionNameTitle = new Label { Style = TextStyle.Heading }; + private readonly Label currentResourceTitle = new Label("Current Resource"); + private readonly Label currentResourceLabel = new Label(); + private readonly Label availableResourcesTitle = new Label("Available Resource(s)"); + private readonly DropDown availableResourcesDropDown = new DropDown { IsDisplayFilterShown = true }; + private readonly TextBox exceptionTextBox = new TextBox { IsMultiline = true, IsVisible = false, Height = 300 }; + + public FunctionSection(string nodeLabel, Guid functionId, Resource resource, IEnumerable availableResources) + { + this.availableResources = availableResources.ToList(); + originalResource = resource; + NodeLabel = nodeLabel; + FunctionId = functionId; + + functionNameTitle.Text = NodeLabel; + currentResourceLabel.Text = (resource == null) ? None : resource.Name; + + Initialize(); + GenerateUi(); + } + + public void Update(Resource resource) + { + currentResourceLabel.Text = (resource == null) ? None : resource.Name; + } + + private void Initialize() + { + List options = new List(new [] { None }); + options.AddRange(availableResources.Select(x => x.Name).OrderBy(x => x)); + availableResourcesDropDown.Options = options; + + availableResourcesDropDown.Selected = (availableResources.Contains(originalResource)) ? originalResource.Name : None; + } + + private void GenerateUi() + { + int row = -1; + + AddWidget(functionNameTitle, ++row, 0, 1, 2); + + AddWidget(currentResourceTitle, ++row, 0); + AddWidget(currentResourceLabel, row, 1); + + AddWidget(availableResourcesTitle, ++row, 0); + AddWidget(availableResourcesDropDown, row, 1); + + AddWidget(UpdateResourceButton, ++row, 1); + + AddWidget(exceptionTextBox, row, 1); + } + + public Button UpdateResourceButton { get; private set; } = new Button("Edit Resource"); + + public string NodeLabel { get; private set; } + + public Guid FunctionId { get; private set; } + + public Resource SelectedResource + { + get + { + if (availableResourcesDropDown.Selected == None) return null; + return availableResources.FirstOrDefault(x => x.Name.Equals(availableResourcesDropDown.Selected)); + } + } + + public Exception Exception + { + set + { + exceptionTextBox.Text = (value == null) ? String.Empty : value.ToString(); + exceptionTextBox.IsVisible = !String.IsNullOrWhiteSpace(exceptionTextBox.Text); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindReservationLoggingDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindReservationLoggingDialog.cs new file mode 100644 index 0000000..288873e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindReservationLoggingDialog.cs @@ -0,0 +1,128 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations +{ + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + + public class FindReservationLoggingDialog : Dialog + { + private readonly string orderLoggingPath = @"C:\Skyline_Data\OrderLogging"; + + private readonly Helpers helpers; + + private readonly Label findReservationsLoggingLabel = new Label("Find Reservation Order Logging") { Style = TextStyle.Heading }; + private readonly Label reservationIdLabel = new Label("GUID"); + private readonly Button enterCurrentReservationIdButton = new Button("Enter Current ID") { Width = 200 }; + + private readonly List responseSections = new List(); + + public FindReservationLoggingDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Find Reservation Order Logging"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private TextBox ReservationIdTextBox { get; set; } + + private Button FindOrderLoggingByReservationIdButton { get; set; } + + private void Initialize() + { + ReservationIdTextBox = new TextBox { PlaceHolder = "GUID", ValidationText = "Invalid GUID", Width = 400 }; + + FindOrderLoggingByReservationIdButton = new Button("Find By GUID") { Width = 150 }; + FindOrderLoggingByReservationIdButton.Pressed += FindOrderLoggingByReservationIdButton_Pressed; + + enterCurrentReservationIdButton.Pressed += (sender, args) => ReservationIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + } + + private void ShowRequestResult(string header, params string[] results) + { + var requestResultSection = new RequestResultSection(header, results); + requestResultSection.SetContentTextBoxWidth(1400); + requestResultSection.SetContentTextBoxHeight(800); + + responseSections.Add(requestResultSection); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(findReservationsLoggingLabel, ++row, 0, 1, 5); + + AddWidget(reservationIdLabel, ++row, 0, 1, 2); + AddWidget(ReservationIdTextBox, row, 2); + AddWidget(FindOrderLoggingByReservationIdButton, row, 3); + AddWidget(enterCurrentReservationIdButton, ++row, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + + private void ShowOrderDetails() + { + GenerateUi(); + } + + private void UpdateReservationIdTextBoxValidation(UIValidationState validationState, string validationText) + { + ReservationIdTextBox.ValidationState = validationState; + ReservationIdTextBox.ValidationText = validationText; + } + + private void FindOrderLoggingByReservationIdButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(ReservationIdTextBox.Text, out var guid)) + { + ShowOrderDetails(); + UpdateReservationIdTextBoxValidation(UIValidationState.Invalid, "Invalid GUID"); + return; + } + + try + { + var combinedPath = Path.Combine(orderLoggingPath, guid.ToString() + ".txt"); + if (File.Exists(combinedPath)) + { + var orderLoggingContent = File.ReadAllText(combinedPath); + ShowRequestResult($"Order Logging {guid}", orderLoggingContent); + UpdateReservationIdTextBoxValidation(UIValidationState.Valid, string.Empty); + } + else + { + UpdateReservationIdTextBoxValidation(UIValidationState.Invalid, "Order logging file path couldn't be found"); + } + } + catch (Exception ex) + { + helpers.Log(nameof(FindReservationLoggingDialog), nameof(FindOrderLoggingByReservationIdButton_Pressed), $"Something went wrong while opening of order logging file {ex}"); + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindReservationsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindReservationsDialog.cs new file mode 100644 index 0000000..afafbcb --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindReservationsDialog.cs @@ -0,0 +1,164 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Debug_2.Debug.Reservations; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Helpers = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers; + + public class FindReservationsDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label findReservationsLabel = new Label("Find Reservation"){Style = TextStyle.Heading}; + private readonly Label reservationNameLabel = new Label("Name"); + private readonly Label reservationIdLabel = new Label("GUID"); + private readonly Button enterCurrentOrderIdButton = new Button("Enter Current ID") { Width = 200 }; + private readonly List responseSections = new List(); + + public FindReservationsDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Find Reservation"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private TextBox ReservationNameTextBox { get; set; } + + private TextBox ReservationIdTextBox { get; set; } + + private Button FindByReservationNameButton { get; set; } + + private Button FindByReservationIdButton { get; set; } + + private void Initialize() + { + ReservationNameTextBox = new TextBox { PlaceHolder = "Name", Width = 400 }; + ReservationIdTextBox = new TextBox { PlaceHolder = "GUID", ValidationText = "Invalid GUID", Width = 400 }; + + FindByReservationNameButton = new Button("Find By Name") { Width = 150 }; + FindByReservationNameButton.Pressed += FindByReservationNameButton_Pressed; + + FindByReservationIdButton = new Button("Find By GUID") { Width = 150 }; + FindByReservationIdButton.Pressed += FindByReservationIdButton_Pressed; + + enterCurrentOrderIdButton.Pressed += (sender, args) => ReservationIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(findReservationsLabel, ++row, 0, 1, 5); + + AddWidget(reservationNameLabel, ++row, 0, 1, 2); + AddWidget(ReservationNameTextBox, row, 2); + AddWidget(FindByReservationNameButton, row, 3); + + AddWidget(reservationIdLabel, ++row, 0, 1, 2); + AddWidget(ReservationIdTextBox, row, 2); + AddWidget(FindByReservationIdButton, row, 3); + AddWidget(enterCurrentOrderIdButton, ++row, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + + private void ShowOrderDetails(ReservationInstance reservationInstance, string serviceConfiguration) + { + var reservationDetailsSection = new ReservationDetailsSection(helpers, reservationInstance, serviceConfiguration); + reservationDetailsSection.RegenerateUi += (o, e) => GenerateUi(); + + responseSections.Add(reservationDetailsSection); + + GenerateUi(); + } + + private void FindByReservationNameButton_Pressed(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(ReservationNameTextBox.Text)) + { + ReservationIdTextBox.Text = String.Empty; + ShowOrderDetails(null, null); + ReservationNameTextBox.ValidationText = "Fill out the Name of a reservation"; + ReservationNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstances = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(ReservationInstanceExposers.Name.Contains(ReservationNameTextBox.Text))); + if (!reservationInstances.Any()) + { + ReservationIdTextBox.Text = String.Empty; + ShowOrderDetails(null, null); + ReservationNameTextBox.ValidationText = "Unable to find a reservation with the specified Name"; + ReservationNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstance = reservationInstances.First(); + + ReservationNameTextBox.Text = reservationInstance.Name; + ReservationIdTextBox.Text = reservationInstance.ID.ToString(); + ReservationNameTextBox.ValidationState = UIValidationState.Valid; + + helpers.OrderManagerElement.TryGetServiceConfigurations(reservationInstance.ID, out var serviceConfigurations); + string serviceConfiguration = JsonConvert.SerializeObject(serviceConfigurations); + + ShowOrderDetails(reservationInstance, serviceConfiguration); + } + + private void FindByReservationIdButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(ReservationIdTextBox.Text, out var guid)) + { + ReservationNameTextBox.Text = String.Empty; + ShowOrderDetails(null, null); + ReservationNameTextBox.ValidationText = "Unable to parse the GUID"; + ReservationIdTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstance = DataMinerInterface.ResourceManager.GetReservationInstance(helpers, guid); + if (reservationInstance == null) + { + ReservationNameTextBox.Text = String.Empty; + ShowOrderDetails(null, null); + ReservationNameTextBox.ValidationText = "No reservations found with the given ID"; + ReservationIdTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + ReservationNameTextBox.Text = reservationInstance.Name; + ReservationIdTextBox.Text = reservationInstance.ID.ToString(); + ReservationIdTextBox.ValidationState = UIValidationState.Valid; + + helpers.OrderManagerElement.TryGetServiceConfigurations(reservationInstance.ID, out var serviceConfigurations); + string serviceConfiguration = JsonConvert.SerializeObject(serviceConfigurations); + + ShowOrderDetails(reservationInstance, serviceConfiguration); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindReservationsWithFiltersDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindReservationsWithFiltersDialog.cs new file mode 100644 index 0000000..2f6f6ea --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/FindReservationsWithFiltersDialog.cs @@ -0,0 +1,166 @@ +namespace Debug_2.Debug.Reservations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class FindReservationsWithFiltersDialog : DebugDialog + { + private readonly GetReservationsSection getReservationsSection; + + private readonly Label actionsLabel = new Label("Actions") { Style = TextStyle.Heading }; + + private readonly Button showJsonButton = new Button("Show Reservations JSON"); + private readonly Button deleteButton = new Button("Delete Reservations"); + private readonly CheckBox deleteSafetyCheckbox = new CheckBox("Confirm Delete"); + private readonly Button getIdsButton = new Button("Get IDs"); + private readonly Button considerAsServiceAndCancelButton = new Button("Consider as Service and Cancel"); + private readonly CheckBox cancelSafetyCheckbox = new CheckBox("Confirm Cancel"); + private readonly Button deleteIfContributingIsNowhereAssignedButton = new Button("Delete if contributing resource is not assigned anywhere"); + private readonly CheckBox deleteIfContributingIsNowhereAssignedButtonConfirmCheckbox = new CheckBox("Confirm Delete"); + + public FindReservationsWithFiltersDialog(Helpers helpers) : base(helpers) + { + Title = "Find Reservations with Filters"; + + getReservationsSection = new GetReservationsSection(helpers); + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + getReservationsSection.RegenerateUiRequired += GetReservationsSection_RegenerateUi; + + showJsonButton.Pressed += ShowJsonButton_Pressed; + + deleteButton.Pressed += DeleteButton_Pressed; + + getIdsButton.Pressed += GetIdsButton_Pressed; + + considerAsServiceAndCancelButton.Pressed += ConsiderAsServiceAndCancelButton_Pressed; + + deleteIfContributingIsNowhereAssignedButton.Pressed += DeleteIfContributingIsNowhereAssignedButton_Pressed; + } + + private void DeleteIfContributingIsNowhereAssignedButton_Pressed(object sender, EventArgs e) + { + using (UiDisabler.StartNew(this)) + { + if (!deleteIfContributingIsNowhereAssignedButtonConfirmCheckbox.IsChecked) return; + + var contributingReservationsToRemove = new List(); + + foreach (var reservation in getReservationsSection.SelectedReservations) + { + var orderReservations = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, ReservationInstanceExposers.ResourceIDsInReservationInstance.Contains(reservation.ID)); + + if (!orderReservations.Any()) + { + contributingReservationsToRemove.Add(reservation); + } + } + + DataMinerInterface.ResourceManager.RemoveReservationInstances(helpers, contributingReservationsToRemove.ToArray()); + + ShowRequestResult("Removed contributing reservations", string.Join("\n", contributingReservationsToRemove.Select(r => r.Name))); + GenerateUi(); + } + } + + private void ConsiderAsServiceAndCancelButton_Pressed(object sender, EventArgs e) + { + using (UiDisabler.StartNew(this)) + { + if (!cancelSafetyCheckbox.IsChecked) return; + + var messages = new List(); + + foreach (var reservation in getReservationsSection.SelectedReservations) + { + var service = Service.FromReservationInstance(helpers, reservation); + + var order = helpers.OrderManager.GetOrder(service.OrderReferences.First()); + + service.Cancel(helpers, order); + + messages.Add($"{service.Name} part of order {order.Name}"); + } + + ShowRequestResult("Cancelled Services", string.Join("\n", messages)); + GenerateUi(); + } + } + + private void GetIdsButton_Pressed(object sender, EventArgs e) + { + ShowRequestResult("Reservation IDs", string.Join("\n", getReservationsSection.SelectedReservations.Select(r => r.ID))); + GenerateUi(); + } + + private void DeleteButton_Pressed(object sender, EventArgs e) + { + if (!deleteSafetyCheckbox.IsChecked) return; + + DataMinerInterface.ResourceManager.RemoveReservationInstances(helpers, getReservationsSection.SelectedReservations.ToArray()); + + ShowRequestResult("Removed Reservations", string.Join("\n", getReservationsSection.SelectedReservations.Select(r => r.Name))); + GenerateUi(); + } + + private void GetReservationsSection_RegenerateUi(object sender, EventArgs e) + { + getReservationsSection.RegenerateUi(); + GenerateUi(); + } + + private void ShowJsonButton_Pressed(object sender, EventArgs e) + { + ShowRequestResult("Serialized Reservations", string.Join("\n", getReservationsSection.SelectedReservations.Select(r => JsonConvert.SerializeObject(r)))); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddSection(getReservationsSection, new SectionLayout(++row, 0)); + row += getReservationsSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(actionsLabel, ++row, 0); + AddWidget(showJsonButton, ++row, 0); + AddWidget(deleteButton, ++row, 0); + AddWidget(deleteSafetyCheckbox, row, 1); + AddWidget(getIdsButton, ++row, 0); + AddWidget(considerAsServiceAndCancelButton, ++row, 0); + AddWidget(cancelSafetyCheckbox, row, 1); + AddWidget(deleteIfContributingIsNowhereAssignedButton, ++row, 0); + AddWidget(deleteIfContributingIsNowhereAssignedButtonConfirmCheckbox, row, 1); + AddWidget(new WhiteSpace(), ++row, 0); + + AddResponseSections(row); + } + + protected override void HandleEnabledUpdate() + { + base.HandleEnabledUpdate(); + + getReservationsSection.IsEnabled = IsEnabled; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/GetReservationsSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/GetReservationsSection.cs new file mode 100644 index 0000000..966e064 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/GetReservationsSection.cs @@ -0,0 +1,198 @@ +namespace Debug_2.Debug.Reservations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Library.UI.Filters; + using Skyline.DataMiner.DeveloperCommunityLibrary.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class GetReservationsSection : YleSection + { + private readonly Label header = new Label("Get Reservations with filters") { Style = TextStyle.Heading }; + + private readonly FilterSection reservationIdFilterSection = new GuidFilterSection("Reservation ID", x => ReservationInstanceExposers.ID.Equal((Guid)x)); + + private readonly FilterSection reservationServiceDefinitionIdFilterSection = new GuidFilterSection("Service Definition ID", x => ServiceReservationInstanceExposers.ServiceDefinitionID.Equal((Guid)x)); + + private readonly FilterSection reservationNameEqualsFilterSection = new StringFilterSection("Reservation Name Equals", x => ReservationInstanceExposers.Name.Equal((string)x)); + + private readonly FilterSection reservationNameContainsFilterSection = new StringFilterSection("Reservation Name Contains", x => ReservationInstanceExposers.Name.Contains((string)x)); + + private readonly FilterSection reservationStartFromFilterSection = new DateTimeFilterSection("Reservation Start From", x => ReservationInstanceExposers.Start.GreaterThanOrEqual((DateTime)x)); + + private readonly FilterSection reservationStartUntilFilterSection = new DateTimeFilterSection("Reservation Start Until", x => ReservationInstanceExposers.Start.LessThanOrEqual((DateTime)x)); + + private readonly FilterSection reservationEndFromFilterSection = new DateTimeFilterSection("Reservation End From", x => ReservationInstanceExposers.End.GreaterThanOrEqual((DateTime)x)); + + private readonly FilterSection reservationEndUntilFilterSection = new DateTimeFilterSection("Reservation End Until", x => ReservationInstanceExposers.End.LessThanOrEqual((DateTime)x)); + + private readonly List> resourceFilterSections = new List>(); + private readonly Button addResourceFilterButton = new Button("Add Resource Filter"); + + private readonly List> propertyFilterSections = new List>(); + private readonly Button addPropertyFilterButton = new Button("Add Property Filter"); + + private readonly Button getReservationsBasedOnFiltersButton = new Button("Get Reservations Based on Filters") { Style = ButtonStyle.CallToAction }; + private List reservationsBasedOnFilters = new List(); + + private readonly Label amountOfReservationsLabel = new Label(string.Empty); + private readonly CheckBoxList selectReservationsCheckBoxList = new CheckBoxList(); + private readonly Button selectAllButton = new Button("Select All") { IsVisible = false }; + private readonly Button unselectAllButton = new Button("Unselect All") { IsVisible = false }; + + public GetReservationsSection(Helpers helpers) : base(helpers) + { + addResourceFilterButton.Pressed += AddResourceFilterButton_Pressed; + + addPropertyFilterButton.Pressed += AddPropertyFilterButton_Pressed; + + getReservationsBasedOnFiltersButton.Pressed += GetReservationsBasedOnFiltersButton_Pressed; + + selectAllButton.Pressed += (o, e) => selectReservationsCheckBoxList.CheckAll(); + unselectAllButton.Pressed += (o, e) => selectReservationsCheckBoxList.UncheckAll(); + + selectReservationsCheckBoxList.Changed += (o, e) => SelectedReservations = GetIndividuallySelectedReservations(); + + GenerateUi(); + } + + private void GetReservationsBasedOnFiltersButton_Pressed(object sender, EventArgs e) + { + SelectedReservations = GetReservationsBasedOnFilters(); + selectAllButton.IsVisible = SelectedReservations.Any(); + unselectAllButton.IsVisible = SelectedReservations.Any(); + RegenerateUiRequired?.Invoke(this, EventArgs.Empty); + } + + public IEnumerable SelectedReservations { get; private set; } = new List(); + + public event EventHandler RegenerateUiRequired; + + public event EventHandler> ReservationsUpdated; + + public void AddDefaultPropertyFilter(string propertyName, string propertyValue) + { + var propertyFilterSection = new StringPropertyFilterSection("Property", (propName, propValue) => ReservationInstanceExposers.Properties.DictStringField((string)propName).Equal((string)propValue)); + + propertyFilterSection.SetDefault(propertyName, propertyValue); + + propertyFilterSections.Add(propertyFilterSection); + + RegenerateUiRequired?.Invoke(this, EventArgs.Empty); + } + + public override void RegenerateUi() + { + GenerateUi(); + } + + private IEnumerable GetReservationsBasedOnFilters() + { + if (!this.ActiveFiltersAreValid()) return new List(); + + reservationsBasedOnFilters = SrmManagers.ResourceManager.GetReservationInstances(this.GetCombinedFilterElement()).ToList(); + + int previousAmountOfOptions = selectReservationsCheckBoxList.Options.Count(); + + amountOfReservationsLabel.Text = $"Found {reservationsBasedOnFilters.Count} matching reservations"; + + selectReservationsCheckBoxList.SetOptions(reservationsBasedOnFilters.Select(r => r.Name).OrderBy(name => name).ToList()); + selectReservationsCheckBoxList.CheckAll(); + + var selectedResources = GetIndividuallySelectedReservations(); + + if (selectReservationsCheckBoxList.Options.Count() != previousAmountOfOptions) RegenerateUiRequired?.Invoke(this, EventArgs.Empty); + + return selectedResources; + } + + private IEnumerable GetIndividuallySelectedReservations() + { + var selectedReservationNames = selectReservationsCheckBoxList.Checked; + + var selectedReservations = reservationsBasedOnFilters.Where(r => selectedReservationNames.Contains(r.Name)).ToList(); + + return selectedReservations; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(header, ++row, 0, 1, 2); + + AddSection(reservationNameEqualsFilterSection, new SectionLayout(++row, 0)); + + AddSection(reservationNameContainsFilterSection, new SectionLayout(++row, 0)); + + AddSection(reservationIdFilterSection, new SectionLayout(++row, 0)); + + AddSection(reservationStartFromFilterSection, new SectionLayout(++row, 0)); + + AddSection(reservationStartUntilFilterSection, new SectionLayout(++row, 0)); + + AddSection(reservationEndFromFilterSection, new SectionLayout(++row, 0)); + + AddSection(reservationEndUntilFilterSection, new SectionLayout(++row, 0)); + + AddSection(reservationServiceDefinitionIdFilterSection, new SectionLayout(++row, 0)); + + foreach (var resourceFilterSection in resourceFilterSections) + { + AddSection(resourceFilterSection, new SectionLayout(++row, 0)); + } + + foreach (var propertyFilterSection in propertyFilterSections) + { + AddSection(propertyFilterSection, new SectionLayout(++row, 0)); + } + + AddWidget(addResourceFilterButton, ++row, 0); + + AddWidget(addPropertyFilterButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(getReservationsBasedOnFiltersButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(amountOfReservationsLabel, 0, 3); + AddWidget(selectReservationsCheckBoxList, 1, 3, selectReservationsCheckBoxList.Options.Any() ? selectReservationsCheckBoxList.Options.Count() : 1, 1, verticalAlignment: VerticalAlignment.Top); + AddWidget(selectAllButton, 1, 4, verticalAlignment: VerticalAlignment.Top); + AddWidget(unselectAllButton, 1, 5, verticalAlignment: VerticalAlignment.Top); + } + + private void AddPropertyFilterButton_Pressed(object sender, EventArgs e) + { + var propertyFilterSection = new StringPropertyFilterSection("Property", (propertyName, propertyValue) => ReservationInstanceExposers.Properties.DictStringField((string)propertyName).Equal((string)propertyValue)); + + propertyFilterSections.Add(propertyFilterSection); + + RegenerateUiRequired?.Invoke(this, EventArgs.Empty); + } + + private void AddResourceFilterButton_Pressed(object sender, EventArgs e) + { + var resourceFilterSection = new GuidFilterSection("Uses Resource ID", (resourceId) => ReservationInstanceExposers.ResourceIDsInReservationInstance.Contains((Guid)resourceId)); + + resourceFilterSections.Add(resourceFilterSection); + + RegenerateUiRequired?.Invoke(this, EventArgs.Empty); + } + + protected override void HandleVisibilityAndEnabledUpdate() + { + resourceFilterSections.ForEach(f => f.IsEnabled = IsEnabled); + + propertyFilterSections.ForEach(f => f.IsEnabled = IsEnabled); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/MoveToQuarantinedStateDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/MoveToQuarantinedStateDialog.cs new file mode 100644 index 0000000..ced1051 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/MoveToQuarantinedStateDialog.cs @@ -0,0 +1,193 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Library.Solutions.SRM; + + public class MoveToQuarantinedStateDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label findReservationsLabel = new Label("Find Reservation") { Style = TextStyle.Heading }; + private readonly Label reservationNameLabel = new Label("Name"); + private readonly Label reservationIdLabel = new Label("GUID"); + private readonly Label srmStateLabel = new Label("SRM State"); + private readonly Button enterCurrentOrderIdButton = new Button("Enter Current ID") { Width = 200 }; + + private ReservationInstance reservationInstance; + + public MoveToQuarantinedStateDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Move Reservation To Quarantined State"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private TextBox ReservationNameTextBox { get; set; } + + private TextBox ReservationIdTextBox { get; set; } + + private Button FindByReservationNameButton { get; set; } + + private Button FindByReservationIdButton { get; set; } + + public Button MoveToQuarantinedStateButton { get; } = new Button("Move to Quarantined State") { Width = 200, IsEnabled = false }; + + public TextBox ExceptionTextBox { get; } = new TextBox { IsMultiline = true, Height = 300 }; + + private void Initialize() + { + ReservationNameTextBox = new TextBox { PlaceHolder = "Name", Width = 400 }; + ReservationIdTextBox = new TextBox { PlaceHolder = "GUID", ValidationText = "Invalid GUID", Width = 400 }; + + FindByReservationNameButton = new Button("Find By Name") { Width = 150 }; + FindByReservationNameButton.Pressed += FindByReservationNameButton_Pressed; + + FindByReservationIdButton = new Button("Find By GUID") { Width = 150 }; + FindByReservationIdButton.Pressed += FindByReservationIdButton_Pressed; + + enterCurrentOrderIdButton.Pressed += (sender, args) => ReservationIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + + MoveToQuarantinedStateButton.Pressed += MoveToQuarantinedStateButton_Pressed; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(findReservationsLabel, ++row, 0, 1, 5); + + AddWidget(reservationNameLabel, ++row, 0, 1, 2); + AddWidget(ReservationNameTextBox, row, 2); + AddWidget(FindByReservationNameButton, row, 3); + + AddWidget(reservationIdLabel, ++row, 0, 1, 2); + AddWidget(ReservationIdTextBox, row, 2); + AddWidget(FindByReservationIdButton, row, 3); + + AddWidget(enterCurrentOrderIdButton, ++row, 2); + + if (reservationInstance != null) + { + AddWidget(srmStateLabel, ++row, 0, 1, 2); + AddWidget(new Label(reservationInstance.Status.GetDescription()), row, 3); + } + + AddWidget(new WhiteSpace(), ++row, 1); + + AddWidget(MoveToQuarantinedStateButton, ++row, 0, 1, 5); + + if (!String.IsNullOrWhiteSpace(ExceptionTextBox.Text)) + { + AddWidget(ExceptionTextBox, row + 1, 0, 1, 5); + } + } + + private void FindByReservationNameButton_Pressed(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(ReservationNameTextBox.Text)) + { + ReservationIdTextBox.Text = String.Empty; + ReservationNameTextBox.ValidationText = "Fill out the Name of a reservation"; + ReservationNameTextBox.ValidationState = UIValidationState.Invalid; + MoveToQuarantinedStateButton.IsEnabled = false; + reservationInstance = null; + GenerateUi(); + return; + } + + var reservationInstances = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(ReservationInstanceExposers.Name.Contains(ReservationNameTextBox.Text))); + if (!reservationInstances.Any()) + { + ReservationIdTextBox.Text = String.Empty; + ReservationNameTextBox.ValidationText = "Unable to find a reservation with the specified Name"; + ReservationNameTextBox.ValidationState = UIValidationState.Invalid; + MoveToQuarantinedStateButton.IsEnabled = false; + reservationInstance = null; + GenerateUi(); + return; + } + + reservationInstance = reservationInstances.First(); + + ReservationNameTextBox.Text = reservationInstance.Name; + ReservationIdTextBox.Text = reservationInstance.ID.ToString(); + ReservationNameTextBox.ValidationState = UIValidationState.Valid; + + MoveToQuarantinedStateButton.IsEnabled = true; + + GenerateUi(); + } + + private void FindByReservationIdButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(ReservationIdTextBox.Text, out var guid)) + { + ReservationNameTextBox.Text = String.Empty; + ReservationNameTextBox.ValidationText = "Unable to parse the GUID"; + ReservationIdTextBox.ValidationState = UIValidationState.Invalid; + MoveToQuarantinedStateButton.IsEnabled = false; + reservationInstance = null; + GenerateUi(); + return; + } + + reservationInstance = DataMinerInterface.ResourceManager.GetReservationInstance(helpers, guid); + if (reservationInstance == null) + { + ReservationNameTextBox.Text = String.Empty; + ReservationNameTextBox.ValidationText = "No reservations found with the given ID"; + ReservationIdTextBox.ValidationState = UIValidationState.Invalid; + MoveToQuarantinedStateButton.IsEnabled = false; + reservationInstance = null; + GenerateUi(); + return; + } + + ReservationNameTextBox.Text = reservationInstance.Name; + ReservationIdTextBox.Text = reservationInstance.ID.ToString(); + ReservationIdTextBox.ValidationState = UIValidationState.Valid; + + MoveToQuarantinedStateButton.IsEnabled = true; + + GenerateUi(); + } + + private void MoveToQuarantinedStateButton_Pressed(object sender, EventArgs e) + { + if (reservationInstance == null) return; + + try + { + reservationInstance.IsQuarantined = true; + reservationInstance = SrmManagers.ResourceManager.AddOrUpdateReservationInstances(true, reservationInstance).FirstOrDefault(); + ExceptionTextBox.Text = String.Empty; + } + catch(Exception exception) + { + ExceptionTextBox.Text = exception.ToString(); + helpers.Log(nameof(MoveToQuarantinedStateDialog), nameof(MoveToQuarantinedStateButton_Pressed), "Something went wrong: " + exception); + } + + GenerateUi(); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/ReservationDetailsSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/ReservationDetailsSection.cs new file mode 100644 index 0000000..1401b4e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/ReservationDetailsSection.cs @@ -0,0 +1,207 @@ +namespace Debug_2.Debug.Reservations +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Text; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.History; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Net.ToolsSpace.Collections; + using SLDataGateway.API.Querying; + + public class ReservationDetailsSection : ResponseSection + { + private readonly CollapseButton collapseButton; + private readonly Label header; + private readonly List propertySections = new List(); + private readonly Label noReservationHistoryAvailableLabel = new Label("No Reservation Instance History Available"); + private readonly List reservationHistorySections = new List(); + private readonly bool isOrder; + private readonly Helpers helpers; + private readonly Button logButton = new Button("Log Reservation JSON"); + private readonly CollapseButton reservationHistoryCollapseButton = new CollapseButton { IsCollapsed = true, CollapseText = "Hide Reservation History", ExpandText = "Show Reservation History" }; + + public ReservationDetailsSection(Helpers helpers, ReservationInstance reservationInstance, string serviceConfiguration) + { + if (reservationInstance == null) + { + header = new Label("Error: no reservation found"); + collapseButton = new CollapseButton(true) { CollapseText = "-", ExpandText = "+", Width = 44 }; + return; + } + + this.helpers = helpers; + Reservation = reservationInstance; + + isOrder = reservationInstance.Properties.Any(x => x.Key.Equals("Booking Manager") && x.Value != null && x.Value.Equals("Order Booking Manager")); + + this.header = new Label($"Reservation {reservationInstance.Name} ({reservationInstance.ID})") { Style = TextStyle.Heading }; + + foreach (var property in reservationInstance.GetType().GetProperties()) + { + if (!property.CanRead) continue; + + object value = property.GetValue(reservationInstance); + if (value == null) continue; + + if (property.Name.Equals("Properties") && value is JSONSerializableDictionary) + { + foreach (KeyValuePair kvp in (JSONSerializableDictionary)value) + { + propertySections.Add(new PropertySection($"Properties[{kvp.Key}]", kvp.Value)); + } + } + else + { + propertySections.Add(new PropertySection(property.Name, value)); + } + } + + propertySections.Add(new PropertySection("Service Configuration", serviceConfiguration)); + + this.collapseButton = new CollapseButton(propertySections.SelectMany(x => x.Widgets), true) { CollapseText = "-", ExpandText = "+", Width = 44 }; + + logButton.Pressed += (sender, e) => helpers.Log(nameof(ReservationDetailsSection), "LogButton Pressed", Reservation.ToJson()); + reservationHistoryCollapseButton.Pressed += ReservationHistoryButton_Pressed; + + GenerateUi(); + } + + public ReservationInstance Reservation { get; } + + public event EventHandler RegenerateUi; + + public override void Collapse() + { + collapseButton.IsCollapsed = true; + } + + private void ReservationHistoryButton_Pressed(object sender, EventArgs e) + { + if (Reservation == null || reservationHistoryCollapseButton.IsCollapsed) return; + + try + { + string subjectId = $"ReservationInstanceID_{Reservation.ID}"; + var filter = new ANDFilterElement(HistoryChangeExposers.SubjectID.Equal(subjectId, StringComparison.OrdinalIgnoreCase)); + var response = (ManagerStorePagingResponse)helpers.Engine.SendSLNetSingleResponseMessage(new ManagerStoreStartPagingRequest(filter.ToQuery(), 100) { ExtraTypeIdentifier = "ReservationInstance" }); + + ClearReservationHistorySections(); + foreach (var historyChange in response.Objects) + { + foreach (var change in historyChange.Changes) + { + var historySection = new HistorySection(change, historyChange.Time, historyChange.FullUsername, historyChange.DmaId, isOrder); + reservationHistoryCollapseButton.LinkedWidgets.AddRange(historySection.Widgets); + reservationHistorySections.Add(historySection); + } + } + + reservationHistoryCollapseButton.LinkedWidgets.Add(noReservationHistoryAvailableLabel); + } + catch (Exception exception) + { + helpers.Log(nameof(ReservationDetailsSection), nameof(ReservationHistoryButton_Pressed), $"Exception occurred: {exception}"); + } + + GenerateUi(); + RegenerateUi(this, new EventArgs()); + } + + private void ClearReservationHistorySections() + { + reservationHistoryCollapseButton.LinkedWidgets.Clear(); + reservationHistorySections.Clear(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(collapseButton, ++row, 0); + AddWidget(header, row, 1, 1, 2); + + AddWidget(logButton, ++row, 1); + + foreach (var propertySection in propertySections.OrderBy(x => x.NameLabel.Text)) + { + AddSection(propertySection, new SectionLayout(++row, 1)); + } + + AddWidget(reservationHistoryCollapseButton, ++row, 1); + if (!reservationHistoryCollapseButton.IsCollapsed && !reservationHistorySections.Any()) + { + AddWidget(noReservationHistoryAvailableLabel, ++row, 1); + } + else + { + foreach (var historySection in reservationHistorySections.OrderBy(x => x.Time)) + { + AddSection(historySection, new SectionLayout(++row, 1)); + row += historySection.RowCount; + } + } + } + + private class PropertySection : Section + { + public PropertySection(string name, object value) + { + NameLabel = new Label(name); + + if (value == null) + { + ValueLabel = new Label(String.Empty); + } + else if (value is DateTime) + { + ValueLabel = new Label(((DateTime)value).ToString("G", CultureInfo.InvariantCulture)); + } + else if (value is string) + { + ValueLabel = new Label(value.ToString()); + } + else if(value is System.Collections.IEnumerable enumerable) + { + var sb = new StringBuilder(); + + foreach (var obj in enumerable) + { + if (obj is Skyline.DataMiner.Net.ResourceManager.Objects.ServiceResourceUsageDefinition resourceUsage) + { + sb.Append($"Node [{resourceUsage.ServiceDefinitionNodeID}] has resource [{resourceUsage.NodeConfiguration.ResourceID}]"); + } + else + { + sb.Append(obj.ToString()); + } + + sb.Append(","); + } + + ValueLabel = new Label(sb.ToString().Trim(',')); + } + else + { + ValueLabel = new Label(value.ToString()); + } + + AddWidget(NameLabel, 0, 0); + AddWidget(ValueLabel, 0, 1, 1, 2); + } + + public Label NameLabel { get; private set; } + + public Label ValueLabel { get; private set; } + } + + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/ReservationHistorySection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/ReservationHistorySection.cs new file mode 100644 index 0000000..592ad25 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/ReservationHistorySection.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Skyline.DataMiner.Utils.InteractiveAutomationScript; +using Skyline.DataMiner.Net.History; +using Skyline.DataMiner.Net.History.ReservationInstances; + +namespace Debug_2.Debug.Reservations +{ + public sealed class HistorySection : Section + { + private readonly Label timeTitle = new Label("Time"); + private readonly Label userTitle = new Label("User"); + private readonly Label DmaIdTitle = new Label("DMA ID"); + private readonly Label TypeTitle = new Label("Type"); + + private readonly Label timeLabel = new Label(); + private readonly Label userLabel = new Label(); + private readonly Label DmaIdLabel = new Label(); + private readonly Label TypeLabel = new Label(); + private readonly Label ChangeLabel = new Label { Style = TextStyle.Heading }; + + public HistorySection(IChangeDescription changeDescription, DateTime time, string userName, int dmaId, bool isOrderHistory) + { + Time = time; + + timeLabel.Text = $"{time.ToUniversalTime()} [UTC]"; + userLabel.Text = userName; + DmaIdLabel.Text = dmaId.ToString(); + + if (changeDescription is ResourceUsageChange resourceUsageChange) + { + TypeLabel.Text = "Resources changed"; + ChangeLabel.Text = changeDescription.ToString(); + } + else if (changeDescription is StatusChange statusChange) + { + TypeLabel.Text = "Status changed"; + ChangeLabel.Text = changeDescription.ToString(); + } + else + { + throw new ArgumentException($"{nameof(changeDescription)} type is not supported"); + } + + GenerateUi(isOrderHistory); + } + + public DateTime Time { get; } + + private void GenerateUi(bool isOrderHistory) + { + int row = -1; + + int valueColumnSpan = isOrderHistory ? 2 : 1; + int valueColumnIdx = isOrderHistory ? 2 : 1; + + AddWidget(ChangeLabel, ++row, 0, 1, valueColumnSpan + 1); + + AddWidget(timeTitle, ++row, 0); + AddWidget(timeLabel, row, valueColumnIdx, 1, valueColumnSpan); + + AddWidget(TypeTitle, ++row, 0); + AddWidget(TypeLabel, row, valueColumnIdx, 1, valueColumnSpan); + + AddWidget(userTitle, ++row, 0); + AddWidget(userLabel, row, valueColumnIdx, 1, valueColumnSpan); + + AddWidget(DmaIdTitle, ++row, 0); + AddWidget(DmaIdLabel, row, valueColumnIdx, 1, valueColumnSpan); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/ReservationPropertySection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/ReservationPropertySection.cs new file mode 100644 index 0000000..232f081 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/ReservationPropertySection.cs @@ -0,0 +1,61 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Debug_2.Debug.Reservations; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Helpers = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers; + + public class ReservationPropertySection : Section + { + private readonly Helpers helpers; + private readonly ReservationInstance reservationInstance; + + private readonly Label nameLabel = new Label(); + private readonly TextBox valueTextBox = new TextBox(); + private readonly Button updateButton = new Button("Update") { Width = 150 }; + + public ReservationPropertySection(Helpers helpers, ReservationInstance reservationInstance, KeyValuePair property) + { + this.helpers = helpers; + this.reservationInstance = reservationInstance; + + nameLabel.Text = property.Key; + valueTextBox.Text = Convert.ToString(property.Value); + + updateButton.Pressed += UpdateButton_Pressed; + + GenerateUi(); + } + + private void UpdateButton_Pressed(object sender, EventArgs e) + { + try + { + DataMinerInterface.ReservationInstance.UpdateServiceReservationProperties(helpers, reservationInstance, new Dictionary { { nameLabel.Text, valueTextBox.Text } }); + valueTextBox.ValidationState = UIValidationState.Valid; + } + catch (Exception ex) + { + valueTextBox.ValidationState = UIValidationState.Invalid; + valueTextBox.ValidationText = $"Unable to update property due to {ex}"; + + helpers.Log(nameof(ReservationPropertySection), nameof(UpdateButton_Pressed), $"Unable to update property due to: {ex}"); + } + } + + private void GenerateUi() + { + AddWidget(nameLabel, 0, 0, 1, 2); + AddWidget(valueTextBox, 0, 2); + AddWidget(updateButton, 0, 3); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/TestDataMinerInterfaceDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/TestDataMinerInterfaceDialog.cs new file mode 100644 index 0000000..a2304b8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Reservations/TestDataMinerInterfaceDialog.cs @@ -0,0 +1,142 @@ +namespace Debug_2.Debug.Reservations +{ + using System; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class TestDataMinerInterfaceDialog : DebugDialog + { + private readonly Label header = new Label("Test DataMiner Interface") { Style = TextStyle.Heading }; + + private readonly GetReservationsSection getReservationsSection; + + private readonly Label resourceManagerAddOrUpdateReservationInstancesLabel = new Label("ResourceManager.AddOrUpdateReservationInstances") { Style = TextStyle.Bold }; + private readonly Label securityViewIdsLabel = new Label("comma-separated security view IDs"); + private readonly TextBox securityViewIdsTextBox = new TextBox(); + private readonly Button resourceManagerAddOrUpdateReservationInstancesButton = new Button("Execute"); + + + private readonly Label bookingManagerChangeNameLabel = new Label("BookingManager.ChangeName") { Style = TextStyle.Bold }; + private readonly Label bookingManagerNameLabel = new Label("Booking Manager Name"); + private readonly TextBox bookingManagerTextBox = new TextBox(); + private readonly Label nameToSetLabel = new Label("New Reservation Name"); + private readonly TextBox nameToSetTextBox = new TextBox(); + private readonly Button bookingManagerChangeNameButton = new Button("Execute"); + + private readonly Label reservationInstanceUpdateServiceReservationPropertiesLabel = new Label("ReservationInstance.UpdateServiceReservationProperties") { Style = TextStyle.Bold }; + private readonly Label propertyNameLabel = new Label("Property Name"); + private readonly TextBox propertyNameTextBox = new TextBox(); + private readonly Label propertyValueLabel = new Label("New Property Name"); + private readonly TextBox propertyValueTextBox = new TextBox(); + private readonly Button reservationInstanceUpdateServiceReservationPropertiesButton = new Button("Execute"); + + public TestDataMinerInterfaceDialog(Helpers helpers) : base(helpers) + { + Title = "Test DataMiner Interface"; + + getReservationsSection = new GetReservationsSection(helpers); + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + getReservationsSection.RegenerateUiRequired += GetReservationsSection_RegenerateUi; + + bookingManagerChangeNameButton.Pressed += BookingManagerChangeNameButton_Pressed; + + reservationInstanceUpdateServiceReservationPropertiesButton.Pressed += ReservationInstanceUpdateServiceReservationPropertiesButton_Pressed; + + resourceManagerAddOrUpdateReservationInstancesButton.Pressed += ResourceManagerAddOrUpdateReservationInstancesButton_Pressed; + } + + private void ResourceManagerAddOrUpdateReservationInstancesButton_Pressed(object sender, EventArgs e) + { + var securityViewIdsToSet = Array.ConvertAll(securityViewIdsTextBox.Text.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries), Convert.ToInt32).ToList(); + + foreach (var reservation in getReservationsSection.SelectedReservations) + { + reservation.SecurityViewIDs = securityViewIdsToSet; + DataMinerInterface.ResourceManager.AddOrUpdateReservationInstances(helpers, reservation); + } + + ShowRequestResult($"Updated reservations with security view IDs {string.Join(",", securityViewIdsToSet)}", string.Join("\n", getReservationsSection.SelectedReservations.Select(r => r.Name))); + GenerateUi(); + } + + private void ReservationInstanceUpdateServiceReservationPropertiesButton_Pressed(object sender, EventArgs e) + { + var reservationsToUpdate = getReservationsSection.SelectedReservations; + foreach (var reservation in reservationsToUpdate) + { + DataMinerInterface.ReservationInstance.UpdateServiceReservationProperties(helpers, reservation, new System.Collections.Generic.Dictionary { { propertyNameTextBox.Text, propertyValueTextBox.Text } }); + } + + ShowRequestResult($"Updated reservation properties.", $"Set property {propertyNameTextBox.Text} to {propertyValueTextBox.Text} for reservations {String.Join(", ", reservationsToUpdate.Select(x => x.Name))}"); + + GenerateUi(); + } + + private void BookingManagerChangeNameButton_Pressed(object sender, EventArgs e) + { + var reservationToUpdate = getReservationsSection.SelectedReservations.FirstOrDefault() as Skyline.DataMiner.Net.ResourceManager.Objects.ServiceReservationInstance; + var updatedReservation = DataMinerInterface.BookingManager.ChangeName(helpers, reservationToUpdate, nameToSetTextBox.Text); + + ShowRequestResult($"Change Name for {reservationToUpdate.Name} ({reservationToUpdate.ID}) to {nameToSetTextBox.Text}", JsonConvert.SerializeObject(updatedReservation)); + } + + private void GetReservationsSection_RegenerateUi(object sender, EventArgs e) + { + getReservationsSection.RegenerateUi(); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + AddWidget(header, ++row, 0, 1, 2); + + AddSection(getReservationsSection, new SectionLayout(++row, 0)); + row += getReservationsSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(bookingManagerChangeNameLabel, ++row, 0); + AddWidget(bookingManagerNameLabel, ++row, 0); + AddWidget(bookingManagerTextBox, row, 1); + AddWidget(nameToSetLabel, ++row, 0); + AddWidget(nameToSetTextBox, row, 1); + AddWidget(bookingManagerChangeNameButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(reservationInstanceUpdateServiceReservationPropertiesLabel, ++row, 0); + AddWidget(propertyNameLabel, ++row, 0); + AddWidget(propertyNameTextBox, row, 1); + AddWidget(propertyValueLabel, ++row, 0); + AddWidget(propertyValueTextBox, row, 1); + AddWidget(reservationInstanceUpdateServiceReservationPropertiesButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(resourceManagerAddOrUpdateReservationInstancesLabel, ++row, 0); + AddWidget(securityViewIdsLabel, ++row, 0); + AddWidget(securityViewIdsTextBox, row, 1); + AddWidget(resourceManagerAddOrUpdateReservationInstancesButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/AddOrUpdateResourcesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/AddOrUpdateResourcesDialog.cs new file mode 100644 index 0000000..4c7c8e6 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/AddOrUpdateResourcesDialog.cs @@ -0,0 +1,119 @@ +namespace Debug_2.Debug.Resources +{ + using System; + using System.Linq; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class AddOrUpdateResourcesDialog : DebugDialog + { + private readonly GetResourcesSection getResourcesSection = new GetResourcesSection(); + + private readonly CheckBox addOrUpdateCustomPropertyCheckBox = new CheckBox("Add or Update Custom Property"); + private readonly Label propertyNameLabel = new Label("Property Name to Add or Update"); + private readonly TextBox propertyNameTextBox = new TextBox(); + private readonly Label propertyValueLabel = new Label("Property Value to Add or Update"); + private readonly TextBox propertyValueTextBox = new TextBox(); + + private readonly CheckBox updateFunctionGuidCheckBox = new CheckBox("Update Function GUID"); + private readonly Label functionGuidLabel = new Label("Function GUID"); + private readonly TextBox functionGuidTextBox = new TextBox(); + + private readonly Button addOrUpdateResourcesButton = new Button("Add or Update Resources"); + + public AddOrUpdateResourcesDialog(Helpers helpers) : base(helpers) + { + Title = "Add or Update Resources"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + getResourcesSection.RegenerateUi += (o, e) => + { + getResourcesSection.GenerateUi(); + GenerateUi(); + }; + + addOrUpdateResourcesButton.Pressed += AddOrUpdateResourcesButton_Pressed; + } + + private void AddOrUpdateResourcesButton_Pressed(object sender, EventArgs e) + { + var selectedResources = getResourcesSection.SelectedResources; + + string propertyName = propertyNameTextBox.Text; + string propertyValue = propertyValueTextBox.Text; + + bool validGuid = Guid.TryParse(functionGuidTextBox.Text, out var newFunctionGuid); + + foreach (var resource in selectedResources) + { + if (addOrUpdateCustomPropertyCheckBox.IsChecked) + { + var existingProperty = resource.Properties.SingleOrDefault(p => p.Name == propertyName); + + if (existingProperty is null) + { + resource.Properties.Add(new Skyline.DataMiner.Net.Messages.ResourceManagerProperty + { + Name = propertyName, + Value = propertyValue, + }); + } + else + { + existingProperty.Value = propertyValue; + } + } + + if (updateFunctionGuidCheckBox.IsChecked && validGuid) + { + resource.FunctionGUID = newFunctionGuid; + } + } + + DataMinerInterface.ResourceManager.AddOrUpdateResources(helpers, selectedResources); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddSection(getResourcesSection, new SectionLayout(++row, 0)); + for (int i = row; i < getResourcesSection.RowCount; i++) + { + SetRowHeight(i, 30); + } + + row += getResourcesSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(addOrUpdateCustomPropertyCheckBox, ++row, 0); + AddWidget(propertyNameLabel, ++row, 0); + AddWidget(propertyNameTextBox, row, 1); + AddWidget(propertyValueLabel, ++row, 0); + AddWidget(propertyValueTextBox, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(updateFunctionGuidCheckBox, ++row, 0); + AddWidget(functionGuidLabel, ++row, 0); + AddWidget(functionGuidTextBox, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(addOrUpdateResourcesButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/FindResourcesWithFiltersDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/FindResourcesWithFiltersDialog.cs new file mode 100644 index 0000000..ef4a974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/FindResourcesWithFiltersDialog.cs @@ -0,0 +1,69 @@ +using System; +using System.Linq; +using Newtonsoft.Json; +using Skyline.DataMiner.Utils.InteractiveAutomationScript; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + +namespace Debug_2.Debug.Resources +{ + public class FindResourcesWithFiltersDialog : DebugDialog + { + private readonly GetResourcesSection getResourcesSection = new GetResourcesSection(); + + private readonly Label actionsHeader = new Label("Actions") { Style = TextStyle.Heading }; + private readonly Button showJsonButton = new Button("Show Resources JSON"); + + public FindResourcesWithFiltersDialog(Helpers helpers) : base(helpers) + { + Title = "Find Resources with Filters"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + getResourcesSection.RegenerateUi += (o, e) => + { + getResourcesSection.GenerateUi(); + GenerateUi(); + }; + + showJsonButton.Pressed += ShowJsonButton_Pressed; + } + + private void ShowJsonButton_Pressed(object sender, EventArgs e) + { + ShowRequestResult("Serialized Resources", string.Join("\n", getResourcesSection.SelectedResources.Select(r => JsonConvert.SerializeObject(r)))); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddSection(getResourcesSection, new SectionLayout(++row, 0)); + for (int i = row; i < getResourcesSection.RowCount; i++) + { + SetRowHeight(i, 30); + } + + row += getResourcesSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(actionsHeader, ++row, 0, 1, 2); + + AddWidget(showJsonButton, ++row, 0, verticalAlignment: VerticalAlignment.Top); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/FixResourceConfigurationDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/FixResourceConfigurationDialog.cs new file mode 100644 index 0000000..8228b44 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/FixResourceConfigurationDialog.cs @@ -0,0 +1,429 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Resources +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Debug_2.Debug.Resources; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.ResourceManager.Objects; + + public class FixResourceConfigurationDialog : Dialog + { + private const int GenericDveTablePid = 65132; + private const int GenericDveLinkerTablePid = 65146; + + private readonly Helpers helpers; + + private readonly GetResourcesSection getResourcesSection = new GetResourcesSection(); + + private readonly Label fixDveElementIdAndStateHeader = new Label("Fix DVE Element ID and State") { Style = TextStyle.Heading }; + private readonly Label explanationLabel = new Label("Will update the Element ID value of the selected resources to the Element ID found in the [Generic DVE table]\nWill set the DVE State column of the [Generic DVE table] to the correct value based on presence of the resource DVE."); + private readonly Button fixResourcesButton = new Button("Fix Selected Resources"); + + private readonly Button fixResourceElementGenericDveTableButton = new Button("Fix Resource Element [Generic DVE Table]"); + + private readonly Label fixResourceElementGenericDveLinkerTableHeader = new Label("Fix [Generic DVE Linker Table]") { Style = TextStyle.Heading }; + private readonly Label fixResourceElementGenericDveLinkerTableLabel = new Label("Created by VSC as part of tasks DCP20070 and DCP199662.\nWill loop over all selected resources and check the function Guid in the [Generic DVE Table] and then add or set the row in the [Generic DVE Linker Table]"); + private readonly Label functionGuidLabel = new Label("Function Guid"); + private readonly TextBox functionGuidTextBox = new TextBox(); + private readonly Label fkDataLabel = new Label("[FK Data] value to set"); + private readonly Numeric fkDataNumeric = new Numeric() { Minimum = -1, Decimals = 0 }; + private readonly Label fkTableLabel = new Label("[FK Table] value to set"); + private readonly Numeric fkTableNumeric = new Numeric() { Minimum = -1, Decimals = 0 }; + private readonly Button getResourceElementGenericDveLinkerTableButton = new Button("Get Resources with invalid Resource Element [Generic DVE Linker Table]"); + private readonly Button fixResourceElementGenericDveLinkerTableButton = new Button("Fix Resource Element [Generic DVE Linker Table]"); + + private readonly Label deleteResourcesHeader = new Label("Delete Resources") { Style = TextStyle.Heading }; + private readonly Button deleteResourcesButton = new Button("Delete Resources") { Style = ButtonStyle.CallToAction }; + + private readonly List resultSections = new List(); + + private IDms dms; + + public FixResourceConfigurationDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Fix Resource Configuration"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private void Initialize() + { + fixResourcesButton.Pressed += UpdateResourcesButton_Pressed; + + fixResourceElementGenericDveTableButton.Pressed += FixResourceElementGenericDveTableButton_Pressed; + + getResourceElementGenericDveLinkerTableButton.Pressed += GetResourceElementGenericDveLinkerTableButton_Pressed; + fixResourceElementGenericDveLinkerTableButton.Pressed += FixResourceElementGenericDveLinkerTableButton_Pressed; + + deleteResourcesButton.Pressed += DeleteResourcesButton_Pressed; + } + + private void DeleteResourcesButton_Pressed(object sender, EventArgs e) + { + try + { + SrmManagers.ResourceManager.RemoveResources(GetSelectedResources()); + + ShowRequestResult("Successfully deleted resources", string.Join("\n", GetSelectedResources().Select(r => r.Name))); + } + catch (Exception ex) + { + ShowRequestResult("Failed to delete resources", ex.ToString()); + } + } + + private void GetResourceElementGenericDveLinkerTableButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(functionGuidTextBox.Text, out var inputFunctionGuid)) + { + ShowRequestResult("Invalid Input", $"Unable to parse {functionGuidTextBox.Text} to a Guid"); + return; + } + + string inputFkData = ((int)fkDataNumeric.Value).ToString(); + string inputFkTable = ((int)fkTableNumeric.Value).ToString(); + + var resourcesToUpdate = GetSelectedResources(); + + dms = dms ?? Skyline.DataMiner.Automation.Engine.SLNetRaw.GetDms(); + + var elements = new Dictionary(); + var cachedGenericDveTables = new Dictionary(); + var cachedGenericDveLinkerTables = new Dictionary(); + + var resourcesWithFailures = new List(); + var resourcesWithMissingRows = new List(); + var resourcesWithInvalidRows = new List(); + + foreach (var resource in resourcesToUpdate.OfType()) + { + int mainDveDmaId = resource.MainDVEDmaID; + int mainDveElementId = resource.MainDVEElementID; + + var mainDveFullId = new DmsElementId(mainDveDmaId, mainDveElementId); + + if (!elements.TryGetValue(mainDveFullId, out var element)) + { + element = dms.GetElement(mainDveFullId); + elements.Add(mainDveFullId, element); + } + + if (!cachedGenericDveTables.TryGetValue(mainDveFullId, out var genericDveTable)) + { + genericDveTable = element.GetTable(GenericDveTablePid); + cachedGenericDveTables.Add(mainDveFullId, genericDveTable); + } + + var genericDveTableRow = genericDveTable.GetData().Values.SingleOrDefault(r => Convert.ToString(r[1]) == resource.FunctionName); + if (genericDveTableRow is null) + { + resourcesWithFailures.Add($"Unable to find row for resource {resource.Name}"); + continue; + } + + if (!Guid.TryParse(Convert.ToString(genericDveTableRow[4]), out var functionGuid) || functionGuid != inputFunctionGuid) + { + resourcesWithFailures.Add($"Resource {resource.Name} Generic DVE Table DVE function Guid is not {inputFunctionGuid}"); + continue; + } + + string genericDveTableRowPrimaryKey = Convert.ToString(genericDveTableRow[0]); + + if (!cachedGenericDveLinkerTables.TryGetValue(mainDveFullId, out var genericDveLinkerTable)) + { + genericDveLinkerTable = element.GetTable(GenericDveLinkerTablePid); + cachedGenericDveLinkerTables.Add(mainDveFullId, genericDveLinkerTable); + } + + var genericDveLinkerTableRow = genericDveLinkerTable.GetData().Values.SingleOrDefault(r => Convert.ToString(r[1]) == genericDveTableRowPrimaryKey); + + if (genericDveLinkerTableRow is null || !genericDveLinkerTableRow.Any()) + { + resourcesWithMissingRows.Add(resource.Name); + } + else if (Convert.ToString(genericDveLinkerTableRow[1]) != genericDveTableRowPrimaryKey || Convert.ToString(genericDveLinkerTableRow[2]) != inputFkData || Convert.ToString(genericDveLinkerTableRow[3]) != inputFkTable) + { + resourcesWithInvalidRows.Add(resource.Name); + } + else + { + // nothing + } + } + + ShowRequestResult("Resources without row in [Generic DVE Linker Table]", string.Join("\n", resourcesWithMissingRows)); + ShowRequestResult("Resources with invalid row in [Generic DVE Linker Table]", string.Join("\n", resourcesWithInvalidRows)); + ShowRequestResult("Resources without row in [Generic DVE Table]", string.Join("\n", resourcesWithFailures)); + } + + private void FixResourceElementGenericDveTableButton_Pressed(object sender, EventArgs e) + { + var resourcesToUpdate = GetSelectedResources(); + + dms = dms ?? Skyline.DataMiner.Automation.Engine.SLNetRaw.GetDms(); + + var elements = new Dictionary(); + var cachedGenericDveTables = new Dictionary(); + + foreach (var resource in resourcesToUpdate.OfType()) + { + int mainDveDmaId = resource.MainDVEDmaID; + int mainDveElementId = resource.MainDVEElementID; + + var mainDveFullId = new DmsElementId(mainDveDmaId, mainDveElementId); + + if (!elements.TryGetValue(mainDveFullId, out var element)) + { + element = dms.GetElement(mainDveFullId); + elements.Add(mainDveFullId, element); + } + + if (!cachedGenericDveTables.TryGetValue(mainDveFullId, out var genericDveTable)) + { + genericDveTable = element.GetTable(GenericDveTablePid); + cachedGenericDveTables.Add(mainDveFullId, genericDveTable); + } + + var genericDveTableRow = genericDveTable.GetData().Values.SingleOrDefault(r => Convert.ToString(r[1]) == resource.FunctionName); + if (genericDveTableRow is null) + { + var existingDisplayKeys = genericDveTable.GetDisplayKeys().Select(key => Convert.ToInt16(key)).ToList(); + + genericDveTableRow = new object[] + { + (existingDisplayKeys.Any() ? existingDisplayKeys.Max() + 1 : 1).ToString(), + resource.FunctionName, + $"{resource.DmaID}/{resource.ElementID}", + 0.ToString(), // disabled + resource.FunctionGUID.ToString(), + resource.ID.ToString(), + }; + } + } + } + + private void FixResourceElementGenericDveLinkerTableButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(functionGuidTextBox.Text, out var inputFunctionGuid)) + { + ShowRequestResult("Invalid Input", $"Unable to parse {functionGuidTextBox.Text} to a Guid"); + return; + } + + string inputFkData = ((int)fkDataNumeric.Value).ToString(); + string inputFkTable = ((int)fkTableNumeric.Value).ToString(); + + var resourcesToUpdate = GetSelectedResources(); + + dms = dms ?? Skyline.DataMiner.Automation.Engine.SLNetRaw.GetDms(); + + var failedUpdates = new List(); + var elements = new Dictionary(); + var cachedGenericDveTables = new Dictionary(); + var cachedGenericDveLinkerTables = new Dictionary(); + + foreach (var resource in resourcesToUpdate.OfType()) + { + int mainDveDmaId = resource.MainDVEDmaID; + int mainDveElementId = resource.MainDVEElementID; + + var mainDveFullId = new DmsElementId(mainDveDmaId, mainDveElementId); + + if (!elements.TryGetValue(mainDveFullId, out var element)) + { + element = dms.GetElement(mainDveFullId); + elements.Add(mainDveFullId, element); + } + + if (!cachedGenericDveTables.TryGetValue(mainDveFullId, out var genericDveTable)) + { + genericDveTable = element.GetTable(GenericDveTablePid); + cachedGenericDveTables.Add(mainDveFullId, genericDveTable); + } + + var genericDveTableRow = genericDveTable.GetData().Values.SingleOrDefault(r => Convert.ToString(r[1]) == resource.FunctionName); + if (genericDveTableRow is null) + { + failedUpdates.Add($"Unable to find row for resource {resource.Name}"); + continue; + } + + if (!Guid.TryParse(Convert.ToString(genericDveTableRow[4]), out var functionGuid) || functionGuid != inputFunctionGuid) + { + failedUpdates.Add($"Resource {resource.Name} Generic DVE Table DVE function Guid is not {inputFunctionGuid}"); + continue; + } + + string genericDveTableRowPrimaryKey = Convert.ToString(genericDveTableRow[0]); + + if (!cachedGenericDveLinkerTables.TryGetValue(mainDveFullId, out var genericDveLinkerTable)) + { + genericDveLinkerTable = element.GetTable(GenericDveLinkerTablePid); + cachedGenericDveLinkerTables.Add(mainDveFullId, genericDveLinkerTable); + } + + var genericDveLinkerTableRow = genericDveLinkerTable.GetData().Values.SingleOrDefault(r => Convert.ToString(r[1]) == genericDveTableRowPrimaryKey); + + if (genericDveLinkerTableRow is null || !genericDveLinkerTableRow.Any()) + { + var existingDisplayKeys = genericDveLinkerTable.GetDisplayKeys().Select(key => Convert.ToInt16(key)).ToList(); + + genericDveLinkerTableRow = new object[] + { + (existingDisplayKeys.Any() ? existingDisplayKeys.Max() + 1 : 1).ToString(), + genericDveTableRowPrimaryKey, + inputFkData, + inputFkTable, + }; + + genericDveLinkerTable.AddRow(genericDveLinkerTableRow); + } + else + { + genericDveLinkerTableRow[1] = genericDveTableRowPrimaryKey; + genericDveLinkerTableRow[2] = inputFkData; + genericDveLinkerTableRow[3] = inputFkTable; + + genericDveLinkerTable.SetRow(genericDveLinkerTableRow[0].ToString(), genericDveLinkerTableRow); + } + } + + ShowRequestResult("Updated Resource Element Generic DVE Linker Tables", $"Updated Generic DVE Linker Tables on resource elements:\n{string.Join("\n", resourcesToUpdate.Select(r => $"{r.Name} => {r.DmaID}/{r.ElementID}"))}"); + + ShowRequestResult("Failed Updates", $"{string.Join("\n", failedUpdates)}"); + } + + private void UpdateResourcesButton_Pressed(object sender, EventArgs e) + { + var resourcesToUpdate = GetSelectedResources(); + + dms = dms ?? Skyline.DataMiner.Automation.Engine.SLNetRaw.GetDms(); + + var failedUpdates = new List(); + var cachedTables = new Dictionary(); + + foreach (var resource in resourcesToUpdate.OfType()) + { + int mainDveDmaId = resource.MainDVEDmaID; + int mainDveElementId = resource.MainDVEElementID; + + var mainDveFullId = new DmsElementId(mainDveDmaId, mainDveElementId); + + if (!cachedTables.TryGetValue(mainDveFullId, out var table)) + { + table = dms.GetElement(mainDveFullId).GetTable(65132); + cachedTables.Add(mainDveFullId, table); + } + + var row = table.GetData().Values.FirstOrDefault(r => Convert.ToString(r[1]) == resource.FunctionName); + if (row is null) + { + failedUpdates.Add($"Unable to find row for resource {resource.Name}"); + continue; + } + + var resourceDveFullId = Convert.ToString(row[2]); + + resource.DmaID = int.Parse(resourceDveFullId.Split('/')[0]); + resource.ElementID = int.Parse(resourceDveFullId.Split('/').Last()); + + try + { + var resourceDve = dms.GetElement(resourceDveFullId); + + if (Convert.ToInt32(row[3]) != 1) + { + // set cell to 1 + row.SetValue(1, 3); + table.SetRow(Convert.ToString(row[0]), row); + } + } + catch (Exception) + { + if (Convert.ToInt32(row[3]) != 0) + { + // set cell to 0 + row.SetValue(0, 3); + table.SetRow(Convert.ToString(row[0]), row); + } + } + } + + SrmManagers.ResourceManager.AddOrUpdateResources(resourcesToUpdate); + + ShowRequestResult("Updated Resources", $"Updated Resources Element IDs:\n{string.Join("\n", resourcesToUpdate.Select(r => $"{r.Name} => {r.DmaID}/{r.ElementID}"))}"); + ShowRequestResult("Failed Updates", $"{string.Join("\n", failedUpdates)}"); + } + + private Resource[] GetSelectedResources() + { + return getResourcesSection.SelectedResources.ToArray(); + } + + private void ShowRequestResult(string header, params string[] results) + { + resultSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 5); + AddWidget(new WhiteSpace(), ++row, 0); + + AddSection(getResourcesSection, new SectionLayout(++row, 0)); + row += getResourcesSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(fixDveElementIdAndStateHeader, ++row, 0, 1, 5); + AddWidget(explanationLabel, ++row, 0, 1, 5); + AddWidget(fixResourcesButton, ++row, 0); + + /* + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(fixResourceElementGenericDveTableHeader, ++row, 0, 1, 5); + AddWidget(fixResourceElementGenericDveTableLabel, ++row, 0, 1, 5); + AddWidget(fixResourceElementGenericDveTableButton, ++row, 0, 1, 5); + */ + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(fixResourceElementGenericDveLinkerTableHeader, ++row, 0, 1, 5); + AddWidget(fixResourceElementGenericDveLinkerTableLabel, ++row, 0, 1, 5); + AddWidget(functionGuidLabel, ++row, 0); + AddWidget(functionGuidTextBox, row, 1); + AddWidget(fkDataLabel, ++row, 0); + AddWidget(fkDataNumeric, row, 1); + AddWidget(fkTableLabel, ++row, 0); + AddWidget(fkTableNumeric, row, 1); + AddWidget(getResourceElementGenericDveLinkerTableButton, ++row, 0); + AddWidget(fixResourceElementGenericDveLinkerTableButton, ++row, 0); + + AddWidget(deleteResourcesHeader, ++row, 0, 1, 5); + AddWidget(deleteResourcesButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + foreach (var resultSection in resultSections) + { + AddSection(resultSection, ++row, 0); + row += resultSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/GetEligibleResourcesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/GetEligibleResourcesDialog.cs new file mode 100644 index 0000000..881dc26 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/GetEligibleResourcesDialog.cs @@ -0,0 +1,139 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Resources +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + + public class GetEligibleResourcesDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label startLabel = new Label("Start"); + private readonly DateTimePicker startDateTimePicker = new DateTimePicker(DateTime.Now); + + private readonly Label endLabel = new Label("End"); + private readonly DateTimePicker endDateTimePicker = new DateTimePicker(DateTime.Now.AddMinutes(60)); + private readonly Label timeZoneLabel = new Label($"Times are displayed here in the time zone of the client."); + private readonly Label timeZone2Label = new Label($"Times in Resource Occupancy page in Cube are displayed in the time zone of the server."); + + private readonly Label resourcePoolLabel = new Label("Resource Pool"); + private DropDown resourcePoolDropDown; + + private readonly CheckBox reservationIdToIgnoreCheckBox = new CheckBox("Reservation ID to Ignore"); + private readonly TextBox reservationIdToIgnoreTextBox = new TextBox(string.Empty); + + private readonly CheckBox nodeIdToIgnoreCheckBox = new CheckBox("Node ID to Ignore"); + private readonly Numeric nodeIdToIgnoreNumeric = new Numeric(0) { Decimals = 0, Minimum = 0, StepSize = 1 }; + + private readonly Button getEligibleResourcesButton = new Button("Get Eligible Resources"); + + + private readonly List resultSections = new List(); + + private ResourcePool[] resourcePools; + + public GetEligibleResourcesDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Get Eligible Resources"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private ResourcePool SelectedResourcePool => resourcePools.SingleOrDefault(pool => pool.Name == resourcePoolDropDown.Selected); + + private void Initialize() + { + resourcePools = helpers.ResourceManager.GetResourcePools(); + var resourcePoolOptions = resourcePools.Select(p => p.Name).OrderBy(name => name).ToList(); + resourcePoolDropDown = new DropDown(resourcePoolOptions, resourcePoolOptions[0]) { IsDisplayFilterShown = true }; + + reservationIdToIgnoreCheckBox.Changed += (s, e) => nodeIdToIgnoreCheckBox.IsChecked = e.IsChecked; + nodeIdToIgnoreCheckBox.Changed += (s, e) => reservationIdToIgnoreCheckBox.IsChecked = e.IsChecked; + + getEligibleResourcesButton.Pressed += GetEligibleResourcesButton_Pressed; + } + + private void GetEligibleResourcesButton_Pressed(object sender, EventArgs e) + { + var context = new EligibleResourceContext + { + TimeRange = new Net.Time.TimeRangeUtc(startDateTimePicker.DateTime, endDateTimePicker.DateTime, TimeZoneInfo.Utc), + ResourceFilter = ResourceExposers.PoolGUIDs.Contains(SelectedResourcePool.GUID), + }; + + bool ignoreReservation = Guid.TryParse(reservationIdToIgnoreTextBox.Text, out var parsedGuid) && reservationIdToIgnoreCheckBox.IsChecked; + if (ignoreReservation) + { + context.ReservationIdToIgnore = new Net.ReservationInstanceID(parsedGuid); + context.NodeIdToIgnore = (int)nodeIdToIgnoreNumeric.Value; + } + + var eligibleResources = DataMinerInterface.ResourceManager.GetEligibleResources(helpers, context); + + if (eligibleResources?.EligibleResources == null) + { + ShowRequestResult($"Eligible Resources for {SelectedResourcePool.Name} from {context.TimeRange.Start} (UTC) until {context.TimeRange.Stop} (UTC) {(ignoreReservation ? $"ignoring reservation {parsedGuid} node {(int)nodeIdToIgnoreNumeric.Value}" : String.Empty)}", "Empty response"); + } + else + { + ShowRequestResult($"Eligible Resources for {SelectedResourcePool.Name} from {context.TimeRange.Start} (UTC) until {context.TimeRange.Stop} (UTC) {(ignoreReservation ? $"ignoring reservation {parsedGuid} node {(int)nodeIdToIgnoreNumeric.Value}" : String.Empty)}", string.Join("\n", eligibleResources.EligibleResources.Select(p => p.Name).OrderBy(n => n))); + } + } + + private void ShowRequestResult(string header, params string[] results) + { + resultSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 5); + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(startLabel, ++row, 0); + AddWidget(startDateTimePicker, row, 1); + + AddWidget(endLabel, ++row, 0); + AddWidget(endDateTimePicker, row, 1); + + AddWidget(timeZoneLabel, ++row, 1); + AddWidget(timeZone2Label, ++row, 1); + + AddWidget(resourcePoolLabel, ++row, 0); + AddWidget(resourcePoolDropDown, row, 1); + + AddWidget(reservationIdToIgnoreCheckBox, ++row, 1); + AddWidget(reservationIdToIgnoreTextBox, row, 2); + + AddWidget(nodeIdToIgnoreCheckBox, ++row, 1); + AddWidget(nodeIdToIgnoreNumeric, row, 2); + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(getEligibleResourcesButton, ++row, 0, 1, 5); + + foreach (var resultSection in resultSections) + { + AddSection(resultSection, ++row, 0); + row += resultSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/GetResourcesSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/GetResourcesSection.cs new file mode 100644 index 0000000..02f9a6a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/GetResourcesSection.cs @@ -0,0 +1,136 @@ +namespace Debug_2.Debug.Resources +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Library.UI.Filters; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + + public class GetResourcesSection : Section + { + private readonly Label header = new Label("Get Resources with filters") { Style = TextStyle.Heading }; + + private readonly FilterSection functionGuidFilterSection = new GuidFilterSection("Function Guid", x => FunctionResourceExposers.FunctionGUID.Equal((Guid)x).CAST()); + + private readonly FilterSection resourcePoolFilterSection = new ResourcePoolFilterSection("Resource Pool", x => ResourceExposers.PoolGUIDs.Contains((Guid)x).CAST(), SrmManagers.ResourceManager.GetResourcePools()); + + private readonly FilterSection resourceNameEqualsFilterSection = new StringFilterSection("Resource Name Equals", x => ResourceExposers.Name.Equal((string)x).CAST()); + + private readonly FilterSection resourceNameContainsFilterSection = new StringFilterSection("Resource Name Contains", x => ResourceExposers.Name.Contains((string)x).CAST()); + + private readonly FilterSection resourceIdFilterSection = new GuidFilterSection("Resource ID", x => ResourceExposers.ID.Equal((Guid)x).CAST()); + + private readonly FilterSection dmaIdFilterSection = new IntegerFilterSection("DMA ID", x => ResourceExposers.DmaID.Equal(Convert.ToInt32(x)).CAST()); + + private readonly FilterSection elementIdFilterSection = new IntegerFilterSection("Element ID", x => ResourceExposers.ElementID.Equal(Convert.ToInt32(x)).CAST()); + + private readonly Button getResourcesBasedOnFiltersButton = new Button("Get Resources Based on Filters") { Style = ButtonStyle.CallToAction }; + private List resourcesBasedOnFilters = new List(); + + private readonly CollapseButton showIndividualResourceSelectionCollapseButton; + private CheckBoxList selectResourcesCheckBoxList = new CheckBoxList(); + private readonly Button selectAllButton = new Button("Select All"); + private readonly Button unselectAllButton = new Button("Unselect All"); + private readonly Button selectResourcesButton = new Button("Get Individually Selected Resources") { Style = ButtonStyle.CallToAction }; + + private readonly CollapseButton showSelectedResourcesButton; + private readonly TextBox selectedResourcesTextBox = new TextBox() { IsMultiline = true }; + + public GetResourcesSection() + { + getResourcesBasedOnFiltersButton.Pressed += (o, e) => SelectedResources = GetResourcesBasedOnFilters(); + + showIndividualResourceSelectionCollapseButton = new CollapseButton(new Widget[] {selectResourcesCheckBoxList, selectResourcesButton, selectAllButton, unselectAllButton}, true) { CollapseText = "Hide Individual Resource Selection", ExpandText = "Show Individual Resource Selection" }; + + selectAllButton.Pressed += (o, e) => selectResourcesCheckBoxList.CheckAll(); + unselectAllButton.Pressed += (o, e) => selectResourcesCheckBoxList.UncheckAll(); + + selectResourcesButton.Pressed += (o, e) => SelectedResources = GetIndividuallySelectedResources(); + + showSelectedResourcesButton = new CollapseButton(selectedResourcesTextBox.Yield(), true) { CollapseText = "Hide Selected Resources", ExpandText = "Show Selected Resources"}; + + GenerateUi(); + } + + public IEnumerable SelectedResources { get; private set; } = new List(); + + public event EventHandler RegenerateUi; + + private IEnumerable GetResourcesBasedOnFilters() + { + selectedResourcesTextBox.Text = String.Empty; + if (!this.ActiveFiltersAreValid()) return new List(); + + resourcesBasedOnFilters = SrmManagers.ResourceManager.GetResources(this.GetCombinedFilterElement().CAST()).Cast().ToList(); + + int previousAmountOfOptions = selectResourcesCheckBoxList.Options.Count(); + + selectResourcesCheckBoxList.SetOptions(resourcesBasedOnFilters.Select(r => r.Name).OrderBy(name => name).ToList()); + selectResourcesCheckBoxList.CheckAll(); + + var selectedResources = GetIndividuallySelectedResources(); + + selectedResourcesTextBox.Text = String.Join("\n", selectedResources.Select(r => r.Name).OrderBy(name => name)); + + if (selectResourcesCheckBoxList.Options.Count() != previousAmountOfOptions) RegenerateUi?.Invoke(this, EventArgs.Empty); + + return selectedResources; + } + + private IEnumerable GetIndividuallySelectedResources() + { + var selectedResourceNames = selectResourcesCheckBoxList.Checked; + + var selectedResources = resourcesBasedOnFilters.Where(r => selectedResourceNames.Contains(r.Name)).ToList(); + + selectedResourcesTextBox.Text = String.Join("\n", selectedResources.Select(r => r.Name).OrderBy(name => name)); + + return selectedResources; + } + + public void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(header, ++row, 0, 1, 2); + + AddSection(functionGuidFilterSection, new SectionLayout(++row, 0)); + + AddSection(resourcePoolFilterSection, new SectionLayout(++row, 0)); + + AddSection(resourceNameEqualsFilterSection, new SectionLayout(++row, 0)); + + AddSection(resourceNameContainsFilterSection, new SectionLayout(++row, 0)); + + AddSection(resourceIdFilterSection, new SectionLayout(++row, 0)); + + AddSection(dmaIdFilterSection, new SectionLayout(++row, 0)); + + AddSection(elementIdFilterSection, new SectionLayout(++row, 0)); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(getResourcesBasedOnFiltersButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(showIndividualResourceSelectionCollapseButton, ++row, 0); + AddWidget(selectResourcesCheckBoxList, 0, 2, selectResourcesCheckBoxList.Options.Count() != 0 ? selectResourcesCheckBoxList.Options.Count() : 1, 1, verticalAlignment: VerticalAlignment.Top); + AddWidget(selectAllButton, 0, 3, verticalAlignment: VerticalAlignment.Top); + AddWidget(unselectAllButton, 0, 4, verticalAlignment: VerticalAlignment.Top); + AddWidget(selectResourcesButton, ++row, 0, verticalAlignment: VerticalAlignment.Top); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(showSelectedResourcesButton, ++row, 0, verticalAlignment:VerticalAlignment.Top); + AddWidget(selectedResourcesTextBox, row, 1); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/ResourceOccupancyDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/ResourceOccupancyDialog.cs new file mode 100644 index 0000000..558853d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Resources/ResourceOccupancyDialog.cs @@ -0,0 +1,191 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Resources +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Resources; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Helpers = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers; + + public class ResourceOccupancyDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label resourceSelectionLabel = new Label("Resource Selection"); + private readonly RadioButtonList resourceSelectionMethodRadioButtonList = new RadioButtonList(new[] {"ID", "Selection"}, "Selection"); + + private readonly Label resourcePoolLabel = new Label("Resource Pool"); + private DropDown resourcePoolDropDown; + + private readonly Label resourceLabel = new Label("Resource"); + private DropDown resourceDropDown; + + private readonly Label resourceIdLabel = new Label("Resource ID") { IsVisible = false }; + private readonly TextBox resourceIdTextBox = new TextBox() { IsVisible = false }; + private readonly Button enterCurrentIdButton = new Button("Enter Current ID") { Width = 200, IsVisible = false }; + + private readonly Label startTimeLabel = new Label("Start Time"); + private readonly DateTimePicker startTimeDateTimePicker = new DateTimePicker(DateTime.Now); + + private readonly Label endTimeLabel = new Label("End Time"); + private readonly DateTimePicker endTimeDateTimePicker = new DateTimePicker(DateTime.Now.AddHours(1)); + + private readonly Label timeZoneLabel = new Label($"Times are displayed here in the time zone of the client."); + private readonly Label timeZone2Label = new Label($"Times in Resource Occupancy page in Cube are displayed in the time zone of the server."); + + + private readonly Button getResourceOccupancyButton = new Button("Get Resource Occupancy"){Width = 200}; + + private readonly List resultSections = new List(); + + private ResourcePool[] resourcePools; + private Resource[] resources; + + public ResourceOccupancyDialog(Helpers helpers) : base(helpers.Engine) + { + this.helpers = helpers; + + Title = "Resource Occupancy"; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back..."){Width = 150}; + + private ResourcePool SelectedResourcePool => resourcePools.SingleOrDefault(pool => pool.Name == resourcePoolDropDown.Selected); + + private Resource SelectedResource => resources.SingleOrDefault(r => r.Name == resourceDropDown.Selected); + + private void Initialize() + { + resourceSelectionMethodRadioButtonList.Changed += ResourceSelectionMethodRadioButtonList_Changed; + + enterCurrentIdButton.Pressed += (sender, args) => resourceIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + + resourcePools = helpers.ResourceManager.GetResourcePools(); + var resourcePoolOptions = resourcePools.Select(p => p.Name).OrderBy(name => name).ToList(); + resourcePoolDropDown = new DropDown(resourcePoolOptions, resourcePoolOptions[0]) { IsDisplayFilterShown = true }; + resourcePoolDropDown.Changed += ResourcePoolDropDown_Changed; + + resources = DataMinerInterface.ResourceManager.GetResources(helpers, ResourceExposers.PoolGUIDs.Contains(SelectedResourcePool.GUID)).ToArray(); + var resourceOptions = resources.Select(r => r.Name).OrderBy(name => name).ToList(); + resourceDropDown = new DropDown(resourceOptions, resourceOptions.FirstOrDefault()) { IsDisplayFilterShown = true }; + + getResourceOccupancyButton.Pressed += GetResourceOccupancyButton_Pressed; + } + + private void ResourceSelectionMethodRadioButtonList_Changed(object sender, RadioButtonList.RadioButtonChangedEventArgs e) + { + resourcePoolLabel.IsVisible = e.SelectedValue == "Selection"; + resourcePoolDropDown.IsVisible = resourcePoolLabel.IsVisible; + resourceLabel.IsVisible = resourcePoolLabel.IsVisible; + resourceDropDown.IsVisible = resourcePoolLabel.IsVisible; + + resourceIdLabel.IsVisible = e.SelectedValue == "ID"; + resourceIdTextBox.IsVisible = resourceIdLabel.IsVisible; + enterCurrentIdButton.IsVisible = resourceIdLabel.IsVisible; + } + + private void ResourcePoolDropDown_Changed(object sender, DropDown.DropDownChangedEventArgs e) + { + resources = DataMinerInterface.ResourceManager.GetResources(helpers, ResourceExposers.PoolGUIDs.Contains(SelectedResourcePool.GUID)).ToArray(); + resourceDropDown.Options = resources.Select(r => r.Name).OrderBy(name => name).ToList(); + } + + private void GetResourceOccupancyButton_Pressed(object sender, EventArgs e) + { + Guid resourceId; + string resourceName; + if (resourceSelectionMethodRadioButtonList.Selected == "Selection") + { + resourceId = SelectedResource.ID; + resourceName = SelectedResource.Name; + } + else if(!Guid.TryParse(resourceIdTextBox.Text, out resourceId)) + { + ShowRequestResult("Invalid GUID", string.Empty); + return; + } + else + { + resourceName = DataMinerInterface.ResourceManager.GetResource(helpers, resourceId)?.Name; + } + + var start = startTimeDateTimePicker.DateTime.ToUniversalTime(); + var end = endTimeDateTimePicker.DateTime.ToUniversalTime(); + + var resourceFilter = ReservationInstanceExposers.ResourceIDsInReservationInstance.Contains(resourceId); + var startFilter = ReservationInstanceExposers.Start.LessThanOrEqual(end); + var endFilter = ReservationInstanceExposers.End.GreaterThanOrEqual(start); + + var occupyingServices = new List(); + + var services = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(resourceFilter, startFilter, endFilter)); + + foreach (var service in services) + { + var contributingResourceFilter = ReservationInstanceExposers.ResourceIDsInReservationInstance.Contains(service.ID); + + var orders = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(contributingResourceFilter)).ToList(); + + occupyingServices.Add(new OccupyingService(service, orders)); + } + + ShowRequestResult($"Reservations occupying '{resourceName}' from {start} ({start.Kind}) until {end} ({end.Kind})", string.Join("\n", occupyingServices.Select(o => o.ToString()))); + } + + private void ShowRequestResult(string header, params string[] results) + { + resultSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 5); + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(resourceSelectionLabel, ++row, 0); + AddWidget(resourceSelectionMethodRadioButtonList, row, 1); + + AddWidget(resourceIdLabel, ++row, 0); + AddWidget(resourceIdTextBox, row, 1); + AddWidget(enterCurrentIdButton, ++row, 1); + + AddWidget(resourcePoolLabel, ++row, 0); + AddWidget(resourcePoolDropDown, row, 1); + + AddWidget(resourceLabel, ++row, 0); + AddWidget(resourceDropDown, row, 1); + + AddWidget(startTimeLabel, ++row, 0); + AddWidget(startTimeDateTimePicker, row, 1); + + AddWidget(endTimeLabel, ++row, 0); + AddWidget(endTimeDateTimePicker, row, 1); + + AddWidget(timeZoneLabel, ++row, 1); + AddWidget(timeZone2Label, ++row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(getResourceOccupancyButton, ++row, 0, 1, 5); + AddWidget(new WhiteSpace(), ++row, 0); + + foreach (var resultSection in resultSections) + { + AddSection(resultSection,++row, 0); + row += resultSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ResponseSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ResponseSection.cs new file mode 100644 index 0000000..a70d9ac --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ResponseSection.cs @@ -0,0 +1,9 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug +{ + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public abstract class ResponseSection : Section + { + public abstract void Collapse(); + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceConfigurations/AddOrUpdateServiceConfigurationsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceConfigurations/AddOrUpdateServiceConfigurationsDialog.cs new file mode 100644 index 0000000..17904f3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceConfigurations/AddOrUpdateServiceConfigurationsDialog.cs @@ -0,0 +1,110 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.ServiceConfigurations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + + public class AddOrUpdateServiceConfigurationsDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label addOrUpdateServiceConfigurationsLabel = new Label("Add or Update Service Configuration") { Style = TextStyle.Heading }; + + private readonly Label orderIdLabel = new Label("Order ID"); + private readonly TextBox orderIdTextBox = new TextBox(string.Empty); + private readonly Button enterCurrentIdButton = new Button("Enter Current ID") { Width = 200 }; + + private readonly Label orderEndLabel = new Label("Order End"); + private readonly DateTimePicker orderEndDateTimePicker = new DateTimePicker(DateTime.Now); + private readonly Label timeZoneLabel = new Label($"Times are displayed here in the time zone of the client."); + + private readonly Label serviceConfigurationsLabel = new Label("Service Configurations"); + private readonly TextBox serviceConfigurationsTextBox = new TextBox { IsMultiline = true }; + + private readonly Button addOrUpdateButton = new Button("Add or Update"); + + private readonly List responseSections = new List(); + + public AddOrUpdateServiceConfigurationsDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Service Configurations"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private void Initialize() + { + enterCurrentIdButton.Pressed += (sender, args) => orderIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + + addOrUpdateButton.Pressed += AddOrUpdateButton_Pressed; + } + + private void AddOrUpdateButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(orderIdTextBox.Text, out Guid orderId)) + { + ShowRequestResult("Invalid Guid", "Invalid Guid"); + } + + bool successful = helpers.OrderManagerElement.AddOrUpdateServiceConfigurations(orderId, orderEndDateTimePicker.DateTime, serviceConfigurationsTextBox.Text); + + ShowRequestResult($"Update {(successful ? "succeeded" : "failed")} for ID {orderId}", $"Update {(successful ? "succeeded" : "failed")} for ID {orderId}"); + } + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(addOrUpdateServiceConfigurationsLabel, ++row, 0, 1, 5); + + AddWidget(orderIdLabel, ++row, 0, 1, 2); + AddWidget(orderIdTextBox, row, 2, 1, 2); + AddWidget(enterCurrentIdButton, ++row, 2, 1, 2); + + AddWidget(orderEndLabel, ++row, 0, 1, 2); + AddWidget(orderEndDateTimePicker, row, 2, 1, 2); + AddWidget(timeZoneLabel, ++row, 2, 1, 2); + + AddWidget(serviceConfigurationsLabel, ++row, 0, 1, 2); + AddWidget(serviceConfigurationsTextBox, row, 2, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(addOrUpdateButton, ++row, 0, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceConfigurations/FixServiceConfigurationsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceConfigurations/FixServiceConfigurationsDialog.cs new file mode 100644 index 0000000..ab5c0fd --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceConfigurations/FixServiceConfigurationsDialog.cs @@ -0,0 +1,161 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.ServiceConfigurations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using System.IO; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Configuration; + + public class FixServiceConfigurationsDialog : DebugDialog + { + private readonly Label fixServiceConfigurationsLabel = new Label("Fix Service Configurations") { Style = TextStyle.Heading }; + + private GetOrderReservationsSection getOrderReservationsSection; + + private readonly Button fixServiceConfigurationsButton = new Button("Fix Service Configurations") { Width = 200 }; + + private readonly Label descriptionLabel = new Label("This feature retrieves the last saved service configuration from the order logging and applies it to the order."); + + public FixServiceConfigurationsDialog(Helpers helpers) : base(helpers) + { + Title = "Fix Service Configurations"; + + Initialize(); + GenerateUi(); + } + + public event EventHandler ShowConfirmationDialog; + + public event EventHandler ShowProgressDialog; + + public event EventHandler OrdersUpdated; + + private void Initialize() + { + getOrderReservationsSection = new GetOrderReservationsSection(helpers); + + fixServiceConfigurationsButton.Pressed += (s, e) => FixServiceConfigurationsButton_Pressed(); + } + + private void FixServiceConfigurationsButton_Pressed() + { + if (!getOrderReservationsSection.IsValid) + { + ShowRequestResult("Invalid order IDs", "Invalid Order IDs"); + } + + var orderReservations = getOrderReservationsSection.GetOrderReservations().OrderBy(x => x.Start).ToList(); + if (!orderReservations.Any()) return; + + StringBuilder sb = new StringBuilder(); + sb.AppendLine($"Are you sure you want to fix the service configurations for following {orderReservations.Count} Order(s):"); + foreach (var orderReservation in orderReservations) sb.AppendLine($"\t-{orderReservation.Name} ({orderReservation.Start.ToLocalTime()} - {orderReservation.End.ToLocalTime()})"); + + ConfirmationDialog confirmationDialog = new ConfirmationDialog(helpers.Engine, sb.ToString()); + + confirmationDialog.YesButton.Pressed += (s, args) => FixServiceConfigurations(orderReservations); + + ShowConfirmationDialog?.Invoke(this, confirmationDialog); + } + + private void FixServiceConfigurations(IEnumerable orderReservations) + { + ProgressDialog progressDialog = new ProgressDialog(helpers.Engine) { Title = "Fixing Service Configurations" }; + progressDialog.OkButton.Pressed += (sender, args) => OrdersUpdated?.Invoke(this, EventArgs.Empty); + progressDialog.Show(false); + + List validOrders = new List(); + List ordersToFix = new List(); + + progressDialog.AddProgressLine($"Analyzing orders..."); + foreach (var orderReservation in orderReservations) + { + try + { + helpers.OrderManager.GetOrder(orderReservation); + validOrders.Add(orderReservation); + + progressDialog.AddProgressLine($"Order {orderReservation.Name} is valid, no need to fix service configuration"); + } + catch (Exception) + { + ordersToFix.Add(orderReservation); + } + } + + progressDialog.AddProgressLine($"Finished analyzing orders"); + + List fixedOrders = new List(); + Dictionary unfixedOrders = new Dictionary(); + + progressDialog.AddProgressLine($"Fixing orders..."); + foreach (var order in ordersToFix) + { + try + { + string fileName = $@"{FixedFileLogger.SkylineDataFilePath}{Configuration.Constants.OrderLoggingDirectoryName}\{order.ID}{FixedFileLogger.TextFileExtension}"; + + string lineContainingLastSave = File.ReadAllLines(fileName).Last(x => x.Contains("OrderManagerElement|AddOrUpdateServiceConfigurations|Saving service configurations:")); + + int startIndex = lineContainingLastSave.IndexOf('{'); + int endIndex = lineContainingLastSave.LastIndexOf('}'); + string serializedServiceConfiguration = lineContainingLastSave.Substring(startIndex, endIndex - startIndex + 1); + + JsonConvert.DeserializeObject>(serializedServiceConfiguration); + + if (!helpers.OrderManagerElement.AddOrUpdateServiceConfigurations(order.ID, order.End, serializedServiceConfiguration)) throw new InvalidOperationException("Unable to save service configuration"); + + fixedOrders.Add(order); + + progressDialog.AddProgressLine($"Fixing order {order.Name}"); + } + catch (Exception e) + { + unfixedOrders.Add(order, e); + + progressDialog.AddProgressLine($"Unable to fix order {order.Name}"); + } + } + + progressDialog.AddProgressLine($"Finished fixing orders"); + + string validOrdersResult = $"Valid Orders (no service config fix required):\n{String.Join("\n", validOrders.Select(x => $"{x.Name} [{x.Start} - {x.End}]"))}"; + string fixedOrdersResult = $"Fixed Orders:\n{String.Join("\n", fixedOrders.Select(x => $"{x.Name} [{x.Start} - {x.End}]"))}"; + string unfixedOrdersResult = $"Unable to fix following orders:\n{String.Join("\n", unfixedOrders.Select(x => $"{x.Key.Name} [{x.Key.Start} - {x.Key.End}] due to: {x.Value}"))}"; + + ShowRequestResult($"Updated Orders {DateTime.Now.ToShortTimeString()}", new string[] { fixedOrdersResult, unfixedOrdersResult, validOrdersResult }); + GenerateUi(); + + progressDialog.Finish(); + ShowProgressDialog?.Invoke(this, progressDialog); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(fixServiceConfigurationsLabel, ++row, 0, 1, 5); + + AddWidget(descriptionLabel, ++row, 0, 1, 5); + + AddSection(getOrderReservationsSection, ++row, 0); + row += getOrderReservationsSection.RowCount; + + AddWidget(fixServiceConfigurationsButton, ++row, 0, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceConfigurations/GetServiceConfigurationsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceConfigurations/GetServiceConfigurationsDialog.cs new file mode 100644 index 0000000..099d698 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceConfigurations/GetServiceConfigurationsDialog.cs @@ -0,0 +1,195 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.ServiceConfigurations +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using System.Diagnostics; + using System.Threading.Tasks; + using Skyline.DataMiner.Net.Messages; + + public class GetServiceConfigurationsDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label findServiceConfigurationsLabel = new Label("Find Service Configuration") { Style = TextStyle.Heading }; + + private readonly Label orderNameLabel = new Label("Order Name"); + private readonly TextBox orderNameTextBox = new TextBox(string.Empty); + private readonly Button findByNameButton = new Button("Find by Name") { Width = 150 }; + + private readonly Label orderIdLabel = new Label("Order ID"); + private readonly TextBox orderIdTextBox = new TextBox(string.Empty); + private readonly Button findByIdButton = new Button("Find by ID") { Width = 150 }; + private readonly Button enterCurrentIdButton = new Button("Enter Current ID") { Width = 200 }; + + private readonly Button findReservationsWithMissingOrEmptyServiceConfigurations = new Button("Find Missing Service Configurations"); + private readonly Label fromLabel = new Label("from"); + private readonly DateTimePicker startDateTimePicker = new DateTimePicker(DateTime.UtcNow); + private readonly Label untilLabel = new Label("until"); + private readonly DateTimePicker endDateTimePicker = new DateTimePicker(DateTime.UtcNow.AddDays(1)); + + private readonly Button executeSetsOnOrderManagerElementButton = new Button("Load test for Order Manager Element [DCP208819]"); + private readonly Label amountOfSetsLabel = new Label("Amount of Sets"); + private readonly Numeric amountOfSetsNumeric = new Numeric(); + + private readonly List responseSections = new List(); + + public GetServiceConfigurationsDialog(Helpers helpers) : base(helpers.Engine) + { + this.helpers = helpers; + + Title = "Service Configurations"; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back..."){Width = 150}; + + private void Initialize() + { + findByNameButton.Pressed += FindByNameButton_Pressed; + + findByIdButton.Pressed += FindByIdButton_Pressed; + + findReservationsWithMissingOrEmptyServiceConfigurations.Pressed += FindReservationsWithMissingOrEmptyServiceConfigurations_Pressed; + + executeSetsOnOrderManagerElementButton.Pressed += ExecuteSetsOnOrderManagerElementButton_Pressed; + + enterCurrentIdButton.Pressed += (sender, args) => orderIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + } + + private void ExecuteSetsOnOrderManagerElementButton_Pressed(object sender, EventArgs e) + { + var startTime = new DateTime(2020,1,1); + var endTime = new DateTime(2024,1,1); + + var reservations = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, ReservationInstanceExposers.Start.GreaterThanOrEqual(startTime).AND(ReservationInstanceExposers.End.LessThanOrEqual(endTime)).AND(ReservationInstanceExposers.Properties.DictStringField("Type").Equal("Video"))).Take((int)amountOfSetsNumeric.Value / 7); + + var reservationsToLoopOver = reservations.Concat(reservations).Concat(reservations).Concat(reservations).Concat(reservations).Concat(reservations).Concat(reservations).ToList(); + + var element = Engine.FindElement("Order Manager"); + + var stopwatch = Stopwatch.StartNew(); + + Parallel.ForEach(reservationsToLoopOver, (reservation) => AutomationExtensions.TryStartScript(helpers, "RequestServiceConfigurationFromOrderManager", new Dictionary { { 2, reservation.ID.ToString() } }, false, false)); + + ShowRequestResult($"Executed {(int)amountOfSetsNumeric.Value} sets on order manager in {stopwatch.Elapsed}"); + } + + private void FindReservationsWithMissingOrEmptyServiceConfigurations_Pressed(object sender, EventArgs e) + { + var startTime = startDateTimePicker.DateTime; + var endTime = endDateTimePicker.DateTime; + + var reservations = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, ReservationInstanceExposers.Start.GreaterThanOrEqual(startTime).AND(ReservationInstanceExposers.End.LessThanOrEqual(endTime)).AND(ReservationInstanceExposers.Properties.DictStringField("Type").Equal("Video"))); + + var ordersWithInvalidServiceConfig = new List(); + + foreach (var orderReservation in reservations) + { + if (!helpers.OrderManagerElement.TryGetServiceConfigurations(orderReservation.ID, out var serviceConfigurations)) + { + ordersWithInvalidServiceConfig.Add(orderReservation); + } + } + + ShowRequestResult($"Orders from {startTime} until {endTime} with invalid service configs", $"Checked {reservations.Count()} orders:\n{string.Join("\n", ordersWithInvalidServiceConfig.Select(o => o.Name))}", string.Join("\n", ordersWithInvalidServiceConfig.Select(o => o.ID)), string.Join("\n", ordersWithInvalidServiceConfig.Select(o => o.CreatedAt))); + } + + private void FindByIdButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(orderIdTextBox.Text, out var guid)) return; + + ShowRequestResult($"Order {guid} service configuration", $"{helpers.OrderManagerElement.GetSerializedServiceConfigurations(guid)}"); + } + + private void FindByNameButton_Pressed(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(orderNameTextBox.Text)) + { + orderNameTextBox.Text = String.Empty; + orderNameTextBox.ValidationText = "Fill out the Name of a reservation"; + orderNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstances = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(ReservationInstanceExposers.Name.Contains(orderNameTextBox.Text))); + if (!reservationInstances.Any()) + { + orderNameTextBox.Text = String.Empty; + orderNameTextBox.ValidationText = "Unable to find a reservation with the specified Name"; + orderNameTextBox.ValidationState = UIValidationState.Invalid; + return; + } + + var reservationInstance = reservationInstances.First(); + + orderNameTextBox.Text = reservationInstance.Name; + orderIdTextBox.Text = reservationInstance.ID.ToString(); + orderNameTextBox.ValidationState = UIValidationState.Valid; + + ShowRequestResult($"Order {reservationInstance.Name} service configuration", $"{helpers.OrderManagerElement.GetSerializedServiceConfigurations(reservationInstance.ID)}"); + } + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(findServiceConfigurationsLabel, ++row, 0, 1, 5); + + AddWidget(orderNameLabel, ++row, 0, 1, 2); + AddWidget(orderNameTextBox, row, 2, 1, 2); + AddWidget(findByNameButton, row, 4); + + AddWidget(orderIdLabel, ++row, 0, 1, 2); + AddWidget(orderIdTextBox, row, 2, 1, 2); + AddWidget(findByIdButton, row, 4); + AddWidget(enterCurrentIdButton, ++row, 2, 1, 2); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(findReservationsWithMissingOrEmptyServiceConfigurations, ++row, 0, 1, 2); + AddWidget(fromLabel, row, 2); + AddWidget(startDateTimePicker, row, 3); + AddWidget(untilLabel, ++row, 2); + AddWidget(endDateTimePicker, row, 3); + + AddWidget(new WhiteSpace(), ++row, 1); + + AddWidget(executeSetsOnOrderManagerElementButton, ++row, 0, 1, 2); + AddWidget(amountOfSetsLabel, row, 2); + AddWidget(amountOfSetsNumeric, row, 3); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/FixMissingServiceDefinitionsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/FixMissingServiceDefinitionsDialog.cs new file mode 100644 index 0000000..a7fc3d9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/FixMissingServiceDefinitionsDialog.cs @@ -0,0 +1,727 @@ +namespace Debug_2.Debug.ServiceDefinitions +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ServiceDefinition; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Net.ServiceManager.Objects; + using SrmServiceDefinition = Skyline.DataMiner.Net.ServiceManager.Objects.ServiceDefinition; + + public class FixMissingServiceDefinitionsDialog : DebugDialog + { + private MisingServiceDefinitionSection section; + private int missingServiceDefinitions = 0; + private readonly Button findReservationsButton = new Button("Find Reservations without Service Definition"); + private bool initialized = false; + + public FixMissingServiceDefinitionsDialog(Helpers helpers) : base(helpers) + { + Title = "Fix Missing Service Definitions"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + findReservationsButton.Pressed += (s, e) => + { + FindReservationsWithoutServiceDefinitions(); + GenerateUi(); + }; + } + + private void FindReservationsWithoutServiceDefinitions() + { + var allServiceDefinitionIds = SrmManagers.ServiceManager.GetServiceDefinitions(ServiceDefinitionExposers.ID.NotEqual(Guid.Empty)).Select(x => x.ID).ToList(); + + List> filters = new List> + { + //ReservationInstanceExposers.Start.GreaterThan(new DateTime(2023, 1, 1)) + }; + + filters.AddRange(allServiceDefinitionIds.Select(x => ServiceReservationInstanceExposers.ServiceDefinitionID.NotEqual(x))); + + FilterElement filter = new ANDFilterElement(filters.ToArray()); + + var affectedReservations = SrmManagers.ResourceManager.GetReservationInstances(filter).Cast(); + + Dictionary> groupedReservations = new Dictionary>(); + foreach (var affectedReservation in affectedReservations) + { + if (groupedReservations.TryGetValue(affectedReservation.ServiceDefinitionID, out List reservations)) + { + reservations.Add(affectedReservation); + } + else + { + groupedReservations.Add(affectedReservation.ServiceDefinitionID, new List { affectedReservation }); + } + } + + missingServiceDefinitions = groupedReservations.Count; + section = null; + initialized = true; + + if (!groupedReservations.Any()) return; + + var mostInfluentialServiceDefinition = groupedReservations.OrderByDescending(x => x.Value.Count).FirstOrDefault(); + section = new MisingServiceDefinitionSection(helpers, mostInfluentialServiceDefinition.Key, mostInfluentialServiceDefinition.Value); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(new Label("Find Reservations Without Valid Service Definition") { Style = TextStyle.Heading }, ++row, 0, 1, 2); + AddWidget(new Label("Searches for Reservations that either don't have a Service Definition assigned to them or for which the Service Definition can not be retrieved."), ++row, 0, 1, 2); + + AddWidget(findReservationsButton, ++row, 0, 1, 2); + + if (initialized) + { + if (section == null) + { + AddWidget(new Label("No invalid reservations found"), ++row, 0, 1, 2); + } + else + { + AddWidget(new Label("Missing Service Definitions:"), ++row, 0); + AddWidget(new Label(missingServiceDefinitions.ToString()), row, 1, horizontalAlignment: HorizontalAlignment.Right); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddSection(section, new SectionLayout(++row, 0)); + row += section.RowCount; + AddWidget(new WhiteSpace(), ++row, 0); + } + } + } + + private class MisingServiceDefinitionSection : Section + { + private readonly Helpers helpers; + private readonly Guid id; + private readonly ICollection affectedReservationInstances; + private readonly TextBox serviceDefinitionTextBox = new TextBox() { IsMultiline = true, Height = 400 }; + private readonly TextBox uploadServiceDefinitionTextBox = new TextBox() { IsMultiline = true, Height = 200 }; + + private ConnectionsSection connectionsSection; + private Dictionary serviceConfigurations = new Dictionary(); + private List fixedNodes; + + public readonly Button UploadButton = new Button("Upload Service Definition"); + public readonly Button GenerateServiceDefinitionButton = new Button("Generate Service Definition"); + public readonly Button DeleteServiceDefinitionButton = new Button("Delete Service Definition"); + + public MisingServiceDefinitionSection(Helpers helpers, Guid id, ICollection affectedReservationInstances) + { + this.helpers = helpers; + this.id = id; + this.affectedReservationInstances = affectedReservationInstances; + + Initialize(); + GenerateUi(); + } + + public Guid ID => id; + + public int AffectedReservationsCount => affectedReservationInstances.Count; + + public int NodeCount => serviceConfigurations.Count; + + private void Initialize() + { + serviceConfigurations = GetMostCompleteServiceConfiguration(); + if (serviceConfigurations == null) return; + + fixedNodes = ConvertToFixedNodes(serviceConfigurations); + + connectionsSection = new ConnectionsSection(fixedNodes); + + GenerateServiceDefinitionButton.Pressed += (s, e) => GenerateServiceDefinition(); + + UploadButton.Pressed += (s, e) => UploadServiceDefinition(); + + DeleteServiceDefinitionButton.Pressed += (s, e) => DeleteServiceDefinition(); + } + + private void DeleteServiceDefinition() + { + try + { + var srmServiceDefinition = SrmManagers.ServiceManager.GetServiceDefinition(id); + SrmManagers.ServiceManager.RemoveServiceDefinitions(out string error, srmServiceDefinition); + + if (!String.IsNullOrWhiteSpace(error)) + { + uploadServiceDefinitionTextBox.Text = $"Unable to delete service definition due to {error}"; + } + else + { + uploadServiceDefinitionTextBox.Text = $"Deleting service definition {id} was successful"; + } + } + catch (Exception e) + { + uploadServiceDefinitionTextBox.Text = $"Unable to delete service definition due to {e}"; + } + } + + private void UploadServiceDefinition() + { + if (String.IsNullOrWhiteSpace(serviceDefinitionTextBox.Text)) return; + try + { + var serviceDefinition = JsonConvert.DeserializeObject(serviceDefinitionTextBox.Text); + SrmManagers.ServiceManager.AddOrUpdateServiceDefinition(serviceDefinition); + uploadServiceDefinitionTextBox.Text = $"Uploading service definition {serviceDefinition.ID} was successful"; + } + catch (Exception e) + { + uploadServiceDefinitionTextBox.Text = $"Unable to upload service definition due to {e}"; + } + } + + private void GenerateServiceDefinition() + { + var serviceDefinition = new SrmServiceDefinition(id) + { + Name = id.ToString(), + IsTemplate = true, + Description = String.Empty, + Properties = new List + { + new Property("Virtual Platform", "Order") + }, + Scripts = new List + { + new Skyline.DataMiner.Net.Profiles.ScriptEntry + { + Name = "START", + Description = null, + Script = "HandleOrderAction" + }, + new Skyline.DataMiner.Net.Profiles.ScriptEntry + { + Name = "STOP", + Description = null, + Script = "HandleOrderAction" + }, + }, + Diagram = new Graph + { + Nodes = new List(), + Edges = new List() + } + }; + + DeterminePositions(); + + foreach (var node in fixedNodes) + { + string resourcePool; + SystemFunctionDefinition systemFunctionDefinition; + + bool isDummyReception = node.ServiceDefinitionId == Guid.Empty; + if (isDummyReception) + { + var randomReceptionServiceDefinition = SrmManagers.ServiceManager.GetServiceDefinition(ServiceDefinitionGuids.FixedLineYleHelsinkiReceptionServiceDefinitionId) ?? throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ServiceDefinition.ServiceDefinitionNotFoundException($"Unable to find service definition {ServiceDefinitionGuids.FixedLineYleHelsinkiReceptionServiceDefinitionId}"); + + var contributingConfig = GetContributingConfig(randomReceptionServiceDefinition) ?? throw new InvalidOperationException($"Unable to get contributing config for SD {randomReceptionServiceDefinition.ID}"); + + systemFunctionDefinition = SrmManagers.ProtocolFunctionManager.GetFunctionDefinition(new Skyline.DataMiner.Net.FunctionDefinitionID(Guid.Parse(contributingConfig.ParentSystemFunction))) ?? throw new FunctionNotFoundException(contributingConfig.ParentSystemFunction); + resourcePool = "not applicable"; + } + else + { + var nodeServiceDefinition = SrmManagers.ServiceManager.GetServiceDefinition(node.ServiceDefinitionId) ?? throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ServiceDefinition.ServiceDefinitionNotFoundException($"Unable to find service definition {node.ServiceDefinitionId}"); + var contributingConfig = GetContributingConfig(nodeServiceDefinition) ?? throw new InvalidOperationException($"Unable to get contributing config for SD {nodeServiceDefinition.ID}"); + + systemFunctionDefinition = SrmManagers.ProtocolFunctionManager.GetFunctionDefinition(new Skyline.DataMiner.Net.FunctionDefinitionID(Guid.Parse(contributingConfig.ParentSystemFunction))) ?? throw new FunctionNotFoundException(contributingConfig.ParentSystemFunction); + + resourcePool = contributingConfig.ResourcePool; + } + + serviceDefinition.Diagram.Nodes.Add(new Node + { + ID = node.Id, + Label = $"{systemFunctionDefinition.Name} [{node.Id}]", + Position = new Position(node.Row, node.Column), + Properties = new[] + { + new Property { Name = "Options", Value = "Optional" }, + new Property { Name = "Resource Pool", Value = resourcePool }, + new Property { Name = "IsContributing", Value = "TRUE" }, + new Property { Name= "IsProfileInstanceOptional", Value = "TRUE" } + }.ToList(), + Configuration = new NodeConfiguration + { + FunctionID = systemFunctionDefinition.GUID, + }, + InterfaceConfigurations = GetNodeInterfaceConfiguration(systemFunctionDefinition).ToArray() + }); + } + + serviceDefinition.Diagram.Edges = GetEdges(serviceDefinition.Diagram.Nodes).ToList(); + + serviceDefinitionTextBox.Text = JsonConvert.SerializeObject(serviceDefinition, Formatting.Indented); + } + + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ContributingConfig GetContributingConfig(SrmServiceDefinition serviceDefinition) + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ContributingConfig contributingConfig = null; + try + { + var contributingConfigProperty = serviceDefinition.Properties.FirstOrDefault(p => String.Equals(p.Name, "Contributing Config", StringComparison.InvariantCultureIgnoreCase)); + + contributingConfig = JsonConvert.DeserializeObject(contributingConfigProperty.Value); + } + catch (Exception) + { + } + + return contributingConfig; + } + + private IEnumerable GetNodeInterfaceConfiguration(Skyline.DataMiner.Net.Messages.SystemFunctionDefinition functionDefinition) + { + var nodeInterfaces = new List(); + + foreach (var inputInterface in functionDefinition.InputInterfaces) + { + nodeInterfaces.Add(new InterfaceConfiguration + { + ID = inputInterface.Id, + Type = InterfaceType.In, + ProfileDefinitionID = inputInterface.ProfileDefinition, + Properties = new List + { + new Property { Name= "IsProfileInstanceOptional", Value = "TRUE" } + } + }); + } + + foreach (var outputInterface in functionDefinition.OutputInterfaces) + { + nodeInterfaces.Add(new InterfaceConfiguration + { + ID = outputInterface.Id, + Type = InterfaceType.Out, + ProfileDefinitionID = outputInterface.ProfileDefinition, + Properties = new List + { + new Property { Name= "IsProfileInstanceOptional", Value = "TRUE" } + } + }); + } + + foreach (var inputOutputInterface in functionDefinition.InputOutputInterfaces) + { + nodeInterfaces.Add(new InterfaceConfiguration + { + ID = inputOutputInterface.Id, + Type = InterfaceType.InOut, + ProfileDefinitionID = inputOutputInterface.ProfileDefinition, + Properties = new List + { + new Property { Name= "IsProfileInstanceOptional", Value = "TRUE" } + } + }); + } + + return nodeInterfaces; + } + + private void DeterminePositions() + { + var edges = connectionsSection.Edges; + + // Get source connections + var sourceNodes = fixedNodes.Where(x => !x.HasInputInfo && x.HasOutputInfo); + + int row = 0; + int column = 0; + SetPositions(edges, sourceNodes, ref row, column); + } + + private void SetPositions(IEnumerable edges, IEnumerable nodes, ref int row, int column) + { + if (!nodes.Any()) + { + row += 1; + return; + } + + foreach (var node in nodes) + { + node.Row = row; + node.Column = column; + + var childNodes = edges.Where(x => x.From.Equals(node)).Select(x => x.To).ToList(); + + SetPositions(edges, childNodes, ref row, column + 1); + } + } + + private IEnumerable GetEdges(IEnumerable configuredNodes) + { + List edges = new List(); + foreach (var fixedEdge in connectionsSection.Edges) + { + var outputNode = configuredNodes.FirstOrDefault(x => x.ID.Equals(fixedEdge.From.Id)); + var inputNode = configuredNodes.FirstOrDefault(x => x.ID.Equals(fixedEdge.To.Id)); + + edges.Add(new Edge + { + FromNodeID = fixedEdge.From.Id, + FromNodeInterfaceID = outputNode.InterfaceConfigurations.FirstOrDefault(x => x.Type == InterfaceType.Out).ID, + ToNodeID = fixedEdge.To.Id, + ToNodeInterfaceID = inputNode.InterfaceConfigurations.FirstOrDefault(x => x.Type == InterfaceType.In).ID, + }); + } + + return edges; + } + + private Dictionary GetMostCompleteServiceConfiguration() + { + int maxAssignedResources = -1; + Dictionary serviceConfigurations = null; + ReservationInstance orderReservation = null; + foreach (var reservation in affectedReservationInstances) + { + if (!helpers.OrderManagerElement.TryGetServiceConfigurations(reservation.ID, out var configs)) continue; + + int assignedResources = CountAssignedResources(configs); + if (maxAssignedResources < assignedResources) + { + maxAssignedResources = assignedResources; + serviceConfigurations = configs; + orderReservation = reservation; + } + } + + helpers.Log(nameof(FixMissingServiceDefinitionsDialog), nameof(GetMostCompleteServiceConfiguration), $"Found service configs for order {orderReservation.Name} ({orderReservation.ID})"); + + return serviceConfigurations; + } + + private int CountAssignedResources(Dictionary serviceConfigurations) + { + int count = 0; + foreach (var kvp in serviceConfigurations) + { + foreach (var function in kvp.Value.Functions) + { + if (String.IsNullOrEmpty(function.Value.ResourceName) || function.Value.ResourceName.Equals("None")) continue; + if (function.Value.ResourceId.Equals(Guid.Empty)) continue; + + count += 1; + } + } + + return count; + } + + private List ConvertToFixedNodes(Dictionary serviceConfigurations) + { + if (serviceConfigurations.Values.Any(x => x.Name.Contains("VIZREM"))) + { + return ConvertVizremConfigurationToFixedNodes(serviceConfigurations); + } + else + { + return ConvertLiveVideoConfigurationToFixedNodes(serviceConfigurations); + } + } + + private List ConvertLiveVideoConfigurationToFixedNodes(Dictionary serviceConfigurations) + { + List fixedNodes = new List(); + var matrixInputFunctionGuids = FunctionGuids.AllMatrixInputGuids.ToList(); + var matrixOutputFunctionGuids = FunctionGuids.AllMatrixOutputGuids.ToList(); + + foreach (var kvp in serviceConfigurations) + { + FixedNode node = new FixedNode + { + Id = kvp.Key, + DisplayName = kvp.Value.Name, + ServiceDefinitionId = kvp.Value.ServiceDefinitionId, + IntegrationType = kvp.Value.IntegrationType + }; + + var functionIds = kvp.Value.Functions.Select(x => x.Value.Id).ToList(); + + bool hasRoutingInputFunction = functionIds.Any(x => matrixInputFunctionGuids.Contains(x)) || kvp.Value.Functions.Values.Any(x => x.Name.Contains("Input")); + bool hasRoutingOutputFunction = functionIds.Any(x => matrixOutputFunctionGuids.Contains(x)) || kvp.Value.Functions.Values.Any(x => x.Name.Contains("Output")); + + if (kvp.Value.Name.Contains("Reception")) + { + // Input service + var outputFunction = kvp.Value.Functions.Values.LastOrDefault(); + node.OutputFunctionName = outputFunction?.Name ?? "dummy source output function"; + node.OutputResource = outputFunction?.ResourceName ?? "dummy source output resource"; + } + else if (hasRoutingInputFunction && hasRoutingOutputFunction) + { + // Routing service + var inputFunction = kvp.Value.Functions.Values.FirstOrDefault(); + node.InputFunctionName = inputFunction?.Name ?? "dummy routing input function"; + node.InputResource = inputFunction?.ResourceName ?? "dummy routing input resource"; + + var outputFunction = kvp.Value.Functions.Values.LastOrDefault(); + node.OutputFunctionName = outputFunction?.Name ?? "dummy routing output function"; + node.OutputResource = outputFunction?.ResourceName ?? "dummy routing output resource"; + } + else if (kvp.Value.Name.Contains("Destination") && kvp.Value.IntegrationType == Skyline.DataMiner.Utils.YLE.Integrations.IntegrationType.Plasma) + { + // Plasma Destination service -> could be used as input for recordings after destinations + var inputFunction = kvp.Value.Functions.Values.FirstOrDefault(); + node.InputFunctionName = inputFunction?.Name ?? "dummy plasma destination input function"; + node.InputResource = inputFunction?.ResourceName ?? "dummy plasma destination input resource"; + + var outputFunction = kvp.Value.Functions.Values.LastOrDefault(); + node.OutputFunctionName = outputFunction?.Name ?? "dummy plasma destination output function"; + node.OutputResource = outputFunction?.ResourceName ?? "dummy plasma destination output resource"; + } + else if (kvp.Value.Name.Contains("Processing")) + { + // Processing service should be handled as routing + var inputFunction = kvp.Value.Functions.Values.FirstOrDefault(); + node.InputFunctionName = inputFunction?.Name ?? "dummy processing input function"; + node.InputResource = inputFunction?.ResourceName ?? "dummy processing input resource"; + + var outputFunction = kvp.Value.Functions.Values.LastOrDefault(); + node.OutputFunctionName = outputFunction?.Name ?? "dummy processing output function"; + node.OutputResource = outputFunction?.ResourceName ?? "dummy processing output resource"; + } + else + { + // Output service + var inputFunction = kvp.Value.Functions.Values.FirstOrDefault(); + node.InputFunctionName = inputFunction?.Name ?? "dummy destination/transmission/recording input function"; + node.InputResource = inputFunction?.ResourceName ?? "dummy destination/transmission/recording input resource"; + } + + fixedNodes.Add(node); + } + + return fixedNodes; + } + + private List ConvertVizremConfigurationToFixedNodes(Dictionary serviceConfigurations) + { + List fixedNodes = new List(); + foreach(var kvp in serviceConfigurations) + { + if (kvp.Key == 1) + { + // First node + fixedNodes.Add(new FixedNode + { + Id = kvp.Key, + DisplayName = kvp.Value.Name, + ServiceDefinitionId = kvp.Value.ServiceDefinitionId, + IntegrationType = kvp.Value.IntegrationType, + OutputFunctionName = kvp.Value.Functions.Last().Value.Name, + OutputResource = kvp.Value.Functions.Last().Value.ResourceName + }); + } + else if (kvp.Key == serviceConfigurations.Last().Key) + { + // Last node + fixedNodes.Add(new FixedNode + { + Id = kvp.Key, + DisplayName = kvp.Value.Name, + ServiceDefinitionId = kvp.Value.ServiceDefinitionId, + IntegrationType = kvp.Value.IntegrationType, + InputFunctionName = kvp.Value.Functions.First().Value.Name, + InputResource = kvp.Value.Functions.First().Value.ResourceName + }); + } + else + { + fixedNodes.Add(new FixedNode + { + Id = kvp.Key, + DisplayName = kvp.Value.Name, + ServiceDefinitionId = kvp.Value.ServiceDefinitionId, + IntegrationType = kvp.Value.IntegrationType, + InputFunctionName = kvp.Value.Functions.First().Value.Name, + InputResource = kvp.Value.Functions.First().Value.ResourceName, + OutputFunctionName = kvp.Value.Functions.Last().Value.Name, + OutputResource = kvp.Value.Functions.Last().Value.ResourceName + }); + } + } + + return fixedNodes; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(new Label(id.ToString()) { Style = TextStyle.Heading }, ++row, 0, 1, 2); + + AddWidget(new Label("Affected Reservations"), ++row, 0); + AddWidget(new Label(AffectedReservationsCount.ToString()), row, 1, horizontalAlignment: HorizontalAlignment.Right); + + AddWidget(new TextBox(String.Join(Environment.NewLine.ToString(), affectedReservationInstances.OrderByDescending(x => x.Start).Select(x => $"{x.Name} [{x.ID}] ({x.Start} - {x.End})"))) { IsMultiline = true, Height = 200 }, ++row, 0, 1, 2); + + if (serviceConfigurations == null) + { + AddWidget(new Label("No Valid Service Configuration Available"), ++row, 0, 1, 2); + } + else + { + AddWidget(new Label("Amount of Nodes"), ++row, 0); + AddWidget(new Label(NodeCount.ToString()), row, 1, horizontalAlignment: HorizontalAlignment.Right); + + AddWidget(new Label("Valid Service Configuration"), ++row, 0, 1, 2); + AddWidget(new TextBox(JsonConvert.SerializeObject(serviceConfigurations, Formatting.Indented)) { Height = 400, IsMultiline = true }, ++row, 0, 1, 2); + + AddSection(connectionsSection, new SectionLayout(++row, 0)); + row += connectionsSection.RowCount; + + AddWidget(GenerateServiceDefinitionButton, ++row, 0, 1, 2); + AddWidget(serviceDefinitionTextBox, ++row, 0, 1, 2); + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(UploadButton, ++row, 0, 1, 2); + AddWidget(DeleteServiceDefinitionButton, ++row, 0, 1, 2); + AddWidget(uploadServiceDefinitionTextBox, ++row, 0, 1, 2); + } + } + } + + private class ConnectionsSection : Section + { + private readonly Dictionary inputNodes = new Dictionary(); + private readonly Dictionary outputNodes = new Dictionary(); + private readonly List> connectionDropDowns = new List>(); + + public ConnectionsSection(ICollection nodes) + { + Initialize(nodes); + GenerateUi(); + } + + public ICollection Edges + { + get + { + List edges = new List(); + foreach (var tuple in connectionDropDowns) + { + edges.Add(new FixedEdge + { + From = outputNodes[tuple.Item1.Selected], + To = inputNodes[tuple.Item2.Text] + }); + } + + return edges; + } + } + + private void Initialize(ICollection nodes) + { + foreach (var node in nodes) + { + if (node.HasInputInfo) inputNodes.Add($"Node {node.Id} ({node.DisplayName}) [{node.InputResource}] {(node.IntegrationType == Skyline.DataMiner.Utils.YLE.Integrations.IntegrationType.None ? String.Empty : node.IntegrationType.ToString())}", node); + if (node.HasOutputInfo) outputNodes.Add($"Node {node.Id} ({node.DisplayName}) [{node.OutputResource}] {(node.IntegrationType == Skyline.DataMiner.Utils.YLE.Integrations.IntegrationType.None ? String.Empty : node.IntegrationType.ToString())}", node); + } + + foreach (var inputNode in inputNodes) + { + DropDown outputDropDown = new DropDown(outputNodes.Keys.Where(x => outputNodes[x] != inputNode.Value)); // Node cannot be connected to itself + Label label = new Label(inputNode.Key); + connectionDropDowns.Add(new Tuple(outputDropDown, label)); + } + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(new Label("Connections") { Style = TextStyle.Heading }, ++row, 0, 1, 2); + for (int i = 0; i < connectionDropDowns.Count; i++) + { + AddWidget(new Label($"Connection {i + 1}"), ++row, 0, 1, 2); + AddWidget(new Label("From"), ++row, 0); + AddWidget(connectionDropDowns[i].Item1, row, 1); + AddWidget(new Label("To"), ++row, 0); + AddWidget(connectionDropDowns[i].Item2, row, 1); + AddWidget(new WhiteSpace(), ++row, 0); + } + } + } + + private class FixedNode + { + public int Id { get; set; } = 0; + + public string DisplayName { get; set; } + + public string InputFunctionName { get; set; } = String.Empty; + + public string InputResource { get; set; } = null; + + public string OutputFunctionName { get; set; } = String.Empty; + + public string OutputResource { get; set; } = null; + + public Guid ServiceDefinitionId { get; set; } = Guid.Empty; + + public int Column { get; set; } = 0; + + public int Row { get; set; } = 0; + + public Skyline.DataMiner.Utils.YLE.Integrations.IntegrationType IntegrationType { get; set; } = Skyline.DataMiner.Utils.YLE.Integrations.IntegrationType.None; + + public bool HasInputInfo => !String.IsNullOrEmpty(InputFunctionName) && !String.IsNullOrEmpty(InputResource); + + public bool HasOutputInfo => !String.IsNullOrEmpty(OutputFunctionName) && !String.IsNullOrEmpty(OutputResource); + + public override bool Equals(object obj) + { + if (!(obj is FixedNode otherNode)) return false; + return Id.Equals(otherNode.Id); + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } + } + + private class FixedEdge + { + public FixedNode From { get; set; } + + public FixedNode To { get; set; } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/GetServiceDefinitionDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/GetServiceDefinitionDialog.cs new file mode 100644 index 0000000..11ab644 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/GetServiceDefinitionDialog.cs @@ -0,0 +1,109 @@ +namespace Debug_2.Debug.ServiceDefinitions +{ + using System; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.ServiceManager.Objects; + + public class GetServiceDefinitionDialog : DebugDialog + { + private GetServiceDefinitionsSection getServiceDefinitionsSection; + + private readonly Button showJsonButton = new Button("Show Service Definitions JSON"); + private readonly Button setDiagramHashCodePropertyButton = new Button("Set Diagram Hash Code Property"); + private readonly Button getDiagramHashCodeButton = new Button("Calculate Diagram Hash Code"); + + public GetServiceDefinitionDialog(Helpers helpers) : base(helpers) + { + Title = "Get Service Definition"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + getServiceDefinitionsSection = new GetServiceDefinitionsSection(helpers); + + getServiceDefinitionsSection.RegenerateUi += GetServiceDefinitionsSection_RegenerateUi; + + showJsonButton.Pressed += ShowJsonButton_Pressed; + setDiagramHashCodePropertyButton.Pressed += SetDiagramHashCodePropertyButton_Pressed; + getDiagramHashCodeButton.Pressed += CalculateDiagramHashCodeButton_Pressed; + } + + private void CalculateDiagramHashCodeButton_Pressed(object sender, EventArgs e) + { + ShowRequestResult("Diagram Hash Codes", string.Join(", ", getServiceDefinitionsSection.SelectedServiceDefinitions.Select(sd => $"{sd.Name} => {sd.Diagram.GetHashCodeForYleProject()}"))); + GenerateUi(); + } + + private void SetDiagramHashCodePropertyButton_Pressed(object sender, EventArgs e) + { + foreach (var serviceDefinition in getServiceDefinitionsSection.SelectedServiceDefinitions) + { + var diagramHashCodeProperty = serviceDefinition.Properties.SingleOrDefault(p => p.Name == ServiceDefinitionPropertyNames.DiagramHashCode); + + if (diagramHashCodeProperty is null) + { + diagramHashCodeProperty = new Property(ServiceDefinitionPropertyNames.DiagramHashCode, serviceDefinition.Diagram.GetHashCodeForYleProject().ToString()); + serviceDefinition.Properties.Add(diagramHashCodeProperty); + } + else + { + diagramHashCodeProperty.Value = serviceDefinition.Diagram.GetHashCodeForYleProject().ToString(); + } + + DataMinerInterface.ServiceManager.AddOrUpdateServiceDefinition(helpers, serviceDefinition, true); + } + + ShowRequestResult($"Updated hash code property on Service definitions", string.Join("\n", getServiceDefinitionsSection.SelectedServiceDefinitions.Select(sd => sd.Name)), string.Join("\n", getServiceDefinitionsSection.SelectedServiceDefinitions.Select(sd => sd.GetPropertiesAsDictionary().Dictionary[ServiceDefinitionPropertyNames.DiagramHashCode]))); + GenerateUi(); + } + + private void GetServiceDefinitionsSection_RegenerateUi(object sender, EventArgs e) + { + getServiceDefinitionsSection.GenerateUi(); + GenerateUi(); + } + + private void ShowJsonButton_Pressed(object sender, EventArgs e) + { + ShowRequestResult("Serialized Service Definitions", string.Join("\n", getServiceDefinitionsSection.SelectedServiceDefinitions.Select(r => JsonConvert.SerializeObject(r)))); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddSection(getServiceDefinitionsSection, new SectionLayout(++row, 0)); + row += getServiceDefinitionsSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(showJsonButton, ++row, 0); + AddWidget(setDiagramHashCodePropertyButton, ++row, 0); + AddWidget(getDiagramHashCodeButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/GetServiceDefinitionsSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/GetServiceDefinitionsSection.cs new file mode 100644 index 0000000..79868ad --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/GetServiceDefinitionsSection.cs @@ -0,0 +1,121 @@ +namespace Debug_2.Debug.ServiceDefinitions +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Library.UI.Filters; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ServiceManager.Objects; + + public class GetServiceDefinitionsSection : Section + { + private readonly Label header = new Label("Get Service Definitions with Filters") { Style = TextStyle.Heading }; + + private readonly StringFilterSection nameFilterSection = new StringFilterSection("Name", name => ServiceDefinitionExposers.Name.Equal((string)name)); + + private readonly StringFilterSection idFilterSection = new GuidFilterSection("ID", id => ServiceDefinitionExposers.ID.Equal((Guid)id)); + + private readonly List> nodeFunctionIdFilterSections = new List>(); + + private readonly Button addNodeFunctionIdFilterButton = new Button("Add Node Function ID Filter"); + + private readonly List> propertyFilterSections = new List>(); + + private readonly Button addPropertyFilterButton = new Button("Add Property Filter"); + + private readonly Button getSelectedServiceDefinitionsButton = new Button("Get Selected Service Definitions") { Style = ButtonStyle.CallToAction }; + private readonly CollapseButton showSelectedServiceDefinitionsButton; + private readonly TextBox selectedServiceDefinitionsTextBox = new TextBox() { IsMultiline = true, MinWidth = 500 }; + private readonly Helpers helpers; + + public GetServiceDefinitionsSection(Helpers helpers) + { + this.helpers = helpers; + + addNodeFunctionIdFilterButton.Pressed += AddNodeFunctionIdFilterButton_Pressed; + addPropertyFilterButton.Pressed += AddPropertyFilterButton_Pressed; + + showSelectedServiceDefinitionsButton = new CollapseButton(selectedServiceDefinitionsTextBox.Yield(), true) { CollapseText = "Hide Selected Service Definitions", ExpandText = "Show Selected Service Definitions" }; + + getSelectedServiceDefinitionsButton.Pressed += (o, e) => SelectedServiceDefinitions = GetSelectedServiceDefinitions(); + + GenerateUi(); + } + + public IEnumerable SelectedServiceDefinitions { get; private set; } = new List(); + + public event EventHandler RegenerateUi; + + private void AddNodeFunctionIdFilterButton_Pressed(object sender, EventArgs e) + { + var nodeFunctionIdFilterSection = new GuidFilterSection("Uses Function ID", guid => ServiceDefinitionExposers.NodeFunctionIDs.Contains((Guid)guid)); + + nodeFunctionIdFilterSections.Add(nodeFunctionIdFilterSection); + + RegenerateUi?.Invoke(this, EventArgs.Empty); + } + + private void AddPropertyFilterButton_Pressed(object sender, EventArgs e) + { + var propertyFilterSection = new StringPropertyFilterSection("Property", (propertyName, propertyValue) => ServiceDefinitionExposers.Properties.DictStringField((string)propertyName).Equal((string)propertyValue)); + + propertyFilterSections.Add(propertyFilterSection); + + RegenerateUi?.Invoke(this, EventArgs.Empty); + } + + private IEnumerable GetSelectedServiceDefinitions() + { + selectedServiceDefinitionsTextBox.Text = String.Empty; + if (!this.ActiveFiltersAreValid()) return new List(); + + if (!this.TryGetCombinedFilterElement(out var combinedFilter)) + { + combinedFilter = new ANDFilterElement(ServiceDefinitionExposers.Name.NotEqual(string.Empty)); + } + + var selectedServiceDefinitions = DataMinerInterface.ServiceManager.GetServiceDefinitions(helpers, combinedFilter); + + selectedServiceDefinitionsTextBox.Text = String.Join("\n", selectedServiceDefinitions.Select(r => r.Name).OrderBy(name => name)); + + return selectedServiceDefinitions; + } + + public void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(header, ++row, 0, 1, 5); + + AddSection(nameFilterSection, new SectionLayout(++row, 0)); + + AddSection(idFilterSection, new SectionLayout(++row, 0)); + + foreach (var nodeFunctionIdFilterSection in nodeFunctionIdFilterSections) + { + AddSection(nodeFunctionIdFilterSection, new SectionLayout(++row, 0)); + } + + AddWidget(addNodeFunctionIdFilterButton, ++row, 0); + + foreach (var propertyFilterSection in propertyFilterSections) + { + AddSection(propertyFilterSection, new SectionLayout(++row, 0)); + } + + AddWidget(addPropertyFilterButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(getSelectedServiceDefinitionsButton, ++row, 0); + AddWidget(showSelectedServiceDefinitionsButton, row, 1); + AddWidget(selectedServiceDefinitionsTextBox, ++row, 1); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/UpdateServiceDefinitionsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/UpdateServiceDefinitionsDialog.cs new file mode 100644 index 0000000..b6ccba0 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/ServiceDefinitions/UpdateServiceDefinitionsDialog.cs @@ -0,0 +1,69 @@ +namespace Debug_2.Debug.ServiceDefinitions +{ + using System; + using Newtonsoft.Json; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.ServiceManager.Objects; + + public class UpdateServiceDefinitionsDialog : DebugDialog + { + private readonly Label updateServiceDefinitionLabel = new Label("Add or Update Service Definition") { Style = TextStyle.Heading }; + + private readonly Label serviceDefinitionLabel = new Label("Service Definition"); + private readonly TextBox serviceDefinitionTextBox = new TextBox { IsMultiline = true }; + + private readonly Button addOrUpdateButton = new Button("Add or Update"); + + public UpdateServiceDefinitionsDialog(Helpers helpers) : base(helpers) + { + Title = "Add or Update Service Definition"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + addOrUpdateButton.Pressed += AddOrUpdateButton_Pressed; + } + + private void AddOrUpdateButton_Pressed(object sender, EventArgs e) + { + var serviceDefinition = JsonConvert.DeserializeObject(serviceDefinitionTextBox.Text); + + bool successful; + if (serviceDefinition is null) + { + successful = false; + } + else + { + DataMinerInterface.ServiceManager.AddOrUpdateServiceDefinition(helpers, serviceDefinition, true); + successful = true; + } + + ShowRequestResult($"Update {(successful ? "succeeded" : "failed")}", $"Update {(successful ? "succeeded" : "failed")}"); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 8); + + AddWidget(updateServiceDefinitionLabel, ++row, 0, 1, 8); + + AddWidget(serviceDefinitionLabel, ++row, 0); + AddWidget(serviceDefinitionTextBox, row, 1, 1, 8); + + AddWidget(addOrUpdateButton, ++row, 0); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Services/ProfileLoadLoggingDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Services/ProfileLoadLoggingDialog.cs new file mode 100644 index 0000000..f917008 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Services/ProfileLoadLoggingDialog.cs @@ -0,0 +1,75 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Debug.Services +{ + using System; + using System.IO; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class ProfileLoadLoggingDialog : DebugDialog + { + private readonly Label header = new Label("Profile Load Logging") { Style = TextStyle.Heading }; + private readonly Label serviceIdLabel = new Label("Service ID"); + private readonly TextBox serviceIdTextBox = new TextBox(); + private readonly Button enterCurrentIdButton = new Button("Enter Current ID"); + private readonly Button getProfileLoadLoggingButton = new Button("Get Profile Load Logging") { Style = ButtonStyle.CallToAction }; + + public ProfileLoadLoggingDialog(Helpers helpers) : base(helpers) + { + Title = "Profile Load Logging"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + enterCurrentIdButton.Pressed += (sender, args) => serviceIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + + getProfileLoadLoggingButton.Pressed += GetProfileLoadLoggingButton_Pressed; + } + + private void GetProfileLoadLoggingButton_Pressed(object sender, EventArgs e) + { + if (!Guid.TryParse(serviceIdTextBox.Text, out Guid serviceId)) + { + ShowRequestResult($"Service ID {serviceIdTextBox.Text} is not a Guid", string.Empty); + GenerateUi(); + return; + } + + string path = $@"C:\Skyline_Data\OrderLogging\{serviceId}.txt"; + + if (!File.Exists(path)) + { + ShowRequestResult($"File {path} does not exist", string.Empty); + GenerateUi(); + return; + } + + var text = File.ReadAllText(path); + + ShowRequestResult($"Profile Load Logging for {serviceId}", text); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0); + + AddWidget(header, ++row, 0, 1, 5); + AddWidget(serviceIdLabel, ++row, 0); + AddWidget(serviceIdTextBox, row, 1); + AddWidget(enterCurrentIdButton, row, 2); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(getProfileLoadLoggingButton, ++row, 0); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Templates/DeleteTemplatesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Templates/DeleteTemplatesDialog.cs new file mode 100644 index 0000000..217afcc --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Templates/DeleteTemplatesDialog.cs @@ -0,0 +1,75 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Templates +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.YleWidgets; + using Debug_2.Debug; + + public class DeleteTemplatesDialog : DebugDialog + { + private readonly Label addOrUpdateServiceConfigurationsLabel = new Label("Order and Event Templates") { Style = TextStyle.Heading }; + + private readonly Label idLabel = new Label("ID"); + private readonly YleTextBox idTextBox = new YleTextBox(string.Empty) { ValidationPredicate = value => Guid.TryParse(value, out var result), ValidationText = "Invalid GUID" }; + private readonly Button enterCurrentIdButton = new Button("Enter Current ID") { Width = 200 }; + + private readonly Button deleteOrderTemplateButton = new Button("Delete Order Template"); + + public DeleteTemplatesDialog(Helpers helpers) : base(helpers) + { + Title = "Templates"; + + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + enterCurrentIdButton.Pressed += (sender, args) => idTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + + deleteOrderTemplateButton.Pressed += DeleteTemplateButton_Pressed; + } + + private void DeleteTemplateButton_Pressed(object sender, EventArgs e) + { + if (!idTextBox.IsValid) return; + + if (helpers.ContractManager.TryDeleteOrderTemplate(Guid.Parse(idTextBox.Text))) + { + ShowRequestResult($"Successfully Removed Order Template {idTextBox.Text}", $"Removed Order Template {idTextBox.Text}"); + } + else + { + ShowRequestResult($"Failed to remove Order Template {idTextBox.Text}", $"Failed to remove Order Template {idTextBox.Text}"); + } + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(addOrUpdateServiceConfigurationsLabel, ++row, 0, 1, 5); + + AddWidget(idLabel, ++row, 0, 1, 2); + AddWidget(idTextBox, row, 2, 1, 2); + AddWidget(enterCurrentIdButton, ++row, 2, 1, 2); + + AddWidget(deleteOrderTemplateButton, ++row, 0, 1, 5); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Templates/EditEventTemplatesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Templates/EditEventTemplatesDialog.cs new file mode 100644 index 0000000..057f550 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Templates/EditEventTemplatesDialog.cs @@ -0,0 +1,131 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Templates +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class EditEventTemplatesDialog : Dialog + { + private readonly Helpers helpers; + private readonly List sections = new List(); + + public EditEventTemplatesDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Edit Event Templates"; + + this.helpers = helpers; + + var eventTemplateNames = helpers.ContractManager.GetAllEventTemplates().OrderBy(x => x); + foreach (var eventTemplateName in eventTemplateNames) + { + sections.Add(new EventTemplateSection(helpers, eventTemplateName)); + } + + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private void GenerateUi() + { + Clear(); + + int row = -1; + AddWidget(BackButton, ++row, 0, 1, 2); + + foreach (var eventTemplateSection in sections) + { + AddSection(eventTemplateSection, ++row, 0); + row += eventTemplateSection.RowCount; + } + } + + private sealed class EventTemplateSection : Section + { + private readonly Helpers helpers; + private readonly string name; + + private readonly TextBox textBox = new TextBox(String.Empty) { IsMultiline = true, Height = 800, Width = 800 }; + private readonly Label templateNameLabel = new Label { Style = TextStyle.Bold }; + private readonly Label statusLabel = new Label(String.Empty); + private readonly Button updateButton = new Button("Update Template") { Width = 150 }; + private readonly CollapseButton collapseButton = new CollapseButton { CollapseText = "-", ExpandText = "+", Width = 44 }; + + public EventTemplateSection(Helpers helpers, string name) + { + this.helpers = helpers; + this.name = name; + + templateNameLabel.Text = name; + + collapseButton.LinkedWidgets.Add(textBox); + collapseButton.LinkedWidgets.Add(updateButton); + collapseButton.LinkedWidgets.Add(statusLabel); + collapseButton.IsCollapsed = true; + + collapseButton.Pressed += (s, e) => RetrieveTemplate(); + updateButton.Pressed += (s, e) => UpdateTemplate(); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + AddWidget(collapseButton, 0, 0); + AddWidget(templateNameLabel, 0, 1); + + AddWidget(textBox, 1, 1); + + AddWidget(updateButton, 2, 1); + + AddWidget(statusLabel, 3, 1); + } + + private void RetrieveTemplate() + { + if (!String.IsNullOrEmpty(textBox.Text)) return; + + if (!helpers.ContractManager.TryGetEventTemplate(name, out EventTemplate template)) + { + statusLabel.Text = $"Unable to retrieve Event Template with name {name}"; + textBox.IsEnabled = false; + updateButton.IsEnabled = false; + return; + } + + textBox.Text = JsonConvert.SerializeObject(template, Formatting.Indented); + } + + private void UpdateTemplate() + { + EventTemplate template; + try + { + template = JsonConvert.DeserializeObject(textBox.Text); + } + catch (Exception) + { + statusLabel.Text = $"Unable to serialize Event Template, template was not updated"; + return; + } + + if (!helpers.ContractManager.TryEditEventTemplate(template)) + { + statusLabel.Text = $"Unable to edit Event Template in Contract Manager"; + return; + } + + statusLabel.Text = $"Event Template was updated"; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Templates/EditOrderTemplatesDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Templates/EditOrderTemplatesDialog.cs new file mode 100644 index 0000000..99f8f54 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Templates/EditOrderTemplatesDialog.cs @@ -0,0 +1,131 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Templates +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class EditOrderTemplatesDialog : Dialog + { + private readonly Helpers helpers; + private readonly List sections = new List(); + + public EditOrderTemplatesDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Edit Order Templates"; + + this.helpers = helpers; + + var orderTemplateNames = helpers.ContractManager.GetAllOrderTemplateNamesAndIds().Select(x => x.Key).OrderBy(x => x); + foreach (var orderTemplateName in orderTemplateNames) + { + sections.Add(new OrderTemplateSection(helpers, orderTemplateName)); + } + + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private void GenerateUi() + { + Clear(); + + int row = -1; + AddWidget(BackButton, ++row, 0, 1, 2); + + foreach (var orderTemplateSection in sections) + { + AddSection(orderTemplateSection, ++row, 0); + row += orderTemplateSection.RowCount; + } + } + + private sealed class OrderTemplateSection : Section + { + private readonly Helpers helpers; + private readonly string name; + + private readonly TextBox textBox = new TextBox(String.Empty) { IsMultiline = true, Height = 800, Width = 800 }; + private readonly Label templateNameLabel = new Label { Style = TextStyle.Bold }; + private readonly Label statusLabel = new Label(String.Empty); + private readonly Button updateButton = new Button("Update Template") { Width = 150 }; + private readonly CollapseButton collapseButton = new CollapseButton { CollapseText = "-", ExpandText = "+", Width = 44 }; + + public OrderTemplateSection(Helpers helpers, string name) + { + this.helpers = helpers; + this.name = name; + + templateNameLabel.Text = name; + + collapseButton.LinkedWidgets.Add(textBox); + collapseButton.LinkedWidgets.Add(updateButton); + collapseButton.LinkedWidgets.Add(statusLabel); + collapseButton.IsCollapsed = true; + + collapseButton.Pressed += (s, e) => RetrieveTemplate(); + updateButton.Pressed += (s, e) => UpdateTemplate(); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + AddWidget(collapseButton, 0, 0); + AddWidget(templateNameLabel, 0, 1); + + AddWidget(textBox, 1, 1); + + AddWidget(updateButton, 2, 1); + + AddWidget(statusLabel, 3, 1); + } + + private void RetrieveTemplate() + { + if (!String.IsNullOrEmpty(textBox.Text)) return; + + if (!helpers.ContractManager.TryGetOrderTemplate(name, out OrderTemplate template)) + { + statusLabel.Text = $"Unable to retrieve Order Template with name {name}"; + textBox.IsEnabled = false; + updateButton.IsEnabled = false; + return; + } + + textBox.Text = JsonConvert.SerializeObject(template, Formatting.Indented); + } + + private void UpdateTemplate() + { + OrderTemplate template; + try + { + template = JsonConvert.DeserializeObject(textBox.Text); + } + catch (Exception) + { + statusLabel.Text = $"Unable to serialize Order Template, template was not updated"; + return; + } + + if (!helpers.ContractManager.TryEditOrderTemplate(template, new string[0])) + { + statusLabel.Text = $"Unable to edit Order Template in Contract Manager"; + return; + } + + statusLabel.Text = $"Order Template was updated"; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Tickets/FindTicketsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Tickets/FindTicketsDialog.cs new file mode 100644 index 0000000..e7f1f02 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Tickets/FindTicketsDialog.cs @@ -0,0 +1,104 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Tickets +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Debug_2.Debug.Reservations; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Helpers = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers; + + public class FindTicketsDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label findTicketsLabel = new Label("Find Ticket") { Style = TextStyle.Heading }; + private readonly Label ticketNameLabel = new Label("Name"); + private readonly Label ticketIdLabel = new Label("GUID"); + private readonly Button enterCurrentIdButton = new Button("Enter Current ID") { Width = 200 }; + private readonly TextBox ticketNameTextBox = new TextBox(); + private readonly TextBox ticketIdTextBox = new TextBox(); + private readonly Button findByTicketNameButton = new Button("Find By Name") { Width = 150 }; + private readonly Button findByTicketIdButton = new Button("Find By ID") { Width = 150 }; + + private readonly List responseSections = new List(); + + public FindTicketsDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Find Tickets"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + private void Initialize() + { + findByTicketIdButton.Pressed += FindByTicketIdButton_Pressed; + findByTicketNameButton.Pressed += FindByTicketNameButton_Pressed; + enterCurrentIdButton.Pressed += (sender, args) => ticketIdTextBox.Text = helpers.Engine.GetScriptParam(1)?.Value; + } + + private void FindByTicketNameButton_Pressed(object sender, EventArgs e) + { + var ticket = helpers.UserTaskManager.TicketingManager.GetTicketWithFieldValue("Name", ticketNameTextBox.Text); + + ShowRequestResult($"Ticket {ticket.ID}", ticket.ToJson()); + } + + private void FindByTicketIdButton_Pressed(object sender, EventArgs e) + { + var splitId = ticketIdTextBox.Text.Split('/'); + + var ticket = helpers.UserTaskManager.TicketingManager.GetTicket(Convert.ToInt32(splitId[0]), Convert.ToInt32(splitId[1])); + + ShowRequestResult($"Ticket {ticket.ID}", ticket.ToJson()); + } + + private void ShowRequestResult(string header, params string[] results) + { + responseSections.Add(new RequestResultSection(header, results)); + + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(findTicketsLabel, ++row, 0, 1, 5); + + AddWidget(ticketNameLabel, ++row, 0, 1, 2); + AddWidget(ticketNameTextBox, row, 2); + AddWidget(findByTicketNameButton, row, 3); + + AddWidget(ticketIdLabel, ++row, 0, 1, 2); + AddWidget(ticketIdTextBox, row, 2); + AddWidget(findByTicketIdButton, row, 3); + AddWidget(enterCurrentIdButton, ++row, 2); + + AddWidget(new WhiteSpace(), ++row, 1); + + row++; + foreach (var responseSection in responseSections) + { + responseSection.Collapse(); + AddSection(responseSection, row, 0); + row += responseSection.RowCount; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Tickets/FindTicketsWithFiltersDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Tickets/FindTicketsWithFiltersDialog.cs new file mode 100644 index 0000000..94226ff --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Tickets/FindTicketsWithFiltersDialog.cs @@ -0,0 +1,97 @@ +namespace Debug_2.Debug.Tickets +{ + using System; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Ticketing; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class FindTicketsWithFiltersDialog : DebugDialog + { + private TicketingGatewayHelper ticketingHelper; + + private readonly GetTicketSection getTicketsSection; + + private readonly Button showJsonButton = new Button("Show Tickets JSON"); + private readonly Button deleteButton = new Button("Delete Tickets"); + private readonly CheckBox confirmDeleteChecbox = new CheckBox("Confirm"); + + public FindTicketsWithFiltersDialog(Helpers helpers) : base(helpers) + { + getTicketsSection = new GetTicketSection(helpers); + + Title = "Find Tickets with Filters"; + Initialize(); + GenerateUi(); + } + + private void Initialize() + { + ticketingHelper = new TicketingGatewayHelper { HandleEventsAsync = false }; + ticketingHelper.RequestResponseEvent += (sender, args) => args.responseMessage = Engine.SendSLNetSingleResponseMessage(args.requestMessage); + + getTicketsSection.RegenerateUiRequired += GetTicketsSection_RegenerateUi; + getTicketsSection.UiEnabledStateChangeRequired += Section_UiEnabledStateChangeRequired; + + showJsonButton.Pressed += ShowJsonButton_Pressed; + + deleteButton.Pressed += DeleteButton_Pressed; + } + + private void DeleteButton_Pressed(object sender, EventArgs e) + { + if (!confirmDeleteChecbox.IsChecked) return; + + if (ticketingHelper.RemoveTickets(out string error, getTicketsSection.SelectedTickets.ToArray())) + { + ShowRequestResult($"Removed tickets", string.Join(", ", getTicketsSection.SelectedTickets.Select(t => t.ID))); + } + else + { + ShowRequestResult($"Error while removing tickets", error); + } + + RegenerateUi(); + } + + private void GetTicketsSection_RegenerateUi(object sender, EventArgs e) + { + RegenerateUi(); + } + + private void ShowJsonButton_Pressed(object sender, EventArgs e) + { + ShowRequestResult("Serialized Tickets", string.Join("\n", getTicketsSection.SelectedTickets.Select(r => JsonConvert.SerializeObject(r)))); + RegenerateUi(); + } + + private void RegenerateUi() + { + getTicketsSection.RegenerateUi(); + GenerateUi(); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddSection(getTicketsSection, new SectionLayout(++row, 0)); + row += getTicketsSection.RowCount; + + AddWidget(new WhiteSpace(), ++row, 0); + AddWidget(showJsonButton, ++row, 0); + AddWidget(deleteButton, ++row, 0); + AddWidget(confirmDeleteChecbox, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddResponseSections(row); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Tickets/GetTicketSection.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Tickets/GetTicketSection.cs new file mode 100644 index 0000000..59c47b1 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/Tickets/GetTicketSection.cs @@ -0,0 +1,232 @@ +namespace Debug_2.Debug.Tickets +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Library.UI.Filters; + using Skyline.DataMiner.DeveloperCommunityLibrary.UI.YleWidgets; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.Ticketing; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class GetTicketSection : YleSection + { + private readonly Label header = new Label("Get Tickets with filters") { Style = TextStyle.Title }; + + private readonly Label ticketDomainIds = new Label(); + + private readonly FilterSection ticketIdFilterSection = new StringFilterSection("Ticket ID", x => TicketingExposers.FullID.Equal((String)x)); + + private readonly FilterSection ticketCreationDateFromFilterSection = new DateTimeFilterSection("Creation Date From", x => TicketingExposers.CreationDate.GreaterThanOrEqual((DateTime)x)); + + private readonly FilterSection ticketCreationDateUntilFilterSection = new DateTimeFilterSection("Creation Date Until", x => TicketingExposers.CreationDate.LessThanOrEqual((DateTime)x)); + + private readonly FilterSection ticketDomainFilterSection = new GuidFilterSection("Ticket Domain ID", x => TicketingExposers.ResolverID.Equal((Guid)x)); + + private readonly List> propertyFilterSections = new List>(); + + private readonly RadioButtonList typeOfPropertyValueFilterToAdd = new RadioButtonList(new[] {"String", "Integer", "Enum"}); + private readonly Button addPropertyValueFilterButton = new Button("Add Property Value Filter"); + + private readonly Button addPropertyExistenceFilterButton = new Button("Add Property Existence Filter"); + + private readonly Button getSelectedTicketsButton = new Button("Get Selected Tickets") { Style = ButtonStyle.CallToAction }; + private readonly CollapseButton showSelectedTicketsButton; + private readonly TextBox selectedTicketsTextBox = new TextBox { IsMultiline = true, MinWidth = 500 }; + + private readonly TicketingGatewayHelper ticketingHelper; + + public GetTicketSection(Helpers helpers) : base(helpers) + { + ticketDomainIds.Text = $"Ticket Domain IDs:\nNon-Live Orders: {helpers.NonLiveOrderManager.TicketDomainId}\nUser Tasks: {helpers.UserTaskManager.TicketingManager.TicketFieldResolver.ID}\nNotes: {helpers.NoteManager.TicketDomainId}"; + + ticketingHelper = new TicketingGatewayHelper { HandleEventsAsync = false }; + ticketingHelper.RequestResponseEvent += (sender, args) => args.responseMessage = Skyline.DataMiner.Automation.Engine.SLNet.SendSingleResponseMessage(args.requestMessage); + + addPropertyExistenceFilterButton.Pressed += AddPropertyExistenceFilterButton_Pressed; + + addPropertyValueFilterButton.Pressed += AddPropertyValueFilterButton_Pressed; + + showSelectedTicketsButton = new CollapseButton(selectedTicketsTextBox.Yield(), true) { CollapseText = "Hide Selected Tickets", ExpandText = "Show Selected Tickets" }; + + getSelectedTicketsButton.Pressed += (s,e) => SelectedTickets = GetSelectedTickets(); + + GenerateUi(); + } + + public event EventHandler RegenerateUiRequired; + + public IEnumerable SelectedTickets { get; private set; } = new List(); + + public void AddStringPropertyValueFilter(string propertyName, string propertyValue = null, bool setAsDefault = false) + { + var propertyFilterSection = new StringPropertyFilterSection("String Property", (pName, pValue) => TicketingExposers.CustomTicketFields.DictStringField((string)pName).Equal((string)pValue)); + + if (setAsDefault) + { + propertyFilterSection.SetDefault(propertyName, propertyValue); + } + else + { + propertyFilterSection.Value = propertyName; + propertyFilterSection.SecondValue= propertyValue ?? string.Empty; + } + + propertyFilterSections.Add(propertyFilterSection); + + RegenerateUiRequired?.Invoke(this, EventArgs.Empty); + } + + public void AddEnumPropertyValueFilter(string propertyName, string firstPropertyValue = null, int? secondPropertyValue = null, bool setAsDefault = false) + { + var propertyFilterSection = new TicketEnumFilterSection("Enum Property", (pName, pValue1, pValue2) => TicketingExposers.CustomTicketFields.DictField((string)pName).Equal($"{pValue1}/{pValue2}")); + + if (setAsDefault) + { + propertyFilterSection.SetDefault(propertyName, firstPropertyValue, secondPropertyValue); + } + else + { + propertyFilterSection.Value = propertyName; + propertyFilterSection.SecondValue = firstPropertyValue ?? string.Empty; + propertyFilterSection.ThirdValue = secondPropertyValue.HasValue ? secondPropertyValue.Value : 0; + } + + propertyFilterSections.Add(propertyFilterSection); + + RegenerateUiRequired?.Invoke(this, EventArgs.Empty); + } + + public void AddIntegerPropertyValueFilter(string propertyName, int? propertyValue = null, bool setAsDefault = false) + { + var propertyFilterSection = new IntegerPropertyFilterSection("Integer Property", (pName, pValue) => TicketingExposers.CustomTicketFields.DictField((string)pName).Equal(pValue)); + + if (setAsDefault) + { + propertyFilterSection.SetDefault(propertyName, propertyValue); + } + else + { + propertyFilterSection.Value = propertyName; + propertyFilterSection.SecondValue = propertyValue.HasValue ? propertyValue.Value : 0; + } + + propertyFilterSections.Add(propertyFilterSection); + + RegenerateUiRequired?.Invoke(this, EventArgs.Empty); + } + + public void AddPropertyExistenceFilter(string propertyName, bool setAsDefault = false) + { + var propertyExistenceFilterSection = new StringFilterSection("Property Exists", (pName) => TicketingExposers.CustomTicketFields.DictStringField((string)pName).NotEqual(string.Empty)); + + if (setAsDefault) + { + propertyExistenceFilterSection.SetDefault(propertyName); + } + else + { + propertyExistenceFilterSection.Value = propertyName; + } + + propertyFilterSections.Add(propertyExistenceFilterSection); + + RegenerateUiRequired?.Invoke(this, EventArgs.Empty); + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(header, ++row, 0, 1, 5); + + AddWidget(ticketDomainIds, ++row, 0); + + AddSection(ticketIdFilterSection, new SectionLayout(++row, 0)); + + AddSection(ticketCreationDateFromFilterSection, new SectionLayout(++row, 0)); + + AddSection(ticketCreationDateUntilFilterSection, new SectionLayout(++row, 0)); + + AddSection(ticketDomainFilterSection, new SectionLayout(++row, 0)); + + foreach (var propertyFilterSection in propertyFilterSections) + { + AddSection(propertyFilterSection, new SectionLayout(++row, 0)); + row += propertyFilterSection.RowCount; + } + + AddWidget(addPropertyExistenceFilterButton, ++row, 0); + AddWidget(addPropertyValueFilterButton, ++row, 0, verticalAlignment: VerticalAlignment.Top); + AddWidget(typeOfPropertyValueFilterToAdd, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(getSelectedTicketsButton, ++row, 0); + AddWidget(showSelectedTicketsButton, row, 1); + AddWidget(selectedTicketsTextBox, ++row, 1); + } + + private void AddPropertyValueFilterButton_Pressed(object sender, EventArgs e) + { + switch (typeOfPropertyValueFilterToAdd.Selected) + { + case nameof(String): + AddStringPropertyValueFilter(string.Empty); + break; + + case "Integer": + AddIntegerPropertyValueFilter(string.Empty); + break; + case "Enum": + AddEnumPropertyValueFilter(string.Empty); + break; + + default: + break; + } + } + + private void AddPropertyExistenceFilterButton_Pressed(object sender, EventArgs e) + { + AddPropertyExistenceFilter(string.Empty); + } + + private IEnumerable GetSelectedTickets() + { + using (UiDisabler.StartNew(this)) + { + selectedTicketsTextBox.Text = String.Empty; + if (!this.ActiveFiltersAreValid()) return new List(); + + var selectedTickets = new HashSet(ticketingHelper.GetTickets(null, this.GetCombinedFilterElement(), false).ToList()); + + selectedTicketsTextBox.Text = String.Join("\n", selectedTickets.Select(r => r.ID).OrderBy(id => id)); + + return selectedTickets; + } + } + + public override void RegenerateUi() + { + GenerateUi(); + } + + protected override void HandleVisibilityAndEnabledUpdate() + { + ticketIdFilterSection.IsEnabled = IsEnabled; + + ticketCreationDateFromFilterSection.IsEnabled = IsEnabled; + + ticketCreationDateUntilFilterSection.IsEnabled = IsEnabled; + + ticketDomainFilterSection.IsEnabled = IsEnabled; + + propertyFilterSections.ForEach(f => f.IsEnabled = IsEnabled); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/VIZREM/VizremDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/VIZREM/VizremDialog.cs new file mode 100644 index 0000000..6fdffb2 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug/VIZREM/VizremDialog.cs @@ -0,0 +1,186 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Debug.VIZREM +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service; + using Order = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports; + using Newtonsoft.Json; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderUpdates; + + public class VizremDialog : Dialog + { + private readonly Helpers helpers; + + private readonly Label triggerVizremBookLabel = new Label("Trigger VIZREM Book") { Style = TextStyle.Heading }; + + public VizremDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Vizrem"; + + this.helpers = helpers; + + Initialize(); + GenerateUi(); + } + + public Button BackButton { get; } = new Button("Back...") { Width = 150 }; + + public Button TriggerBookFlowButton { get; } = new Button("Trigger Book...") { Width = 150 }; + + private TextBox DataTextBox { get; set; } + + public void CreateVizremOrder(InteractiveController app) + { + //var createdOrder = CreateNewOrder(); + var adaptedOrder = GetOrderAndChangeResources(); + + AddOrUpdateOrder(adaptedOrder, app); + } + + private void Initialize() + { + DataTextBox = new TextBox { PlaceHolder = "Data", Width = 400 }; + } + + private void GenerateUi() + { + Clear(); + + int row = -1; + + AddWidget(BackButton, ++row, 0, 1, 3); + + AddWidget(triggerVizremBookLabel, ++row, 0, 1, 5); + + AddWidget(DataTextBox, ++row, 2); + AddWidget(TriggerBookFlowButton, ++row, 2); + } + + private Order CreateNewOrder() + { + DateTime start = DateTime.Now.AddDays(1).RoundToMinutes(); + DateTime end = start.AddMinutes(60).RoundToMinutes(); + + var allServiceDefinitions = helpers.ServiceDefinitionManager.ServiceDefinitionsForLiveOrderForm; + + var studioService = new DisplayedService(helpers, allServiceDefinitions.VizremStudios.First(x => x.Description.Contains("NDI Router"))); + studioService.AcceptChanges(); + + var vizremService = new DisplayedService(helpers, allServiceDefinitions.VizremFarms.First()); + vizremService.AcceptChanges(); + + var studioDestinationService = new DisplayedService(helpers, allServiceDefinitions.VizremStudios.First(x => x.Description.Contains("NDI Router"))); + studioDestinationService.AcceptChanges(); + + studioService.Start = start; + studioService.End = end; + var studioFunction = studioService.Functions[0]; + var studioResource = helpers.ResourceManager.GetResourcesByName("ST26 NDI1 to NDI1").First() as FunctionResource; + studioFunction.Resource = studioResource; + + vizremService.Start = start; + vizremService.End = end; + var vizremFunction = vizremService.Functions[0]; + vizremFunction.Resource = helpers.ResourceManager.GetResourcesByName("VIZREM 06").First() as FunctionResource; + + studioDestinationService.Start = start; + studioDestinationService.End = end; + var studioDestinationFunction = studioDestinationService.Functions[0]; + studioDestinationFunction.Resource = helpers.ResourceManager.GetResourcesByName("ST26 NDI5 to NDI5").First() as FunctionResource; + + + Order newOrder = new Order + { + ManualName = $"Vizrem Order {Guid.NewGuid()}", + Start = start, + End = end, + Subtype = OrderSubType.Vizrem, + Event = null, + IsInternal = false, + Contract = "YLE Base", + Company = "YLE", + CreatedByUserName = helpers.Engine.UserLoginName, + CreatedByEmail = String.Empty, + CreatedByPhone = String.Empty, + LastUpdatedBy = helpers.Engine.UserLoginName, + LastUpdatedByEmail = String.Empty, + LastUpdatedByPhone = String.Empty, + BillingInfo = new BillingInfo + { + BillableCompany = "YLE", + CustomerCompany = String.Empty + }, + Status = YLE.Order.Status.Confirmed, + }; + + newOrder.SetUserGroupIds(new HashSet() { 0 }); + + newOrder.SetSecurityViewIds(new HashSet() { 10102 }); + + newOrder.AcceptChanges(); + newOrder.SourceService = studioService; + newOrder.SourceService.Children.Add(vizremService); + vizremService.Children.Add(studioDestinationService); + + DataTextBox.Text = JsonConvert.SerializeObject(newOrder.AllServices); + + return newOrder; + } + + private Order GetOrderAndChangeResources() + { + var order = helpers.OrderManager.GetOrder(new Guid("359555fe-6a44-499b-a4d0-4e075d76f6b8")); + var orderServices = order.AllServices; + + var studioService = order.Sources[0]; + var studioFunction = studioService.Functions[0]; + studioFunction.Resource = helpers.ResourceManager.GetResourcesByName("T2.Studio Mediapolis").First() as FunctionResource; + + var vizremFarm = orderServices.First(s => s.Definition.VirtualPlatform == VirtualPlatform.VizremFarm); + var vizremFunction = vizremFarm.Functions[0]; + vizremFunction.Resource = helpers.ResourceManager.GetResourcesByName("VIZREM 05").First() as FunctionResource; + + var studioDestination = orderServices.Last(s => s.Definition.VirtualPlatform == VirtualPlatform.VizremStudio); + var studioDestinationFunction = studioDestination.Functions[0]; + studioDestinationFunction.Resource = helpers.ResourceManager.GetResourcesByName("T2.Studio Mediapolis").First() as FunctionResource; + + return order; + } + + private void AddOrUpdateOrder(Order order, InteractiveController app) + { + var reportDialog = new AddOrUpdateReportDialog(helpers, false); + + reportDialog.OkButton.Pressed += (o, e) => + { + app.ShowDialog(this); + }; + + app.ShowDialog(reportDialog); + + var tasks = order.AddOrUpdate(helpers, false).Tasks; + + if (tasks.Any()) + { + reportDialog.Finish(tasks); + + // release the locks if all tasks were successful + //if (tasks.All(t => t.Status == TaskStatus.Ok)) helpers.LockManager.ReleaseLocks(); + + app.ShowDialog(reportDialog); + } + + helpers.Log(nameof(VizremDialog), nameof(AddOrUpdateOrder), $"Vizrem Order Updated"); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug_2.csproj new file mode 100644 index 0000000..f15d886 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Debug_2.csproj @@ -0,0 +1,177 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {92B8FAFF-3EBC-4C12-91AB-71A8B6E0EC1C} + Library + Properties + Debug_2 + Debug_2 + v4.7.2 + 512 + + + + True + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\Debug_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\Debug_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0.0.4 + + + 10.3.5 + + + 7.0.1 + + + 1.0.1.12 + + + + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/GlobalSuppressions.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/GlobalSuppressions.cs new file mode 100644 index 0000000..b48557d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/GlobalSuppressions.cs @@ -0,0 +1,15 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:Debug_2.Debug.ServiceDefinitions.FixMissingServiceDefinitionsDialog.MisingServiceDefinitionSection.GetEdges(System.Collections.Generic.IEnumerable{Skyline.DataMiner.Net.ServiceManager.Objects.Node})~System.Collections.Generic.IEnumerable{Skyline.DataMiner.Net.ServiceManager.Objects.Edge}")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.SendPbsIntegrationNotificationDialog.NotificationSection_LoadButton_Pressed(System.Object,System.EventArgs)")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Integrations.AnalyzePlasmaRecordingsDialog.GetPgmRecording(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order)~Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Jobs.FindReservationsWithoutJobDialog.FixButton_Pressed(System.Object,System.EventArgs)")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations.FindQuarantinedOrdersDialog.QuarantinedReservationSection.ResourceAssignmentSection.Initialize")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations.FindQuarantinedOrdersDialog.QuarantinedReservationSection.ResourceAssignmentSection.UpdateResourceButton_Pressed(System.Object,System.EventArgs)")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~P:Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Reservations.FindQuarantinedOrdersDialog.QuarantinedReservationSection.ResourceAssignmentSection.FunctionSection.SelectedResource")] +[assembly: SuppressMessage("Minor Code Smell", "S6608:Prefer indexing instead of \"Enumerable\" methods on types implementing \"IList\"", Justification = "", Scope = "member", Target = "~M:Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug.Resources.FixResourceConfigurationDialog.UpdateResourcesButton_Pressed(System.Object,System.EventArgs)")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..50018dd --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Debug_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("Debug_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("7EBD3ADA-EF18-4285-A42A-042F004F31FE")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Script.cs new file mode 100644 index 0000000..d70fb62 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/Script.cs @@ -0,0 +1,359 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace Debug_2 +{ + using System; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Reflection; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Debug; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using System.Collections.Generic; + using System.IO; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + /// + /// DataMiner Script Class. + /// + public class Script : IDisposable + { + private const string LocalTempFolderPath = @"C:\Skyline DataMiner\Documents\.Temp"; + private const string RemoteTempFolderPath = @"\Documents\.Temp"; + + private Helpers helpers; + private InteractiveController app; + private OverviewDialog overviewDialog; + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + try + { + Initialize(engine); + + app.Run(overviewDialog); + } + catch (ScriptAbortException) + { + // Nothing to log + } + catch (InteractiveUserDetachedException) + { + // Nothing to log + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Something went wrong: {e}"); + + ExceptionDialog exceptionDialog = new ExceptionDialog(engine, e); + exceptionDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("OK"); + if (app.IsRunning) app.ShowDialog(exceptionDialog); + else app.Run(exceptionDialog); + } + finally + { + Dispose(); + } + } + + private void Initialize(Engine engine) + { + //engine.ShowUI(); + engine.ShowProgress("Loading..."); + engine.Timeout = TimeSpan.FromHours(10); + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.SetFlag(RunTimeFlags.NoCheckingSets); + engine.SetFlag(RunTimeFlags.NoInformationEvents); + + helpers = new Helpers(engine, Scripts.Debug); + + app = new InteractiveController(engine); + + overviewDialog = new OverviewDialog(helpers); + + overviewDialog.FindReservationsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FindReservationsDialog); + overviewDialog.FindReservationOrderLoggingButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FindReservationLoggingDialog); + overviewDialog.GetServiceConfigurationsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.ServiceConfigurationsDialog); + overviewDialog.RetriggerIntegrationUpdatesButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.RetriggerIntegrationUpdatesDialog); + overviewDialog.ReservationsWithoutJobsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FindReservationsWithoutJobDialog); + overviewDialog.MetricsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.MetricsDialog); + overviewDialog.SendIntegrationNotificationButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog); + overviewDialog.UpdateOrderUiPropertiesButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.UpdateOrderUiPropertiesDialog); + overviewDialog.LogCollectorButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.LogCollectorDialog); + overviewDialog.EligibleResourcesButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.GetEligibleResourcesDialog); + overviewDialog.ResourceOccupancyButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.ResourceOccupancyDialog); + overviewDialog.MoveToQuarantinedStateButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.MoveToQuarantinedStateDialog); + overviewDialog.FindQuarantinedOrdersButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FindQuarantinedOrdersDialog); + overviewDialog.FindProfileParameterButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FindProfileParameterDialog); + overviewDialog.FindTicketsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FindTicketsDialog); + overviewDialog.EditReservationPropertiesButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.EditReservationPropertiesDialog); + overviewDialog.OrderHistoryButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.OrderHistoryDialog); + overviewDialog.StopOrderNowButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.StopOrderNowDialog); + overviewDialog.AddOrUpdateServiceConfigurationsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.AddOrUpdateServiceConfigurationsDialog); + overviewDialog.FixServiceConfigurationsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FixServiceConfigurationsDialog); + overviewDialog.DeleteOrdersButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.DeleteOrdersDialog); + overviewDialog.FixResourceConfigurationButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FixResourceConfigurationDialog); + overviewDialog.DeleteTemplatesButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.DeleteTemplatesDialog); + overviewDialog.EditOrderTemplateButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.EditOrderTemplatesDialog); + overviewDialog.EditEventTemplateButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.EditEventTemplatesDialog); + overviewDialog.AnalyzePlasmaRecordingsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.AnalyzePlasmaRecordingsDialog); + overviewDialog.VizremButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.VizremDialog); + overviewDialog.ActiveFunctionsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.ActiveFunctionsDialog); + overviewDialog.GetServiceDefinitionButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.GetServiceDefinitionDialog); + overviewDialog.UpdateServiceDefinitionsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.UpdateServiceDefinitionsDialog); + overviewDialog.FindResourcesWithFiltersButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FindResourcesWithFiltersDialog); + overviewDialog.FindReservationsWithFiltersButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FindReservationsWithFiltersDialog); + overviewDialog.RemoveDuplicatePropertiesButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.RemoveDuplicatePropertiesDialog); + overviewDialog.FindTicketsWithFiltersButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FindTicketsWithFiltersDialog); + overviewDialog.UpdateNonLiveOrderUserTasksButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.UpdateNonLiveOrderUserTasksDialog); + overviewDialog.TestDataMinerInterfaceButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.TestDataMinerInterfaceDialog); + overviewDialog.FixMissingServiceDefinitionsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.FixMissingServiceDefinitionsDialog); + overviewDialog.AddOrUpdateResourcesButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.AddOrUpdateResourcesDialog); + overviewDialog.ReassignJobButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.ReassignJobDialog); + overviewDialog.ManageSectionDefinitionsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.ManageSectionDefinitionsDialog); + overviewDialog.ProfileLoadLoggingButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.ProfileLoadLoggingDialog); + overviewDialog.AutoUpdateOrderPropertiesButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.AutoUpdateOrderPropertiesDialog); + overviewDialog.NonLiveOrdersButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.NonLiveOrdersDialog); + overviewDialog.DownloadLoggingButton.Pressed += (sender, args) => DownloadLogging(); + + overviewDialog.SendIntegrationNotificationDialog.FeenixButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog.FeenixNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.CeitonButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog.CeitonNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.PlasmaButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog.PlasmaNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.PlasmaOldButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog.PlasmaNotificationOldDialog); + overviewDialog.SendIntegrationNotificationDialog.EurovisionButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog.EurovisionNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.PebbleBeachButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog.PbsNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.EvsButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog.EvsNotificationDialog); + + overviewDialog.FindReservationsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FindReservationLoggingDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.ServiceConfigurationsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.RetriggerIntegrationUpdatesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FindReservationsWithoutJobDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.MetricsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.SendIntegrationNotificationDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.UpdateOrderUiPropertiesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.LogCollectorDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.GetEligibleResourcesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.ResourceOccupancyDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.MoveToQuarantinedStateDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FindQuarantinedOrdersDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FindProfileParameterDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FindTicketsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.EditReservationPropertiesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.OrderHistoryDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.StopOrderNowDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.AddOrUpdateServiceConfigurationsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FixServiceConfigurationsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.DeleteOrdersDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FixResourceConfigurationDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.DeleteTemplatesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.EditOrderTemplatesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.EditEventTemplatesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.AnalyzePlasmaRecordingsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.VizremDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.VizremDialog.TriggerBookFlowButton.Pressed += (sender, args) => overviewDialog.VizremDialog.CreateVizremOrder(app); + overviewDialog.ActiveFunctionsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.GetServiceDefinitionDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.UpdateServiceDefinitionsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FindResourcesWithFiltersDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FindReservationsWithFiltersDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.RemoveDuplicatePropertiesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FindTicketsWithFiltersDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.UpdateNonLiveOrderUserTasksDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.TestDataMinerInterfaceDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.FixMissingServiceDefinitionsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.AddOrUpdateResourcesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.ReassignJobDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.ManageSectionDefinitionsDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.ProfileLoadLoggingDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.AutoUpdateOrderPropertiesDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + overviewDialog.NonLiveOrdersDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog); + + overviewDialog.SendIntegrationNotificationDialog.FeenixNotificationDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.PlasmaNotificationDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.PlasmaNotificationOldDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.CeitonNotificationDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.EurovisionNotificationDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog); + overviewDialog.SendIntegrationNotificationDialog.PbsNotificationDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog); + + overviewDialog.GenerateFieldsFileButton.Pressed += (sender, args) => GenerateFieldsFile(engine); + + SubscribeOnUpdateOrderUiPropertiesDialog(); + SubscribeOnAnalyzePlasmaRecordingsDialog(); + SubscribeOnFixServiceConfigurationsDialog(); + + if (overviewDialog.SendIntegrationNotificationDialog.EvsNotificationDialog != null) + { + overviewDialog.SendIntegrationNotificationDialog.EvsNotificationDialog.BackButton.Pressed += (sender, args) => app.ShowDialog(overviewDialog.SendIntegrationNotificationDialog); + } + } + + private void GenerateFieldsFile(Engine engine) + { + ReflectionHandler.GetFields(engine, helpers, "YLE.UI"); + ReflectionHandler.WriteFile(helpers); + engine.Log(nameof(Script), nameof(GenerateFieldsFile), $"UiFields Count: {ReflectionHandler.UiToolTips.Count}"); + engine.Log(nameof(Script), nameof(GenerateFieldsFile), $"UiFields: {JsonConvert.SerializeObject(ReflectionHandler.UiToolTips)}"); + } + + private void SubscribeOnUpdateOrderUiPropertiesDialog() + { + overviewDialog.UpdateOrderUiPropertiesDialog.ShowConfirmationDialog += (sender, args) => + { + args.NoButton.Pressed += (s, a) => app.ShowDialog(overviewDialog.UpdateOrderUiPropertiesDialog); + app.ShowDialog(args); + }; + + overviewDialog.UpdateOrderUiPropertiesDialog.ShowProgressDialog += (sender, args) => app.ShowDialog(args); + + overviewDialog.UpdateOrderUiPropertiesDialog.OrdersUpdated += (sender, args) => app.ShowDialog(overviewDialog.UpdateOrderUiPropertiesDialog); + } + + private void SubscribeOnAnalyzePlasmaRecordingsDialog() + { + overviewDialog.AnalyzePlasmaRecordingsDialog.ShowConfirmationDialog += (sender, args) => + { + args.NoButton.Pressed += (s, a) => app.ShowDialog(overviewDialog.AnalyzePlasmaRecordingsDialog); + app.ShowDialog(args); + }; + + overviewDialog.AnalyzePlasmaRecordingsDialog.ShowProgressDialog += (sender, args) => app.ShowDialog(args); + + overviewDialog.AnalyzePlasmaRecordingsDialog.OrdersUpdated += (sender, args) => app.ShowDialog(overviewDialog.AnalyzePlasmaRecordingsDialog); + } + + private void SubscribeOnFixServiceConfigurationsDialog() + { + overviewDialog.FixServiceConfigurationsDialog.ShowConfirmationDialog += (sender, args) => + { + args.NoButton.Pressed += (s, a) => app.ShowDialog(overviewDialog.FixServiceConfigurationsDialog); + app.ShowDialog(args); + }; + + overviewDialog.FixServiceConfigurationsDialog.ShowProgressDialog += (sender, args) => app.ShowDialog(args); + + overviewDialog.FixServiceConfigurationsDialog.OrdersUpdated += (sender, args) => app.ShowDialog(overviewDialog.FixServiceConfigurationsDialog); + } + + private void DownloadLogging() + { + try + { + var subsScript = helpers.Engine.PrepareSubScript("FileRetrieval"); + subsScript.SelectScriptParam("path", $@"C:\Skyline_Data\OrderLogging\{overviewDialog.CurrentIdTextBox.Text}.txt"); + subsScript.SelectScriptParam("isSubscript", "false"); + subsScript.SelectScriptParam("download", "false"); + subsScript.Synchronous = true; + subsScript.StartScript(); + + var result = subsScript.GetScriptResult(); + + var retrievedFiles = JsonConvert.DeserializeObject>(result["fileInfo"]); + string tempDirToZip = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + if (!Directory.Exists(tempDirToZip)) Directory.CreateDirectory(tempDirToZip); + + foreach (var file in retrievedFiles) + { + if (String.IsNullOrWhiteSpace(file.Content)) continue; + + string tempFilePath = Path.Combine(tempDirToZip, $"{file.Agent}_{overviewDialog.CurrentIdTextBox.Text}.txt"); + File.WriteAllText(tempFilePath, file.Content); + } + + string zipArchiveName = $"{overviewDialog.CurrentIdTextBox.Text}.zip"; + string localZipArchivePath = Path.Combine(LocalTempFolderPath, zipArchiveName); + if (File.Exists(localZipArchivePath)) File.Delete(localZipArchivePath); + System.IO.Compression.ZipFile.CreateFromDirectory(tempDirToZip, localZipArchivePath); + + DownloadDialog dialog = new DownloadDialog(helpers.Engine, Path.Combine(RemoteTempFolderPath, zipArchiveName)); + dialog.DownloadButton.DownloadStarted += (s, e) => app.ShowDialog(overviewDialog); + app.ShowDialog(dialog); + } + catch (Exception ex) + { + helpers.Log(nameof(OverviewDialog), nameof(DownloadLogging), $"Unable to retrieve log files due to: {ex}"); + } + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } + + public class RetrievedFile + { + public string Agent { get; set; } + + public string Content { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Debug_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates.xml new file mode 100644 index 0000000..32396c7 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates.xml @@ -0,0 +1,24 @@ + + + DecodingResourceCapabilityUpdates + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/SRM + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/DecodingResourceCapabilityUpdates_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/DecodingResourceCapabilityUpdates_1.csproj new file mode 100644 index 0000000..7729a4b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/DecodingResourceCapabilityUpdates_1.csproj @@ -0,0 +1,93 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {6C8B2D4E-6B4E-4F71-AA72-BF0BB37D6DAD} + Library + Properties + DecodingResourceCapabilityUpdates_1 + DecodingResourceCapabilityUpdates_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\DecodingResourceCapabilityUpdates_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\DecodingResourceCapabilityUpdates_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/GlobalSuppressions.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/GlobalSuppressions.cs new file mode 100644 index 0000000..64b5f30 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/GlobalSuppressions.cs @@ -0,0 +1,10 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:DecodingResourceCapabilityUpdates_1.Script.GetNs3DemodulatingResources(Skyline.DataMiner.Net.Messages.ResourceManagerHelper)~System.Collections.Generic.List{System.String}")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:DecodingResourceCapabilityUpdates_1.Script.GetResourcesConnectedToMatrixOutputAsiResource(Skyline.DataMiner.Net.Messages.ResourceManagerHelper)~System.Collections.Generic.HashSet{System.String}")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:DecodingResourceCapabilityUpdates_1.Script.UpdateDecodingResourcesWithCorrectLinksToDemodulatingResources(Skyline.DataMiner.Net.Messages.ResourceManagerHelper,System.Collections.Generic.HashSet{System.String},System.Collections.Generic.List{System.String})")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2fc1a4e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("DecodingResourceCapabilityUpdates_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("DecodingResourceCapabilityUpdates_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("BE836594-4AF7-4BD2-94DD-55A11AC14974")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/Script.cs new file mode 100644 index 0000000..7211673 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/Script.cs @@ -0,0 +1,191 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace DecodingResourceCapabilityUpdates_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + + /// + /// DataMiner Script Class. + /// + class Script + { + private static readonly Guid ResourceOutputConnectionsASICapabilityProfileId = Guid.Parse("3c08c3a7-d1fb-46f2-877b-8927345cf931"); + private static readonly Guid ResourceInputConnectionsASICapabilityProfileId = Guid.Parse("58a7e9e4-6a39-42c9-b275-92f9dc7f9003"); + private static readonly Guid ModulationStandardCapabilityProfileId = Guid.Parse("ed8446e9-e373-419d-9b9f-8a1c94ec8ae7"); + + private const string MatrixOutputASIResourcePoolName = "Reception.Satellite.Matrix Output ASI"; + private const string DecodingResourcePoolName = "Reception.Satellite.Decoding"; + private const string DemodulatingResourcePoolName = "Reception.Satellite.Demodulating"; + + private const string ns3ModulationStandard = "NS3"; + private const string ns4ModulationStandard = "NS4"; + + public void Run(Engine engine) + { + var resourceManagerHelper = new ResourceManagerHelper(); + resourceManagerHelper.RequestResponseEvent += (s, e) => e.responseMessage = engine.SendSLNetSingleResponseMessage(e.requestMessage); + + var resourcesConnectedToMatrixOutputASI = GetResourcesConnectedToMatrixOutputAsiResource(resourceManagerHelper); + if (!resourcesConnectedToMatrixOutputASI.Any()) return; + + var demodulatingResources = GetNs3DemodulatingResources(resourceManagerHelper); + demodulatingResources.AddRange(GetTREDemodulatingResources(resourceManagerHelper)); + if (!demodulatingResources.Any()) return; + + UpdateDecodingResourcesWithCorrectLinksToDemodulatingResources(resourceManagerHelper, resourcesConnectedToMatrixOutputASI, demodulatingResources); + } + + private HashSet GetResourcesConnectedToMatrixOutputAsiResource(ResourceManagerHelper resourceManagerHelper) + { + var resourcesConnectedToMatrixOutputASI = new HashSet(); + + var matrixOutputASIResourcePool = resourceManagerHelper.GetResourcePools(new ResourcePool { Name = MatrixOutputASIResourcePoolName }).FirstOrDefault(); + if (matrixOutputASIResourcePool == null) return resourcesConnectedToMatrixOutputASI; + + var matrixOutputASIResources = resourceManagerHelper.GetResources(ResourceExposers.PoolGUIDs.Contains(matrixOutputASIResourcePool.ID)); + if (matrixOutputASIResources == null) return resourcesConnectedToMatrixOutputASI; + + foreach (var matrixOutputASIResource in matrixOutputASIResources) + { + var resourceOutputConnectionsASICapability = matrixOutputASIResource.Capabilities.FirstOrDefault(c => c.CapabilityProfileID == ResourceOutputConnectionsASICapabilityProfileId); + if (resourceOutputConnectionsASICapability?.Value?.Discreets == null) continue; + + foreach (var discreetValue in resourceOutputConnectionsASICapability.Value.Discreets) + { + if (String.IsNullOrEmpty(discreetValue)) continue; + + resourcesConnectedToMatrixOutputASI.Add(discreetValue); + } + } + + return resourcesConnectedToMatrixOutputASI; + } + + private List GetNs3DemodulatingResources(ResourceManagerHelper resourceManagerHelper) + { + var ns3DemodulatingResources = new HashSet(); + + var demodulatingResourcePool = resourceManagerHelper.GetResourcePools(new ResourcePool { Name = DemodulatingResourcePoolName }).FirstOrDefault(); + if (demodulatingResourcePool == null) return ns3DemodulatingResources.ToList(); + + var demodulatingResources = resourceManagerHelper.GetResources(ResourceExposers.PoolGUIDs.Contains(demodulatingResourcePool.ID)); + if (demodulatingResources == null) return ns3DemodulatingResources.ToList(); + + foreach (var demodulatingResource in demodulatingResources) + { + var modulatingStandardCapability = demodulatingResource.Capabilities.FirstOrDefault(c => c.CapabilityProfileID == ModulationStandardCapabilityProfileId); + if (modulatingStandardCapability?.Value?.Discreets == null) continue; + + foreach (var discreetValue in modulatingStandardCapability.Value.Discreets) + { + if (discreetValue == ns3ModulationStandard || discreetValue == ns4ModulationStandard) ns3DemodulatingResources.Add(demodulatingResource.Name); + } + } + + return ns3DemodulatingResources.ToList(); + } + + private List GetTREDemodulatingResources(ResourceManagerHelper resourceManagerHelper) + { + var treDemodulatingResources = new HashSet(); + + var demodulatingResourcePool = resourceManagerHelper.GetResourcePools(new ResourcePool { Name = DemodulatingResourcePoolName }).FirstOrDefault(); + if (demodulatingResourcePool == null) return treDemodulatingResources.ToList(); + + var demodulatingResources = resourceManagerHelper.GetResources(ResourceExposers.PoolGUIDs.Contains(demodulatingResourcePool.ID)); + if (demodulatingResources == null) return treDemodulatingResources.ToList(); + + foreach (var demodulatingResource in demodulatingResources) + { + if (demodulatingResource.Name.Contains("TRE")) treDemodulatingResources.Add(demodulatingResource.Name); + } + + return treDemodulatingResources.ToList(); + } + + private void UpdateDecodingResourcesWithCorrectLinksToDemodulatingResources(ResourceManagerHelper resourceManagerHelper, HashSet resourcesConnectedToMatrixOutputASI, List demodulatingResources) + { + var decodingResourcePool = resourceManagerHelper.GetResourcePools(new ResourcePool { Name = DecodingResourcePoolName }).FirstOrDefault(); + if (decodingResourcePool == null) return; + + var decodingResourcesToUpdate = new List(); + var decodingResources = resourceManagerHelper.GetResources(ResourceExposers.PoolGUIDs.Contains(decodingResourcePool.ID)); + foreach (var decodingResource in decodingResources) + { + if (!resourcesConnectedToMatrixOutputASI.Contains(decodingResource.Name)) continue; + + var resourceInputConnectionsASICapability = decodingResource.Capabilities.FirstOrDefault(c => c.CapabilityProfileID == ResourceInputConnectionsASICapabilityProfileId); + if (resourceInputConnectionsASICapability?.Value == null) continue; + + bool updateRequired = false; + foreach (var ns3DemodulatingResource in demodulatingResources) + { + if (!resourceInputConnectionsASICapability.Value.Discreets.Contains(ns3DemodulatingResource)) + { + resourceInputConnectionsASICapability.Value.Discreets.Add(ns3DemodulatingResource); + + updateRequired = true; + } + } + + if (updateRequired) decodingResourcesToUpdate.Add(decodingResource); + } + + if (decodingResourcesToUpdate.Any()) resourceManagerHelper.AddOrUpdateResources(true, decodingResourcesToUpdate.ToArray()); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DecodingResourceCapabilityUpdates_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent.xml new file mode 100644 index 0000000..0d85ad7 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent.xml @@ -0,0 +1,31 @@ + + + DeleteEvent + Script 1.0.1.77 + Automation + SKYLINE2\ThomasRE + FALSE + YLE/Customer UI + + + + + + + + + + jobId + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/DeleteEventDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/DeleteEventDialog.cs new file mode 100644 index 0000000..ac09a6f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/DeleteEventDialog.cs @@ -0,0 +1,43 @@ +namespace DeleteEvent_2 +{ + using System; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking; + + public class DeleteEventDialog : Dialog + { + private readonly Label informationLabel; + + public DeleteEventDialog(Engine engine, LockInfo lockInfo) : base(engine) + { + YesButton = new Button("Yes") { Width = 150, Style = ButtonStyle.CallToAction }; + NoButton = new Button("No") { Width = 150 }; + OkButton = new Button("Ok") { Width = 150, Style = ButtonStyle.CallToAction }; + + Title = "Delete Event"; + + if (lockInfo.IsLockGranted) + { + informationLabel = new Label("Are you sure you want to delete this Event?"); + + AddWidget(informationLabel, 0, 0, 1, 2); + AddWidget(YesButton, 1, 0); + AddWidget(NoButton, 1, 1); + } + else + { + informationLabel = new Label(String.Format("Unable to delete this Event as it is currently locked by {0}", lockInfo.LockUsername)); + + AddWidget(informationLabel, 0, 0, 1, 2); + AddWidget(OkButton, 1, 0); + } + } + + public Button YesButton { get; private set; } + + public Button NoButton { get; private set; } + + public Button OkButton { get; private set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/DeleteEvent_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/DeleteEvent_2.csproj new file mode 100644 index 0000000..0c35b00 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/DeleteEvent_2.csproj @@ -0,0 +1,104 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {E69808C1-8776-4055-8385-05CCE596C4E5} + Library + Properties + DeleteEvent_2 + DeleteEvent_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\DeleteEvent_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\DeleteEvent_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + 1.0.1.12 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ee0b163 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("DeleteEvent_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("DeleteEvent_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("267591BF-AEFD-4D1B-9555-DFA5C307F842")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/Script.cs new file mode 100644 index 0000000..cdaf34b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/Script.cs @@ -0,0 +1,297 @@ +/* +**************************************************************************** +* Copyright (c) 2019, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2019 1.0.0.1 XXX, Skyline Initial Version +**************************************************************************** +*/ + + + +//--------------------------------- +// DeleteEvent_2.cs +//--------------------------------- + +// Added so DM recognizes this script as an IAS. +// engine.ShowUI(); + +namespace DeleteEvent_2 +{ + using System; + using System.Threading.Tasks; + using System.Timers; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.YLE.Integrations; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + /// + /// DataMiner Script Class. + /// + class Script : IDisposable + { + private Helpers helpers; + private Engine engine; + private InteractiveController app; + private string jobId; + private LockInfo lockInfo; + private Event eventInfo; + + private int attemptsExtendLocking = 1; + private readonly Timer extendLocksTimer = new Timer(); + + private int timeOutResult; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + Task scriptTask = Task.Factory.StartNew(() => + { + try + { + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.Timeout = TimeSpan.FromHours(10); + + app = new InteractiveController(engine); + helpers = new Helpers(engine, Scripts.DeleteEvent); + this.engine = engine; + + jobId = engine.GetScriptParam("jobId").Value; + + lockInfo = helpers.LockManager.RequestEventLock(jobId); + + eventInfo = GetEvent(); + + RunSafe(engine); + } + catch (ScriptAbortException) + { + Dispose(); + } + catch (InteractiveUserDetachedException) + { + Dispose(); + } + catch (Exception e) + { + if (timeOutResult != -1) + { + ShowExceptionDialog(engine, e); + Dispose(); + } + } + }); + + timeOutResult = Task.WaitAny(new [] { scriptTask }, new TimeSpan(9, 59, 40)); + if (timeOutResult == -1) + { + Dispose(); + } + } + + private void RunSafe(Engine engine) + { + app = new InteractiveController(engine); + + if (lockInfo != null && lockInfo.IsLockGranted) + { + extendLocksTimer.Elapsed += ExtendLocksTimer_Elapsed; + extendLocksTimer.Interval = lockInfo.ReleaseLocksAfter.TotalMilliseconds; + extendLocksTimer.AutoReset = true; + extendLocksTimer.Enabled = true; + } + + if (eventInfo.IntegrationType == IntegrationType.None) + { + DeleteEventDialog deleteEventDialog = new DeleteEventDialog(engine, lockInfo); + deleteEventDialog.YesButton.Pressed += DeleteEventDialog_YesButton_Pressed; + deleteEventDialog.NoButton.Pressed += (sender, args) => engine.ExitSuccess("The event was not deleted."); + deleteEventDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("The event was not deleted."); + app.Run(deleteEventDialog); + } + else + { + ShowMessageDialog(engine, "Unable to delete this event as it is created/updated by an integration", "Unable to Delete"); + } + } + + private void DeleteEventDialog_YesButton_Pressed(object sender, EventArgs e) + { + if (eventInfo == null) + { + var dialog = new MessageDialog(engine, String.Format("Event ({0}) could not be found", jobId)) { Title = "Unable to retrieve Event" }; + dialog.OkButton.Pressed += (send, args) => engine.ExitSuccess("Unable to retrieve the event."); + app.ShowDialog(dialog); + + return; + } + + if (helpers.EventManager.HasOrders(eventInfo.Id)) + { + var dialog = new MessageDialog(engine, String.Format("Event {0} can't be deleted as it still contains orders", eventInfo.Name)) { Title = "Event not deleted" }; + dialog.OkButton.Pressed += (send, args) => engine.ExitSuccess("Event not deleted."); + app.ShowDialog(dialog); + + return; + } + + if (!helpers.EventManager.DeleteEvent(eventInfo.Id)) + { + var dialog = new MessageDialog(engine, String.Format("Unable to delete event {0}", eventInfo.Name)) { Title = "Unable to delete Event" }; + dialog.OkButton.Pressed += (send, args) => engine.ExitSuccess("Unable to delete the event."); + app.ShowDialog(dialog); + + return; + } + + engine.ExitSuccess("The event was successfully deleted."); + } + + private void ExtendLocksTimer_Elapsed(object sender, ElapsedEventArgs e) + { + if (attemptsExtendLocking >= 10) + { + extendLocksTimer.Stop(); + return; + } + + if (eventInfo != null) + { + var eventLockInfo = helpers.LockManager.RequestEventLock(eventInfo.Id, extendLock: true); + if (eventLockInfo.LockUsername.Contains("error")) + { + ShowExceptionDialog(engine, new Exception("Extend lock request didn't succeed")); + } + } + + attemptsExtendLocking++; + } + + private Event GetEvent() + { + try + { + Guid jobGuid; + if (!Guid.TryParse(jobId, out jobGuid)) + { + return null; + } + + return helpers.EventManager.GetEvent(jobGuid); + } + catch (Exception e) + { + engine.Log("GetEvent|Retrieving Event failed: " + e); + } + + return null; + } + + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong during the creation of the new Event."); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + private void ShowMessageDialog(Engine engine, string message, string title) + { + MessageDialog dialog = new MessageDialog(engine, message) { Title = title }; + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess(message); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + #region IDisposable Support + private bool disposedValue; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + + helpers.LockManager.ReleaseLocks(); + + extendLocksTimer.Stop(); + extendLocksTimer.Dispose(); + } + + disposedValue = true; + } + } + + ~Script() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} + +//--------------------------------- +// DeleteEventDialog.cs +//--------------------------------- \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteEvent_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders.xml new file mode 100644 index 0000000..76589ed --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders.xml @@ -0,0 +1,28 @@ + + + DeleteIntegrationOrders + Script 1.0.1.77 + Automation + SKYLINE2\thomasre + FALSE + YLE/Tools + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/DeleteIntegrationOrders_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/DeleteIntegrationOrders_1.csproj new file mode 100644 index 0000000..76b7719 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/DeleteIntegrationOrders_1.csproj @@ -0,0 +1,107 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {66B48A43-2EA8-4463-81B5-D842A49DBD73} + Library + Properties + DeleteIntegrationOrders_1 + DeleteIntegrationOrders_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\DeleteIntegrationOrders_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\DeleteIntegrationOrders_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + 1.0.1.12 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/GlobalSuppressions.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/GlobalSuppressions.cs new file mode 100644 index 0000000..35f624e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/GlobalSuppressions.cs @@ -0,0 +1,15 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:DeleteIntegrationOrders_1.Script.GetIntegrationEvents(Skyline.DataMiner.Utils.YLE.Integrations.IntegrationType)~System.Collections.Generic.List{DeleteIntegrationOrders_1.ISrmObject}")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~P:DeleteIntegrationOrders_1.IntegrationOrdersDialog.SelectedCeitonEvent")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~P:DeleteIntegrationOrders_1.IntegrationOrdersDialog.SelectedEbuEvent")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~P:DeleteIntegrationOrders_1.IntegrationOrdersDialog.SelectedEbuOrder")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~P:DeleteIntegrationOrders_1.IntegrationOrdersDialog.SelectedFeenixEvent")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~P:DeleteIntegrationOrders_1.IntegrationOrdersDialog.SelectedFeenixOrder")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~P:DeleteIntegrationOrders_1.IntegrationOrdersDialog.SelectedPlasmaEvent")] +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~P:DeleteIntegrationOrders_1.IntegrationOrdersDialog.SelectedPlasmaOrders")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/ISrmObject.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/ISrmObject.cs new file mode 100644 index 0000000..e056387 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/ISrmObject.cs @@ -0,0 +1,14 @@ +namespace DeleteIntegrationOrders_1 +{ + using System; + using Skyline.DataMiner.Utils.YLE.Integrations; + + public interface ISrmObject + { + string Name { get; set; } + + Guid ID { get; set; } + + IntegrationType Type { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/IntegrationEvent.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/IntegrationEvent.cs new file mode 100644 index 0000000..080fde3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/IntegrationEvent.cs @@ -0,0 +1,18 @@ +namespace DeleteIntegrationOrders_1 +{ + using System; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations; + using Skyline.DataMiner.Net.Jobs; + using Skyline.DataMiner.Utils.YLE.Integrations; + + public class IntegrationEvent : ISrmObject + { + public string Name { get; set; } + + public Guid ID { get; set; } + + public IntegrationType Type { get; set; } + + public Job Job { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/IntegrationOrder.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/IntegrationOrder.cs new file mode 100644 index 0000000..57eed1b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/IntegrationOrder.cs @@ -0,0 +1,18 @@ +namespace DeleteIntegrationOrders_1 +{ + using System; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Utils.YLE.Integrations; + + public class IntegrationOrder : ISrmObject + { + public string Name { get; set; } + + public Guid ID { get; set; } + + public IntegrationType Type { get; set; } + + public ServiceReservationInstance Reservation { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/IntegrationOrdersDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/IntegrationOrdersDialog.cs new file mode 100644 index 0000000..cad2e5c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/IntegrationOrdersDialog.cs @@ -0,0 +1,247 @@ +namespace DeleteIntegrationOrders_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class IntegrationOrdersDialog : Dialog + { + public IntegrationOrdersDialog(Engine engine) : base(engine) + { + Title = "Delete Integration Orders"; + + PlasmaOrdersRadioButtonList.Changed += (sender, args) => + { + PlasmaOrdersDropdown.IsEnabled = (args.SelectedValue == "Single"); + PlasmaMultipleOrdersTextBox.IsEnabled = (args.SelectedValue == "Multiple"); + }; + + GenerateUI(); + } + + private void GenerateUI() + { + int row = -1; + + AddWidget(new Label("Plasma") { Style = TextStyle.Heading }, ++row, 0, 1, 3); + + AddWidget(new Label("Orders"), ++row, 0); + AddWidget(PlasmaOrdersRadioButtonList, row, 1); + + AddWidget(PlasmaOrdersDropdown, ++row, 1); + AddWidget(DeleteSelectedPlasmaOrderButton, row, 2); + + AddWidget(PlasmaMultipleOrdersTextBox, ++row, 1); + + AddWidget(new Label("Events"), ++row, 0); + AddWidget(PlasmaEventsDropdown, row, 1); + AddWidget(DeleteSelectedPlasmaEventButton, row, 2); + + AddWidget(new Label("Feenix") { Style = TextStyle.Heading }, ++row, 0, 1, 3); + + AddWidget(new Label("Orders"), ++row, 0); + AddWidget(FeenixOrdersDropdown, row, 1); + AddWidget(DeleteSelectedFeenixOrderButton, row, 2); + + AddWidget(new Label("Events"), ++row, 0); + AddWidget(FeenixEventsDropdown, row, 1); + AddWidget(DeleteSelectedFeenixEventButton, row, 2); + + AddWidget(new Label("Eurovision") { Style = TextStyle.Heading }, ++row, 0, 1, 3); + + AddWidget(new Label("Orders"), ++row, 0); + AddWidget(EbuOrdersDropdown, row, 1); + AddWidget(DeleteSelectedEbuOrderButton, row, 2); + + AddWidget(new Label("Events"), ++row, 0); + AddWidget(EbuEventsDropdown, row, 1); + AddWidget(DeleteSelectedEbuEventButton, row, 2); + + AddWidget(new Label("Ceiton") { Style = TextStyle.Heading }, ++row, 0, 1, 3); + + AddWidget(new Label("Events"), ++row, 0); + AddWidget(CeitonEventsDropdown, row, 1); + AddWidget(DeleteSelectedCeitonEventButton, row, 2); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(DeleteAllIntegrationsButton, ++row, 0); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(ExitButton, row + 1, 0); + } + + public void InitPlasmaOrders(List orders) + { + PlasmaOrders = orders; + PlasmaOrdersDropdown.Options = orders.Select(x => x.Name); + } + + public void InitPlasmaEvents(List events) + { + PlasmaEvents = events; + PlasmaEventsDropdown.Options = events.Select(x => x.Name); + } + + public void InitFeenixOrders(List orders) + { + FeenixOrders = orders; + FeenixOrdersDropdown.Options = orders.Select(x => x.Name); + } + + public void InitFeenixEvents(List events) + { + FeenixEvents = events; + FeenixEventsDropdown.Options = events.Select(x => x.Name); + } + + public void InitEbuOrders(List orders) + { + EbuOrders = orders; + EbuOrdersDropdown.Options = orders.Select(x => x.Name); + } + + public void InitEbuEvents(List events) + { + EbuEvents = events; + EbuEventsDropdown.Options = events.Select(x => x.Name); + } + + public void InitCeitonEvents(List events) + { + CeitonEvents = events; + CeitonEventsDropdown.Options = events.Select(x => x.Name); + } + + public List PlasmaOrders { get; private set; } = new List(); + + public List PlasmaEvents { get; private set; } = new List(); + + public List FeenixOrders { get; private set; } = new List(); + + public List FeenixEvents { get; private set; } = new List(); + + public List EbuOrders { get; private set; } = new List(); + + public List EbuEvents { get; private set; } = new List(); + + public List CeitonEvents { get; private set; } = new List(); + + public ISrmObject[] SelectedPlasmaOrders + { + get + { + if (PlasmaOrdersRadioButtonList.Selected == "Single") + { + return new ISrmObject[] { PlasmaOrders.FirstOrDefault(x => x.Name.Equals(PlasmaOrdersDropdown.Selected)) }; + } + else + { + string[] splitPlasmaIds = PlasmaMultipleOrdersTextBox.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + List selectedOrders = new List(); + foreach (string plasmaId in splitPlasmaIds) + { + selectedOrders.Add(PlasmaOrders.FirstOrDefault(x => x.Name.Contains(plasmaId))); + } + + return selectedOrders.ToArray(); + } + } + } + + public ISrmObject SelectedPlasmaEvent + { + get + { + return PlasmaEvents.FirstOrDefault(x => x.Name.Equals(PlasmaEventsDropdown.Selected)); + } + } + + public ISrmObject SelectedFeenixOrder + { + get + { + return FeenixOrders.FirstOrDefault(x => x.Name.Equals(FeenixOrdersDropdown.Selected)); + } + } + + public ISrmObject SelectedFeenixEvent + { + get + { + return FeenixEvents.FirstOrDefault(x => x.Name.Equals(FeenixEventsDropdown.Selected)); + } + } + + public ISrmObject SelectedEbuOrder + { + get + { + return EbuOrders.FirstOrDefault(x => x.Name.Equals(EbuOrdersDropdown.Selected)); + } + } + + public ISrmObject SelectedEbuEvent + { + get + { + return EbuEvents.FirstOrDefault(x => x.Name.Equals(EbuEventsDropdown.Selected)); + } + } + + public ISrmObject SelectedCeitonEvent + { + get + { + return CeitonEvents.FirstOrDefault(x => x.Name.Equals(CeitonEventsDropdown.Selected)); + } + } + + public RadioButtonList PlasmaOrdersRadioButtonList { get; private set; } = new RadioButtonList(new string[] { "Single", "Multiple" }, "Single"); + + public DropDown PlasmaOrdersDropdown { get; private set; } = new DropDown { IsDisplayFilterShown = true, IsSorted = true }; + + public DropDown PlasmaEventsDropdown { get; private set; } = new DropDown { IsDisplayFilterShown = true, IsSorted = true }; + + public TextBox PlasmaMultipleOrdersTextBox { get; private set; } = new TextBox { IsMultiline = true, Height = 300, IsEnabled = false }; + + public DropDown FeenixOrdersDropdown { get; private set; } = new DropDown { IsDisplayFilterShown = true, IsSorted = true }; + + public DropDown FeenixEventsDropdown { get; private set; } = new DropDown { IsDisplayFilterShown = true, IsSorted = true }; + + public DropDown EbuOrdersDropdown { get; private set; } = new DropDown { IsDisplayFilterShown = true, IsSorted = true }; + + public DropDown EbuEventsDropdown { get; private set; } = new DropDown { IsDisplayFilterShown = true, IsSorted = true }; + + public DropDown CeitonEventsDropdown { get; private set; } = new DropDown { IsDisplayFilterShown = true, IsSorted = true }; + + public Button DeleteAllIntegrationsButton { get; private set; } = new Button("Delete All"); + + public Button DeleteSelectedPlasmaOrderButton { get; private set; } = new Button("Delete Selected Plasma Order(s)"); + + public Button DeleteSelectedPlasmaEventButton { get; private set; } = new Button("Delete Selected Plasma Event"); + + public Button DeleteAllPlasmaOrdersButton { get; private set; } = new Button("Delete All Plasma Orders"); + + public Button DeleteSelectedFeenixOrderButton { get; private set; } = new Button("Delete Selected Feenix Order"); + + public Button DeleteSelectedFeenixEventButton { get; private set; } = new Button("Delete Selected Feenix Event"); + + public Button DeleteAllFeenixOrdersButton { get; private set; } = new Button("Delete All Feenix Orders"); + + public Button DeleteSelectedEbuOrderButton { get; private set; } = new Button("Delete Selected EBU Order"); + + public Button DeleteSelectedEbuEventButton { get; private set; } = new Button("Delete Selected EBU Event"); + + public Button DeleteAllEbuOrdersButton { get; private set; } = new Button("Delete All EBU Orders"); + + public Button DeleteSelectedCeitonEventButton { get; private set; } = new Button("Delete Selected Ceiton Event"); + + public Button DeleteAllCeitonEventsButton { get; private set; } = new Button("Delete All Ceiton Events"); + + public Button ExitButton { get; private set; } = new Button("Exit"); + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..31273c8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("DeleteIntegrationOrders_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("DeleteIntegrationOrders_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("43EA67FA-96FC-4AF7-BD0F-02890D433E8E")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/Script.cs new file mode 100644 index 0000000..d96669e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/Script.cs @@ -0,0 +1,309 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace DeleteIntegrationOrders_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net; + using Skyline.DataMiner.Net.Jobs; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.Advanced; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Net.Sections; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.Utils.YLE.Integrations; + + /// + /// DataMiner Script Class. + /// + public class Script : IDisposable + { + private Helpers helpers; + private InteractiveController app; + private IntegrationOrdersDialog integrationsDialog; + private ProgressDialog progressDialog; + private Engine engine; + private bool disposedValue; + + /// + /// The Script entry point. + /// Engine.ShowUI(); + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + try + { + this.engine = engine; + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.Timeout = TimeSpan.FromHours(10); + + helpers = new Helpers(engine, Scripts.DeleteIntegrationOrders); + + RunSafe(engine); + } + catch (ScriptAbortException) + { + throw; + } + catch (Exception e) + { + engine.Log("Run|Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + } + + private void RunSafe(Engine engine) + { + app = new InteractiveController(engine); + integrationsDialog = new IntegrationOrdersDialog(engine); + progressDialog = new ProgressDialog(engine); + + progressDialog.OkButton.Pressed += (sender, args) => + { + app.ShowDialog(integrationsDialog); + }; + + // Retrieve Integration Orders & Events + integrationsDialog.InitPlasmaOrders(GetIntegrationOrders(IntegrationType.Plasma)); + integrationsDialog.InitPlasmaEvents(GetIntegrationEvents(IntegrationType.Plasma)); + + integrationsDialog.InitFeenixOrders(GetIntegrationOrders(IntegrationType.Feenix)); + integrationsDialog.InitFeenixEvents(GetIntegrationEvents(IntegrationType.Feenix)); + + integrationsDialog.InitEbuOrders(GetIntegrationOrders(IntegrationType.Eurovision)); + integrationsDialog.InitEbuOrders(GetIntegrationEvents(IntegrationType.Eurovision)); + + integrationsDialog.InitCeitonEvents(GetIntegrationEvents(IntegrationType.Ceiton)); + + integrationsDialog.ExitButton.Pressed += (sender, args) => engine.ExitSuccess("OK"); + + integrationsDialog.DeleteSelectedPlasmaOrderButton.Pressed += (sender, args) => DeleteIntegrationOrders(integrationsDialog.SelectedPlasmaOrders); + integrationsDialog.DeleteSelectedPlasmaEventButton.Pressed += (sender, args) => DeleteIntegrationEvents(integrationsDialog.SelectedPlasmaEvent); + integrationsDialog.DeleteAllPlasmaOrdersButton.Pressed += (sender, args) => DeleteIntegrationOrders(integrationsDialog.PlasmaOrders.ToArray()); + + integrationsDialog.DeleteSelectedFeenixOrderButton.Pressed += (sender, args) => DeleteIntegrationOrders(integrationsDialog.SelectedFeenixOrder); + integrationsDialog.DeleteSelectedFeenixEventButton.Pressed += (sender, args) => DeleteIntegrationEvents(integrationsDialog.SelectedFeenixEvent); + integrationsDialog.DeleteAllFeenixOrdersButton.Pressed += (sender, args) => DeleteIntegrationOrders(integrationsDialog.FeenixOrders.ToArray()); + + integrationsDialog.DeleteSelectedEbuOrderButton.Pressed += (sender, args) => DeleteIntegrationOrders(integrationsDialog.SelectedEbuOrder); + integrationsDialog.DeleteSelectedEbuEventButton.Pressed += (sender, args) => DeleteIntegrationEvents(integrationsDialog.SelectedEbuEvent); + integrationsDialog.DeleteAllEbuOrdersButton.Pressed += (sender, args) => DeleteIntegrationOrders(integrationsDialog.EbuOrders.ToArray()); + + integrationsDialog.DeleteSelectedCeitonEventButton.Pressed += (sender, args) => DeleteIntegrationEvents(integrationsDialog.SelectedCeitonEvent); + integrationsDialog.DeleteAllCeitonEventsButton.Pressed += (sender, args) => DeleteIntegrationEvents(integrationsDialog.CeitonEvents.ToArray()); + + integrationsDialog.DeleteAllIntegrationsButton.Pressed += (sender, args) => + { + // Delete Orders + List orders = new List(integrationsDialog.PlasmaOrders); + orders.AddRange(integrationsDialog.FeenixOrders); + orders.AddRange(integrationsDialog.EbuOrders); + DeleteIntegrationOrders(orders.ToArray()); + }; + + // Define dialogs here + app.Run(integrationsDialog); + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong"); + if (app.IsRunning) app.ShowDialog(dialog); else app.Run(dialog); + } + + private List GetIntegrationOrders(IntegrationType type) + { + List orders = new List(); + foreach (var reservation in DataMinerInterface.ResourceManager.GetReservationInstancesByProperty(helpers, LiteOrder.PropertyNameIntegration, type.ToString())) + { + ServiceReservationInstance serviceInstance = reservation as ServiceReservationInstance; + if (serviceInstance != null && serviceInstance.ContributingResourceID == Guid.Empty) + { + orders.Add(new IntegrationOrder + { + Type = type, + ID = serviceInstance.ID, + Name = serviceInstance.Name, + Reservation = serviceInstance + }); + } + } + + return orders; + } + + private List GetIntegrationEvents(IntegrationType type) + { + List events = new List(); + + JobManagerHelper jobManager = new JobManagerHelper(m => engine.SendSLNetMessages(m)); + var sectionDefinitions = jobManager.SectionDefinitions.Read(SectionDefinitionExposers.Name.NotEqual(String.Empty)); + + // search for a section with a field named Status + var defaultSectionDefinition = sectionDefinitions.FirstOrDefault(x => x.GetAllFieldDescriptors().Any(y => y.Name.Equals("Integration", StringComparison.OrdinalIgnoreCase))) ?? throw new NotFoundException("Unable to find Integration section definition"); + var integrationField = defaultSectionDefinition.GetAllFieldDescriptors().FirstOrDefault(d => d.Name.Contains("Integration")) ?? throw new NotFoundException("Unable to find Integration field descriptor"); + + var filter = JobExposers.FieldValues.JobField(integrationField.ID).Equal(type.ToString()); + var jobs = jobManager.Jobs.Read(filter); + foreach (Job job in jobs) + { + jobManager.StitchJob(job); + events.Add(new IntegrationEvent { ID = job.ID.Id, Name = job.GetJobName(), Type = type, Job = job }); + } + + return events; + } + + private void DeleteIntegrationOrders(params ISrmObject[] srmObjects) + { + app.ShowDialog(progressDialog); + helpers.ProgressReported += (sender, args) => progressDialog.AddProgressLine(args.Progress); + + foreach (IntegrationOrder order in srmObjects.OfType()) + { + if (order == null) continue; + + helpers.ReportProgress("Deleting " + order.Name + "..."); + + List reservationInstancesToRemove = new List(); + List servicesToRemove = new List(); + foreach (var resourceUsage in order.Reservation.ResourcesInReservationInstance) + { + var resourceReservationInstance = DataMinerInterface.ResourceManager.GetReservationInstance(helpers, resourceUsage.GUID) as ServiceReservationInstance; + if (resourceReservationInstance == null) continue; + + reservationInstancesToRemove.Add(resourceReservationInstance); + servicesToRemove.Add(resourceReservationInstance.ServiceID); + } + + reservationInstancesToRemove.Add(order.Reservation); + + try + { + DataMinerInterface.ResourceManager.RemoveReservationInstances(helpers, reservationInstancesToRemove.ToArray()); + helpers.ReportProgress("Reservations were removed"); + + foreach (var serviceId in servicesToRemove) + { + engine.SendSLNetMessage(new SetDataMinerInfoMessage + { + Uia1 = new UIA(new[] { (uint)serviceId.DataMinerID, (uint)serviceId.SID }), + What = 74 + }); + + helpers.ReportProgress("Service " + serviceId.DataMinerID + "/" + serviceId.SID + " was removed"); + } + + helpers.ReportProgress(order.Name + "was deleted"); + } + catch (Exception e) + { + helpers.ReportProgress("Something went wrong when deleting: " + order.Name + "|" + e); + } + } + + progressDialog.Finish(); + app.ShowDialog(progressDialog); + } + + private void DeleteIntegrationEvents(params ISrmObject[] srmObjects) + { + app.ShowDialog(progressDialog); + helpers.ProgressReported += (sender, args) => progressDialog.AddProgressLine(args.Progress); + + JobManagerHelper jobManager = new JobManagerHelper(m => engine.SendSLNetMessages(m)); + foreach (IntegrationEvent eventInfo in srmObjects.OfType()) + { + try + { + helpers.ReportProgress("Deleting " + eventInfo.Name + "..."); + jobManager.Jobs.Delete(eventInfo.Job); + helpers.ReportProgress(eventInfo.Name + "was deleted"); + } + catch (Exception e) + { + helpers.ReportProgress("Something went wrong when deleting: " + eventInfo.Name + "|" + e); + } + } + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteIntegrationOrders_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder.xml new file mode 100644 index 0000000..2b850c3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder.xml @@ -0,0 +1,30 @@ + + DeleteNonLiveOrder + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/Customer UI + + + + + + + + + + ticketId + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/DeleteDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/DeleteDialog.cs new file mode 100644 index 0000000..f874179 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/DeleteDialog.cs @@ -0,0 +1,43 @@ +namespace DeleteNonLiveOrder_2 +{ + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport; + + public class DeleteDialog : Dialog + { + private readonly Label infoLabel = new Label(); + + public DeleteDialog(Engine engine, NonLiveOrder nonLiveOrder) : base(engine) + { + Title = "Delete Export"; + infoLabel.Text = "Are you sure you want to delete this Non-Live Order?"; + + YesButton = new Button("Yes") { Width = 150, Style = ButtonStyle.CallToAction }; + NoButton = new Button("No") { Width = 150 }; + + GenerateUI(); + } + + public Button YesButton + { + get; private set; + } + + public Button NoButton + { + get; private set; + } + + private void GenerateUI() + { + MinWidth = 800; + int row = 0; + + AddWidget(infoLabel, ++row, 0, 1, 2); + + AddWidget(YesButton, ++row, 0); + AddWidget(NoButton, row, 1); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/DeleteNonLiveOrder_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/DeleteNonLiveOrder_2.csproj new file mode 100644 index 0000000..fb6a9cd --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/DeleteNonLiveOrder_2.csproj @@ -0,0 +1,106 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {98F1FA3D-7B10-4178-A6A4-41F6958CCBE5} + Library + Properties + DeleteNonLiveOrder_2 + DeleteNonLiveOrder_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\DeleteNonLiveOrder_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\DeleteNonLiveOrder_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + 1.0.1.12 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6854ec6 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("DeleteNonLiveOrder_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("DeleteNonLiveOrder_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("C72A8ED8-6F39-4319-958C-5DFA804756FC")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/Script.cs new file mode 100644 index 0000000..70419db --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/Script.cs @@ -0,0 +1,183 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +03/02/2020 1.0.0.1 JVT, Skyline Initial version +**************************************************************************** +*/ + +namespace DeleteNonLiveOrder_2 +{ + using System; + using System.Threading.Tasks; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + public class Script : IDisposable + { + private Helpers helpers; + private InteractiveController app; + + private int ticketId; + private int dataminerId; + + private Task scriptTask; + private int timeOutResult; + private bool disposedValue; + + public void Run(Engine engine) + { + scriptTask = Task.Factory.StartNew(() => + { + try + { + //engine.ShowUI(); + helpers = new Helpers(engine, Scripts.DeleteNonLiveOrder); + + string[] dmaAndTicketId = engine.GetScriptParam("ticketId").Value.Split(new[] { '/' }); + + if (dmaAndTicketId.Length == 2) + { + ticketId = Int32.Parse(dmaAndTicketId[1]); + dataminerId = Int32.Parse(dmaAndTicketId[0]); + } + else + { + ticketId = -1; + dataminerId = -1; + } + + RunSafe(engine); + } + catch (ScriptAbortException) + { + throw; + } + catch (Exception e) + { + if (timeOutResult != -1) + { + engine.Log("Run|Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + } + }); + + timeOutResult = Task.WaitAny(new Task[] { scriptTask }, new TimeSpan(9, 59, 40)); + } + + private void RunSafe(Engine engine) + { + app = new InteractiveController(engine); + + NonLiveOrder nonLiveOrder = helpers.NonLiveOrderManager.GetNonLiveOrder(dataminerId, ticketId); + + Dialog dialog; + if (nonLiveOrder == null) + { + MessageDialog messageDialog = new MessageDialog(engine, String.Format("Unable to retrieve Non-Live Order with ID {0}/{1}", dataminerId, ticketId)) { Title = "Unable to retrieve Order" }; + messageDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Unable to remove Non-Live Order"); + dialog = messageDialog; + } + else + { + DeleteDialog deleteDialog = new DeleteDialog(engine, nonLiveOrder); + deleteDialog.YesButton.Pressed += DeleteDialog_YesButton_Pressed; + deleteDialog.NoButton.Pressed += (sender, args) => engine.ExitSuccess("Non-Live Order was not removed"); + dialog = deleteDialog; + } + + app.Run(dialog); + } + + private void DeleteDialog_YesButton_Pressed(object sender, EventArgs e) + { + if (!helpers.NonLiveOrderManager.DeleteNonLiveOrder(dataminerId, ticketId)) + { + MessageDialog messageDialog = new MessageDialog((Engine)helpers.Engine, "Unable to remove Non-Live Order.") { Title = "Removal failed" }; + messageDialog.OkButton.Pressed += (s, args) => helpers.Engine.ExitSuccess("Unable to remove Non-Live Order"); + app.ShowDialog(messageDialog); + } + else + { + helpers.Engine.ExitSuccess("The Non-Live Order was successfully removed."); + } + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong during the execution of the script"); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteNonLiveOrder_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource.xml new file mode 100644 index 0000000..3f9792b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource.xml @@ -0,0 +1,28 @@ + + + DeleteReservationsForCertainResource + Script 1.0.1.77 + Automation + SKYLINE2\GillesVH + FALSE + YLE/Tools + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/ConfirmDeleteDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/ConfirmDeleteDialog.cs new file mode 100644 index 0000000..07e0afe --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/ConfirmDeleteDialog.cs @@ -0,0 +1,36 @@ +namespace DeleteReservationsForCertainResource_1 +{ + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class ConfirmDeleteDialog : Dialog + { + private readonly Label messageLabel = new Label("Are you sure that you want to delete the selected reservations?"); + + public ConfirmDeleteDialog(Engine engine) : base(engine) + { + this.Title = "Confirm Delete"; + + YesButton = new Button("Yes") { Width = 200 }; + NoButton = new Button("No") { Width = 200 }; + + GenerateUi(); + } + + public Button YesButton { get; private set; } + + public Button NoButton { get; private set; } + + private void GenerateUi() + { + int row = -1; + + AddWidget(messageLabel, ++row, 0, 1, 2); + + AddWidget(new WhiteSpace(), new WidgetLayout(++row, 0)); + + AddWidget(YesButton, ++row, 0, 1, 1); + AddWidget(NoButton, row, 1, 1, 1); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/DeleteReservationsForCertainResource_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/DeleteReservationsForCertainResource_1.csproj new file mode 100644 index 0000000..7d103d1 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/DeleteReservationsForCertainResource_1.csproj @@ -0,0 +1,97 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {30536342-FF9E-4B4E-8679-55DDF1583BCE} + Library + Properties + DeleteReservationsForCertainResource_1 + DeleteReservationsForCertainResource_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\DeleteReservationsForCertainResource_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\DeleteReservationsForCertainResource_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + 1.0.1.12 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/DeleteReservationsFromResourceDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/DeleteReservationsFromResourceDialog.cs new file mode 100644 index 0000000..1fc0626 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/DeleteReservationsFromResourceDialog.cs @@ -0,0 +1,223 @@ +namespace DeleteReservationsForCertainResource_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.Library.Solutions.SRM.Helpers; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + + public class DeleteReservationsFromResourceDialog : Dialog + { + private Resource[] currentFoundResourcesForSpecificPool; + private readonly ResourcePool[] resourcePools; + + private readonly Engine engine; + private readonly ResourceManagerHelper resourceManagerHelper; + + private readonly Label selectResourcePoolLabel = new Label("Select Resource Pool:"); + private readonly Label selectResourceLabel = new Label("Select Resource:"); + private readonly Label startTimeLabel = new Label("Start Time:"); + private readonly Label endTimeLabel = new Label("End Time:"); + private readonly Label linkedReservationsLabel = new Label("Linked Reservations:") { IsVisible = false }; + + public DeleteReservationsFromResourceDialog(Engine engine) : base(engine) + { + this.engine = engine; + + resourceManagerHelper = new ResourceManagerHelperExtended(); + resourceManagerHelper.RequestResponseEvent += (s, e) => e.responseMessage = Skyline.DataMiner.Automation.Engine.SLNet.SendSingleResponseMessage(e.requestMessage); + + resourcePools = resourceManagerHelper.GetResourcePools(); + + InitializeWidgets(); + GetSpecificResourcesBasedOnSelectedResourcePool(); + GenerateUi(); + } + + public DropDown ResourcePoolDropDown { get; private set; } + + public DropDown ResourcesDropDown { get; private set; } + + public DateTimePicker StartTimeDateTimePicker { get; private set; } + + public DateTimePicker EndTimeDateTimePicker { get; private set; } + + public CheckBoxList LinkedReservationsCheckBoxList { get; private set; } + + public Button DeleteSelectedReservationsButton { get; private set; } + + public List CurrentFoundReservationInstances { get; private set; } + + public Resource CurrentSelectedResource => currentFoundResourcesForSpecificPool.Single(r => r.Name == ResourcesDropDown.Selected); + + public void RemoveSelectedReservationInstances() + { + try + { + var reservationsThatAreChecked = LinkedReservationsCheckBoxList.Checked.ToList(); + var reservationsToDelete = CurrentFoundReservationInstances.Where(r => r != null && reservationsThatAreChecked.Contains(r.Name)).ToArray(); + + resourceManagerHelper.RemoveReservationInstances(reservationsToDelete); + } + catch (Exception ex) + { + engine.Log($"{nameof(DeleteReservationsFromResourceDialog)} | {nameof(GetSpecificResourcesBasedOnSelectedResourcePool)}| Something went wrong durin removal of the selected reservation instances" + ex.Message); + } + } + + private void InitializeWidgets() + { + this.Title = "Release or Delete Reservation"; + + ResourcePoolDropDown = new DropDown(); + ResourcePoolDropDown.Options = resourcePools?.Select(r => r.Name).OrderBy(n => n); + ResourcePoolDropDown.Selected = ResourcePoolDropDown.Options.First(); + + ResourcesDropDown = new DropDown(); + + StartTimeDateTimePicker = new DateTimePicker(DateTime.Now) { IsEnabled = false }; + EndTimeDateTimePicker = new DateTimePicker(DateTime.Now.AddMinutes(30)) { IsEnabled = false }; + + LinkedReservationsCheckBoxList = new CheckBoxList { IsVisible = false, IsSorted = true }; + + DeleteSelectedReservationsButton = new Button("Delete Reservations") { Width = 150, IsEnabled = false }; + + // Handlers + ResourcePoolDropDown.Changed += ResourcePoolDropDown_Changed; + ResourcesDropDown.Changed += ResourcesDropDown_Changed; + LinkedReservationsCheckBoxList.Changed += LinkedReservationsCheckBoxList_Changed; + StartTimeDateTimePicker.Changed += StartTimeDateTimePicker_Changed; + EndTimeDateTimePicker.Changed += EndTimeDateTimePicker_Changed; + } + + private void InitializeReservationCheckBoxList(bool showReservationSelection) + { + LinkedReservationsCheckBoxList.SetOptions(CurrentFoundReservationInstances.Select(r => r?.Name)); + LinkedReservationsCheckBoxList.IsVisible = showReservationSelection; + linkedReservationsLabel.IsVisible = showReservationSelection; + } + + private void GenerateUi() + { + int row = -1; + + AddWidget(selectResourcePoolLabel, ++row, 0); + AddWidget(ResourcePoolDropDown, row, 1); + + AddWidget(selectResourceLabel, ++row, 0); + AddWidget(ResourcesDropDown, row, 1); + + AddWidget(startTimeLabel, ++row, 0); + AddWidget(StartTimeDateTimePicker, row, 1); + + AddWidget(endTimeLabel, ++row, 0); + AddWidget(EndTimeDateTimePicker, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(linkedReservationsLabel, ++row, 0, HorizontalAlignment.Left, VerticalAlignment.Top); + AddWidget(LinkedReservationsCheckBoxList, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(DeleteSelectedReservationsButton, row + 1, 0); + + SetColumnWidth(0, 150); + SetColumnWidth(1, 300); + } + + private void GetSpecificResourcesBasedOnSelectedResourcePool() + { + try + { + var selectedResourcePool = resourcePools?.Single(r => r.Name == ResourcePoolDropDown.Selected); + if (selectedResourcePool == null) throw new InvalidOperationException(nameof(selectedResourcePool)); + + currentFoundResourcesForSpecificPool = resourceManagerHelper.GetResources(ResourceExposers.PoolGUIDs.Contains(selectedResourcePool.GUID)); + + if (currentFoundResourcesForSpecificPool.Any()) + { + engine.Log($"{nameof(DeleteReservationsFromResourceDialog)} | {nameof(GetSpecificResourcesBasedOnSelectedResourcePool)} | Currently found resources {String.Join(";", currentFoundResourcesForSpecificPool.Select(r => r.ToString()))} for resource pool: {selectedResourcePool}"); + + ResourcesDropDown.Options = currentFoundResourcesForSpecificPool?.Select(r => r.Name).OrderBy(x => x); + ResourcesDropDown.Selected = ResourcesDropDown.Options?.First(); + + UpdateWidgetVisibility(); + GetReservationInstancesWithSpecificResourceAndTimeSpan(CurrentSelectedResource, StartTimeDateTimePicker.DateTime, EndTimeDateTimePicker.DateTime); + } + } + catch (Exception ex) + { + engine.Log($"{nameof(DeleteReservationsFromResourceDialog)} | {nameof(GetSpecificResourcesBasedOnSelectedResourcePool)} |Failure while getting resources: " + ex.Message); + } + } + + private void GetReservationInstancesWithSpecificResourceAndTimeSpan(Resource resource, DateTime start, DateTime end) + { + if (resource == null) throw new ArgumentNullException(nameof(resource)); + if (resource.ID == Guid.Empty) throw new ArgumentException("Resource ID is empty GUID", nameof(resource)); + + if (end < start) throw new ArgumentException("End date is before start date", nameof(end)); + + var resourceFilter = ReservationInstanceExposers.ResourceIDsInReservationInstance.Contains(resource.ID); + var startFilter = ReservationInstanceExposers.Start.LessThanOrEqual(end); + var endFilter = ReservationInstanceExposers.End.GreaterThanOrEqual(start); + + CurrentFoundReservationInstances = resourceManagerHelper.GetReservationInstances(new ANDFilterElement(resourceFilter, startFilter, endFilter)).ToList(); + + if (CurrentFoundReservationInstances != null && CurrentFoundReservationInstances.Any()) + { + engine.Log($"{nameof(DeleteReservationsFromResourceDialog)} | {nameof(GetReservationInstancesWithSpecificResourceAndTimeSpan)} | Currently found reservation instances based on resource selection and timing {String.Join(";", CurrentFoundReservationInstances)}, Timing Start = {start}, Timing End = {end}, Resource name = {resource.Name}"); + + InitializeReservationCheckBoxList(CurrentFoundReservationInstances.Any()); + } + } + + private void ResourcePoolDropDown_Changed(object sender, DropDown.DropDownChangedEventArgs e) + { + GetSpecificResourcesBasedOnSelectedResourcePool(); + } + + private void ResourcesDropDown_Changed(object sender, DropDown.DropDownChangedEventArgs e) + { + GetReservationInstancesWithSpecificResourceAndTimeSpan(CurrentSelectedResource, StartTimeDateTimePicker.DateTime, EndTimeDateTimePicker.DateTime); + } + + private void EndTimeDateTimePicker_Changed(object sender, DateTimePicker.DateTimePickerChangedEventArgs e) + { + if (EndTimeDateTimePicker.DateTime <= StartTimeDateTimePicker.DateTime) + { + StartTimeDateTimePicker.DateTime = EndTimeDateTimePicker.DateTime.AddMinutes(-30); + } + + GetReservationInstancesWithSpecificResourceAndTimeSpan(CurrentSelectedResource, StartTimeDateTimePicker.DateTime, e.DateTime); + } + + private void StartTimeDateTimePicker_Changed(object sender, DateTimePicker.DateTimePickerChangedEventArgs e) + { + if (StartTimeDateTimePicker.DateTime >= EndTimeDateTimePicker.DateTime) + { + EndTimeDateTimePicker.DateTime = StartTimeDateTimePicker.DateTime.AddMinutes(30); + } + + GetReservationInstancesWithSpecificResourceAndTimeSpan(CurrentSelectedResource, e.DateTime, EndTimeDateTimePicker.DateTime); + } + + private void LinkedReservationsCheckBoxList_Changed(object sender, CheckBoxList.CheckBoxListChangedEventArgs e) + { + UpdateWidgetVisibility(); + } + + private void UpdateWidgetVisibility() + { + StartTimeDateTimePicker.IsEnabled = !String.IsNullOrEmpty(ResourcesDropDown.Selected); + EndTimeDateTimePicker.IsEnabled = StartTimeDateTimePicker.IsEnabled; + + DeleteSelectedReservationsButton.IsEnabled = LinkedReservationsCheckBoxList.Checked.Any(); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1169a63 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("DeleteReservationsForCertainResource_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("DeleteReservationsForCertainResource_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("38428D11-BAA0-41E1-ABD6-8435EFBF8638")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/Script.cs new file mode 100644 index 0000000..40c6681 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/Script.cs @@ -0,0 +1,147 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + + + +//--------------------------------- +// DeleteReservationsForCertainResource_1.cs +//--------------------------------- + +namespace DeleteReservationsForCertainResource_1 +{ + using System; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + /// + /// DataMiner Script Class. + /// + public class Script + { + private Engine engine; + private InteractiveController app; + + private DeleteReservationsFromResourceDialog handleResourcesFromReservationsDialog; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + try + { + RunSafe(engine); + } + catch (ScriptAbortException) + { + throw; + } + catch (Exception e) + { + ShowExceptionDialog(engine, e); + } + } + + private void RunSafe(Engine engine) + { + // engine.ShowUI() + engine.Timeout = TimeSpan.FromHours(10); + this.engine = engine; + + app = new InteractiveController(engine); + + handleResourcesFromReservationsDialog = new DeleteReservationsFromResourceDialog(engine); + handleResourcesFromReservationsDialog.DeleteSelectedReservationsButton.Pressed += DeleteSelectedReservationsButton_Pressed; + app.Run(handleResourcesFromReservationsDialog); + } + + private void DeleteSelectedReservationsButton_Pressed(object sender, EventArgs e) + { + ConfirmDeleteDialog confirmDeleteDialog = new ConfirmDeleteDialog(engine); + confirmDeleteDialog.NoButton.Pressed += (o, args) => app.ShowDialog(handleResourcesFromReservationsDialog); + confirmDeleteDialog.YesButton.Pressed += (o, args) => DeleteReservations(); + + app.ShowDialog(confirmDeleteDialog); + } + + private void DeleteReservations() + { + handleResourcesFromReservationsDialog.RemoveSelectedReservationInstances(); + + ShowMessageDialog(engine, "Removing the selected reservation instance(s) succeeded", "Removing Selected Reservation(s)"); + } + + private void ShowMessageDialog(Engine engine, string message, string title) + { + MessageDialog dialog = new MessageDialog(engine, message) { Title = title }; + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess(message); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitFail("Something went wrong during the handling of reservation deletion"); + if (!app.IsRunning) app.Run(dialog); + else app.ShowDialog(dialog); + } + } +} +//--------------------------------- +// ConfirmDeleteDialog.cs +//--------------------------------- + +//--------------------------------- +// DeleteReservationsFromResourceDialog.cs +//--------------------------------- \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteReservationsForCertainResource_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations.xml new file mode 100644 index 0000000..3c686fc --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations.xml @@ -0,0 +1,28 @@ + + + DeleteUnusedReservations + Script 1.0.1.77 + Automation + SKYLINE2\GillesVH + FALSE + YLE/Tools + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/ConfirmDeleteDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/ConfirmDeleteDialog.cs new file mode 100644 index 0000000..789a021 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/ConfirmDeleteDialog.cs @@ -0,0 +1,36 @@ +namespace DeleteUnusedReservations_1 +{ + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class ConfirmDeleteDialog : Dialog + { + private readonly Label messageLabel = new Label("Are you sure that you want to delete the selected reservations?"); + + public ConfirmDeleteDialog(Engine engine) : base(engine) + { + this.Title = "Confirm Delete"; + + YesButton = new Button("Yes") { Width = 200 }; + NoButton = new Button("No") { Width = 200 }; + + GenerateUi(); + } + + public Button YesButton { get; private set; } + + public Button NoButton { get; private set; } + + private void GenerateUi() + { + int row = -1; + + AddWidget(messageLabel, ++row, 0, 1, 2); + + AddWidget(new WhiteSpace(), new WidgetLayout(++row, 0)); + + AddWidget(YesButton, ++row, 0, 1, 1); + AddWidget(NoButton, row, 1, 1, 1); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/DeleteUnusedReservationsDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/DeleteUnusedReservationsDialog.cs new file mode 100644 index 0000000..09cccf3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/DeleteUnusedReservationsDialog.cs @@ -0,0 +1,257 @@ +namespace DeleteUnusedReservations_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Service = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.LiveUserTasks; + + public class DeleteUnusedReservationsDialog : Dialog, IDisposable + { + private readonly Engine engine; + private readonly Helpers helpers; + + private readonly Label startTimeLabel = new Label("Start Time:"); + private readonly Label endTimeLabel = new Label("End Time:"); + private readonly Label linkedReservationsLabel = new Label("Linked Reservations:") { IsVisible = false }; + private bool disposedValue; + private const string OrderReferencesPropertyName = "OrderIds"; + + public DeleteUnusedReservationsDialog(Engine engine, Helpers helpers) : base(engine) + { + this.engine = engine; + this.helpers = helpers; + + InitializeWidgets(); + GetReservationInstancesForSpecificTimeSpan(StartTimeDateTimePicker.DateTime, EndTimeDateTimePicker.DateTime); + GenerateUi(); + } + + public DateTimePicker StartTimeDateTimePicker { get; private set; } + + public DateTimePicker EndTimeDateTimePicker { get; private set; } + + public CheckBoxList LinkedReservationsCheckBoxList { get; private set; } + + public Button DeleteSelectedReservationsButton { get; private set; } + + private List CurrentFoundReservationInstances { get; set; } + + public List ReservationsToRemove { get; private set; } = new List(); + + private void InitializeWidgets() + { + this.Title = "Delete Unused Reservations"; + + StartTimeDateTimePicker = new DateTimePicker(DateTime.Now); + EndTimeDateTimePicker = new DateTimePicker(DateTime.Now.AddMinutes(30)); + + LinkedReservationsCheckBoxList = new CheckBoxList { IsVisible = false, IsSorted = true }; + + DeleteSelectedReservationsButton = new Button("Delete Reservations") { Width = 150, IsEnabled = false }; + + // Handlers + LinkedReservationsCheckBoxList.Changed += LinkedReservationsCheckBoxList_Changed; + StartTimeDateTimePicker.Changed += StartTimeDateTimePicker_Changed; + EndTimeDateTimePicker.Changed += EndTimeDateTimePicker_Changed; + } + + private void InitializeReservationCheckBoxList(bool showReservationSelection) + { + LinkedReservationsCheckBoxList.SetOptions(ReservationsToRemove.Select(x => x.Name)); + LinkedReservationsCheckBoxList.IsVisible = showReservationSelection; + linkedReservationsLabel.IsVisible = showReservationSelection; + } + + private void GenerateUi() + { + int row = -1; + + AddWidget(startTimeLabel, ++row, 0); + AddWidget(StartTimeDateTimePicker, row, 1); + + AddWidget(endTimeLabel, ++row, 0); + AddWidget(EndTimeDateTimePicker, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(linkedReservationsLabel, ++row, 0, HorizontalAlignment.Left, VerticalAlignment.Top); + AddWidget(LinkedReservationsCheckBoxList, row, 1); + + AddWidget(new WhiteSpace(), ++row, 0); + + AddWidget(DeleteSelectedReservationsButton, row + 1, 0); + + SetColumnWidth(0, 150); + SetColumnWidth(1, 300); + } + + private void GetReservationInstancesForSpecificTimeSpan(DateTime start, DateTime end) + { + if (end < start) throw new ArgumentException("End date is before start date", nameof(end)); + + try + { + var startFilter = ReservationInstanceExposers.Start.LessThanOrEqual(end); + var endFilter = ReservationInstanceExposers.End.GreaterThanOrEqual(start); + + CurrentFoundReservationInstances = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, new ANDFilterElement(startFilter, endFilter)).ToList(); + + List ConvertedServiceReservations = new List(); + foreach (var reservationInstance in CurrentFoundReservationInstances) + { + if (reservationInstance != null) ConvertedServiceReservations.Add(FromReservationInstance(reservationInstance)); + } + + // filter out order reservation instances + ConvertedServiceReservations = ConvertedServiceReservations.Where(c => c != null && c.OrderReferences.Any()).ToList(); + + HandleReservationsToDelete(ConvertedServiceReservations); + InitializeReservationCheckBoxList(ReservationsToRemove.Any()); + } + catch (Exception ex) + { + engine.Log("GetReservationInstancesForSpecificTimeSpan|Something went wrong while converting into service contributings " + ex.Message); + } + } + + private Service FromReservationInstance(ReservationInstance reservationInstance) + { + if (reservationInstance == null) throw new ArgumentNullException(nameof(reservationInstance)); + + var booking = reservationInstance.GetBookingData(); + + var service = new DisplayedService(booking.Description) + { + UserTasks = new List(), + Id = reservationInstance.ID, + }; + + TimeSpan preRoll = reservationInstance.GetPreRoll(); + TimeSpan postRoll = reservationInstance.GetPostRoll(); + + DateTime convertedStartTime = reservationInstance.Start.FromReservation().Truncate(TimeSpan.FromSeconds(1)).Truncate(TimeSpan.FromMilliseconds(1)); + DateTime convertedEndTime = reservationInstance.End.FromReservation().Truncate(TimeSpan.FromSeconds(1)).Truncate(TimeSpan.FromMilliseconds(1)); + + service.Start = convertedStartTime.Add(preRoll); + service.End = convertedEndTime.Subtract(postRoll); + + service.IsBooked = true; + + service.OrderReferences = GetOrderReferences(reservationInstance); + + return service; + } + + private static HashSet GetOrderReferences(ReservationInstance reservation) + { + var orders = new HashSet(); + + var orderIdsProperty = reservation.Properties.FirstOrDefault(p => String.Equals(p.Key, OrderReferencesPropertyName, StringComparison.InvariantCultureIgnoreCase)); + if (orderIdsProperty.Equals(default(KeyValuePair)) || Convert.ToString(orderIdsProperty.Value) == String.Empty) + { + return orders; + } + + try + { + var orderIds = Convert.ToString(orderIdsProperty.Value).Split(';').Select(id => Guid.Parse(id)); + foreach (var orderId in orderIds) + { + if (orderId == Guid.Empty) continue; + + orders.Add(orderId); + } + } + catch (Exception) + { + return orders; + } + + return orders; + } + + private void HandleReservationsToDelete(List ConvertedServiceReservations) + { + bool allOrderReferencesOfReservationDontExist; + foreach (var reservation in ConvertedServiceReservations) + { + allOrderReferencesOfReservationDontExist = true; + foreach (var linkedOrderId in reservation.OrderReferences) + { + if (DataMinerInterface.ResourceManager.GetReservationInstance(helpers, linkedOrderId) != null) + { + allOrderReferencesOfReservationDontExist = false; + break; + } + } + + if (allOrderReferencesOfReservationDontExist) + { + var reservationToDelete = CurrentFoundReservationInstances.Single(r => r.ID == reservation.Id); + ReservationsToRemove.Add(reservationToDelete); + } + } + } + + private void EndTimeDateTimePicker_Changed(object sender, DateTimePicker.DateTimePickerChangedEventArgs e) + { + if (EndTimeDateTimePicker.DateTime <= StartTimeDateTimePicker.DateTime) + { + StartTimeDateTimePicker.DateTime = EndTimeDateTimePicker.DateTime.AddMinutes(-30); + } + + GetReservationInstancesForSpecificTimeSpan(StartTimeDateTimePicker.DateTime, e.DateTime); + } + + private void StartTimeDateTimePicker_Changed(object sender, DateTimePicker.DateTimePickerChangedEventArgs e) + { + if (StartTimeDateTimePicker.DateTime >= EndTimeDateTimePicker.DateTime) + { + EndTimeDateTimePicker.DateTime = StartTimeDateTimePicker.DateTime.AddMinutes(30); + } + + GetReservationInstancesForSpecificTimeSpan(e.DateTime, EndTimeDateTimePicker.DateTime); + } + + private void LinkedReservationsCheckBoxList_Changed(object sender, CheckBoxList.CheckBoxListChangedEventArgs e) + { + UpdateWidgetVisibility(); + } + + private void UpdateWidgetVisibility() + { + DeleteSelectedReservationsButton.IsEnabled = LinkedReservationsCheckBoxList.Checked.Any(); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/DeleteUnusedReservations_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/DeleteUnusedReservations_1.csproj new file mode 100644 index 0000000..48629bd --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/DeleteUnusedReservations_1.csproj @@ -0,0 +1,102 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {1A694B8E-C1E4-4BC2-A5F3-F658EB733EDB} + Library + Properties + DeleteUnusedReservations_1 + DeleteUnusedReservations_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\DeleteUnusedReservations_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\DeleteUnusedReservations_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c4a5385 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("DeleteUnusedReservations_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("DeleteUnusedReservations_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("DF34DEF7-1B07-4821-A250-9117DD9C4914")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/Script.cs new file mode 100644 index 0000000..93c933a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/Script.cs @@ -0,0 +1,173 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace DeleteUnusedReservations_1 +{ + using System; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + /// + /// DataMiner Script Class. + /// + public class Script : IDisposable + { + private Engine engine; + private InteractiveController app; + private Helpers helpers; + + DeleteUnusedReservationsDialog deleteUnusedReservationsDialog; + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + try + { + RunSafe(engine); + } + catch (ScriptAbortException) + { + throw; + } + catch (Exception e) + { + ShowExceptionDialog(engine, e); + } + } + + private void RunSafe(Engine engine) + { + // engine.ShowUI(); + engine.Timeout = TimeSpan.FromHours(10); + this.engine = engine; + this.helpers = new Helpers(engine, Scripts.DeleteUnusedReservations); + + app = new InteractiveController(engine); + + deleteUnusedReservationsDialog = new DeleteUnusedReservationsDialog(engine, helpers); + deleteUnusedReservationsDialog.DeleteSelectedReservationsButton.Pressed += DeleteSelectedReservationsButton_Pressed; + app.Run(deleteUnusedReservationsDialog); + } + + private void DeleteSelectedReservationsButton_Pressed(object sender, EventArgs e) + { + ConfirmDeleteDialog confirmDeleteDialog = new ConfirmDeleteDialog(engine); + confirmDeleteDialog.NoButton.Pressed += (o, args) => app.ShowDialog(deleteUnusedReservationsDialog); + confirmDeleteDialog.YesButton.Pressed += (o, args) => DeleteReservations(); + + app.ShowDialog(confirmDeleteDialog); + } + + private void DeleteReservations() + { + try + { + if (deleteUnusedReservationsDialog.ReservationsToRemove.Any()) + { + var reservationsThatAreChecked = deleteUnusedReservationsDialog.LinkedReservationsCheckBoxList.Checked; + helpers.ResourceManager.RemoveReservationInstances(deleteUnusedReservationsDialog.ReservationsToRemove.Where(r => reservationsThatAreChecked.Contains(r.Name)).ToArray()); + } + + ShowMessageDialog(engine, "Reservations are successfully deleted", "Deleting Reservations"); + } + catch (Exception ex) + { + engine.Log("DeleteReservations| " + ex.Message); + } + } + + private void ShowMessageDialog(Engine engine, string message, string title) + { + MessageDialog dialog = new MessageDialog(engine, message) { Title = title }; + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess(message); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitFail("Something went wrong during the handling of reservation deletion"); + if (!app.IsRunning) app.Run(dialog); + else app.ShowDialog(dialog); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + deleteUnusedReservationsDialog.Dispose(); + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DeleteUnusedReservations_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Directory.Build.props b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Directory.Build.props new file mode 100644 index 0000000..c98bd4f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Directory.Build.props @@ -0,0 +1,5 @@ + + + x86 + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll new file mode 100644 index 0000000..45c098c Binary files /dev/null and b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll differ diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/Microsoft.VisualStudio.TestPlatform.TestFramework.dll b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/Microsoft.VisualStudio.TestPlatform.TestFramework.dll new file mode 100644 index 0000000..e566389 Binary files /dev/null and b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/Microsoft.VisualStudio.TestPlatform.TestFramework.dll differ diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/Moq.dll b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/Moq.dll new file mode 100644 index 0000000..431affb Binary files /dev/null and b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/Moq.dll differ diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/SLMediationSnippets.dll b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/SLMediationSnippets.dll new file mode 100644 index 0000000..d2fcb69 Binary files /dev/null and b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/SLMediationSnippets.dll differ diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/SLSRMLibrary.dll b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/SLSRMLibrary.dll new file mode 100644 index 0000000..eacd337 Binary files /dev/null and b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/SLSRMLibrary.dll differ diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/readme.txt b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/readme.txt new file mode 100644 index 0000000..a3170b3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Dlls/readme.txt @@ -0,0 +1 @@ +This folder contains DLL files that should be placed under the ProtocolScripts folder of DataMiner for this solution to work correctly. \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Documentation/LOF_MVC.drawio b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Documentation/LOF_MVC.drawio new file mode 100644 index 0000000..28d7831 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Documentation/LOF_MVC.drawio @@ -0,0 +1 @@ +5Vxbc6M2FP41PGaHu8ljYme3ndm2O5tpu/sog2xrg5Er5NjJr68EEjdhjBPA2JnJTOAIBDqfvnOTsGZN1/svBGxWf+AAhpqpB3vNmmmmadimqfE/PXhJJZ4zSQVLggJxUS54RK9QCHUh3aIAxqULKcYhRZuy0MdRBH1akgFC8K582QKH5aduwBIqgkcfhKr0XxTQlZAaup43/AbRckXl+ETDGsiLhSBegQDvCiLrQbOmBGOaHq33Uxhy5Um9pPd9PtCavRiBEW1zw3c3wNh7ev0zMJfBHZn/vvv+68a2026eQbgVIxZvS1+kCgjeRgHkvRiadb9bIQofN8DnrTsGOpOt6DoUzQscUYGiwYZ4H1OCn+AUh5gwUQAXYBtSfh0KQymNcMSuvw9AvMoe8wwJRQyGuxAtIyajmD9IHbNQA78c7gsioYMvEK8hJS/sEtFqeQIPMSEnEp9dDq9tCdmqgKzpCiEQU2qZ9Z1rnR0IxZ8AghxEQecwYLNQnAr15DDo7AwTusJLHIHwK+aqSZT2C1L6IrQPthSXoYF7RH8Ujn+KrvjxbF88eZEnERvej+LJT3k/P8lvSs7kXcUpMKlArZnWwvOh7ytTg7XMPcd29CaYY7wlPmxQpTQRgCwhbbjOSa/jam6cNASGgKLnsjHofgLcDjMBMjg/OUVA9SOAlohZRTdmuqZ33NIyiR+COEa+FH9GoXx2/5Dao4JU2qXcrv5FAkg0003M35wfLfnRlOmT4DDkbdU5EIbMzcHjRhfEm9T3LdCeA9Ul5dpbVsMpW1bbdBTLmvnNomXNhN2j4H0kyxoA6C1qYXZ9D84X76Kh3ZKG7qhoqIY3j5A8IzbSsxDxPQi9nYjORA1xhiai1UjEnHMPufR8Dq/Ks5ID7N3hORfJNGOgGKbG1MrjelN7znC0LZSTUUHpHIpdLjs+cYyyWXTPbxVdRaeDUKI++jjVKpa5PGQs4raklTcqWrmHY5HLjjeqxDL18zPLuc54Q7jRYrDxPg81uUgqZTXVgQomRgnNHNwRVsDaAmqMC1A15vgHwR2v2CMCY/6iz0wV/ICuAOWvQCC3JiAKQgaxqc/5yzblcGygX8EchhULKurLPuud3aUWntcoCFLrAGP0CuZJfxyiDUb8hVjnzr3mzGpgV0FsnMyKwc1WNcRTteLCQZ0hvtE/6Z5llIyxOGsNo+j8Gx9doWdjUu7VsMtd4MUiZvOtOg+yd3z71JgcikarCfwj0xTC0aWHqd7t+Mpok0HM7TnLW15LszmuKrNpD+MHRYYhE4kT6psnes72Sw0HIqExzplxuVpPsacHS6K9W9Rh8pOqRR1BPfRWAaEhdGHDpGW9nrCq3j7AqcOykuMfDXDeXavOluePYWP15ux0BRuxreUDwaKm9OdGRV1QTROEDwRK1Y6dnyumWtMq2jF9uwkATdK3dS2FzpCUEUxB4tSs2Y3tnATMyfmY5VZYNOkNCDVLknvxDiXQPtjGSYNItFnQJwEbGU59wzSp+CDT6QsmS/Ut3yBZYLKOUykKQG3EdcysCQPWs01rjM678DqVOK0m83WHNG9W86r1ufdlqXst+6wUy7rS0XTHMrUx5TuWGjnITIcrsASv+98Wy4abOFHtHbvAMDf7vFFmR3/HiY/zQ+Q/cfqCgNchZzCmKBIs1rPUSp9vKeWi9MlsJOnD067UadY2w1Jz5OPRTi7tgLN2JVLMjGkxKDFrWOv1xtrmtZ8+qlUDsM9sy75xVajke3fOvsrywF0N+e4F5fQppyj7/8BDoOunoFeXFwxLQTUcvUZOtt0TaY1rq5ZV99FHF5wUCzM8/s5zQLWsyBwlp2xQImucecokERH54rVT1dDrVneG5Wrzxr3et0pob15aH4DhbXcaWePaH2GpdZluGF4tKhziMKN4sioPP4bHNYy6JYVBaWw3f0Q24h1PA9C49equPi4aq2t1nQbPwhFHyUmVymLp79qo6zpjy1fti/02on/mSkIeZ+64ik62WujtJe1Vg+tZPY2v3SNXaX3+HFjOSHXjWmmbYtkI5xFUKYdKUqIQxXzi4EWpNe4GtLbf6vcK2giyIbsucq4o+Lp/EMHQDZU6tb+IYBi9odCifnTlKBiOSoWhUVDDzzftuRjB4mRx1f+2o426lllxOZbKm0GXK+1Od5V9ENQMvSYBGBQ2R40V37bh7KMgZtz2ti+Anea/yJR+wZD/rpX18D8= \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Documentation/readme.txt b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Documentation/readme.txt new file mode 100644 index 0000000..11d30e6 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Documentation/readme.txt @@ -0,0 +1 @@ +This folder can be used to add documentation related to this solution. \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder.xml new file mode 100644 index 0000000..67cabcd --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder.xml @@ -0,0 +1,30 @@ + + DuplicateNonLiveOrder + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/Customer UI + + + + + + + + + + ticketId + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/DuplicateNonLiveOrder_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/DuplicateNonLiveOrder_2.csproj new file mode 100644 index 0000000..90202f2 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/DuplicateNonLiveOrder_2.csproj @@ -0,0 +1,102 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {A90B225A-0F85-416B-9CE8-EEBDF2929BC4} + Library + Properties + DuplicateNonLiveOrder_2 + DuplicateNonLiveOrder_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\DuplicateNonLiveOrder_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\DuplicateNonLiveOrder_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..40b934d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("DuplicateNonLiveOrder_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("DuplicateNonLiveOrder_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("8BDB95C6-5911-44CB-A4E9-55351B8F9372")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/Script.cs new file mode 100644 index 0000000..6717f13 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/Script.cs @@ -0,0 +1,203 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +03/02/2020 1.0.0.1 JVT, Skyline Initial version +**************************************************************************** +*/ + +namespace DuplicateNonLiveOrder_2 +{ + using System; + using System.Threading.Tasks; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.LoadingScreens; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.NonLive; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + + internal class Script : IDisposable + { + /* + This script is a copy of AddOrUpdateNonLiveOrder with minimal changes to allow for duplication + */ + + private InteractiveController app; + + private LoadNonLiveOrderFormDialog loadNonLiveOrderFormDialog; + private MainDialog nonLiveOrderForm; + private NonLiveRejectionDialog rejectionDialog; + private Helpers helpers; + + private int timeOutResult; + private bool disposedValue; + + public void Run(Engine engine) + { + var scriptTask = Task.Factory.StartNew(() => + { + try + { + Initialize(engine); + + loadNonLiveOrderFormDialog = new LoadNonLiveOrderFormDialog(helpers, LoadNonLiveOrderFormDialog.ScriptAction.Duplicate); + + if (loadNonLiveOrderFormDialog.Execute()) ShowNonLiveOrderForm(); + else app.Run(loadNonLiveOrderFormDialog); + } + catch (ScriptAbortException) + { + throw; + } + catch (Exception e) + { + if (timeOutResult != -1) + { + engine.Log("Run|Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + } + }); + + timeOutResult = Task.WaitAny(new[] { scriptTask }, new TimeSpan(9, 59, 40)); + } + + private void Initialize(Engine engine) + { + engine.Timeout = TimeSpan.FromHours(10); + //engine.ShowUI(); + + helpers = new Helpers(engine, Scripts.DuplicateNonLiveOrder); + app = new InteractiveController(engine); + } + + private void ShowNonLiveOrderForm() + { + nonLiveOrderForm = loadNonLiveOrderFormDialog.NonLiveOrderFormDialog; + nonLiveOrderForm.BookOrSaveFinished += NonLiveOrderForm_BookOrSaveFinished; + nonLiveOrderForm.RejectOrderButton.Pressed += Dialog_RejectOrderButton_Pressed; + + if(app.IsRunning) app.ShowDialog(nonLiveOrderForm); + else app.Run(nonLiveOrderForm); + } + + private void NonLiveOrderForm_BookOrSaveFinished(object sender, Library_1.EventArguments.StringEventArgs e) + { + ShowMessageDialog(e.Value, "Duplicate Non-Live Order finished"); + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog exceptionDialog = new ExceptionDialog(engine, exception); + exceptionDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong during the creation of the new Order."); + + if (app.IsRunning) app.ShowDialog(exceptionDialog); + else app.Run(exceptionDialog); + } + + private void ShowMessageDialog(string message, string title) + { + MessageDialog dialog = new MessageDialog(helpers.Engine, message) { Title = title }; + dialog.OkButton.Pressed += (sender, args) => helpers.Engine.ExitSuccess(message); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + private void Dialog_RejectOrderButton_Pressed(object sender, EventArgs e) + { + rejectionDialog = new NonLiveRejectionDialog(helpers.Engine); + rejectionDialog.CancelButton.Pressed += RejectionDialog_CancelButton_Pressed; + rejectionDialog.RejectButton.Pressed += RejectionDialog_RejectButton_Pressed; + + app.ShowDialog(rejectionDialog); + } + + private void RejectionDialog_RejectButton_Pressed(object sender, EventArgs e) + { + if (!rejectionDialog.IsValid()) + { + return; + } + + rejectionDialog.UpdateNonLiveOrder(nonLiveOrderForm.NonLiveOrder); + + helpers.NonLiveOrderManager.SetNonLiveOrderToChangeRequested(nonLiveOrderForm.NonLiveOrder, loadNonLiveOrderFormDialog.UserInfo.User); + + ShowMessageDialog("Order successfully rejected", "Reject Non Live Order"); + } + + private void RejectionDialog_CancelButton_Pressed(object sender, EventArgs e) + { + app.ShowDialog(nonLiveOrderForm); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/DuplicateNonLiveOrder_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate.xml new file mode 100644 index 0000000..30081f8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate.xml @@ -0,0 +1,28 @@ + + + EditOrderTemplate + Script 1.0.1.77 + Automation + SKYLINE2\VictorSC + FALSE + YLE/SRM + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/EditOrderTemplateDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/EditOrderTemplateDialog.cs new file mode 100644 index 0000000..9b7592a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/EditOrderTemplateDialog.cs @@ -0,0 +1,109 @@ +namespace EditOrderTemplate_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Core.DataMinerSystem.Common; + + public class EditOrderTemplateDialog : Dialog + { + private readonly Helpers helpers; + private readonly Element contractManagerElement; + + private readonly Dictionary templatePrimaryKeysPerTemplateName; + + private readonly Label templateLabel = new Label("Template"); + private readonly DropDown templateDropDown; + + private readonly TextBox templateTextBox = new TextBox(string.Empty) { IsMultiline = true, Height = 500, Width = 1000 }; + private readonly Button confirmButton = new Button("Confirm"); + private readonly Label validationLabel = new Label(string.Empty); + + public EditOrderTemplateDialog(Helpers helpers) : base(helpers.Engine) + { + Title = "Edit Order Template"; + + this.helpers = helpers; + this.contractManagerElement = helpers.Engine.FindElementsByProtocol("Finnish Broadcasting Company Contract Manager").FirstOrDefault() ?? throw new ElementNotFoundException("Could not find Contract Manager Element"); + + + templatePrimaryKeysPerTemplateName = helpers.ContractManager.GetAllOrderTemplateNamesAndIds(); + + var orderTemplateNames = new List { Constants.None }.Concat(templatePrimaryKeysPerTemplateName.Keys.OrderBy(name => name)); + + templateDropDown = new DropDown(orderTemplateNames, Constants.None) { IsDisplayFilterShown = true }; + templateDropDown.Changed += TemplateDropDown_Changed; + + confirmButton.Pressed += ConfirmButtonOnPressed; + + GenerateUi(); + } + + private void ConfirmButtonOnPressed(object sender, EventArgs e) + { + var newTemplate = OrderTemplate.Deserialize(templateTextBox.Text); + + if (!templateTextBox.IsEnabled || newTemplate == null) + { + validationLabel.Text = "Provide a valid template"; + } + else + { + contractManagerElement.SetParameterByPrimaryKey(15004, templatePrimaryKeysPerTemplateName[templateDropDown.Selected], templateTextBox.Text); + + validationLabel.Text = "Update complete"; + } + } + + private void TemplateDropDown_Changed(object sender, DropDown.DropDownChangedEventArgs e) + { + if (e.Selected == Constants.None) + { + templateTextBox.Text = string.Empty; + templateTextBox.IsEnabled = false; + } + else if (helpers.ContractManager.TryGetOrderTemplate(e.Selected, out var template)) + { + try + { + templateTextBox.Text = JsonConvert.SerializeObject(template, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize }); + templateTextBox.IsEnabled = true; + + } + catch (Exception ex) + { + templateTextBox.Text = ex.ToString(); + templateTextBox.IsEnabled = false; + } + } + else + { + templateTextBox.Text = "Error while getting template"; + templateTextBox.IsEnabled = false; + } + } + + private void GenerateUi() + { + int row = -1; + + AddWidget(templateLabel, new WidgetLayout(++row, 0)); + AddWidget(templateDropDown, new WidgetLayout(row, 1)); + + AddWidget(templateTextBox, new WidgetLayout(++row, 0, 1, 2)); + + AddWidget(confirmButton, new WidgetLayout(++row, 0)); + AddWidget(validationLabel, new WidgetLayout(row + 1, 0)); + + SetColumnWidth(0, 500); + SetColumnWidth(1, 500); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/EditOrderTemplate_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/EditOrderTemplate_1.csproj new file mode 100644 index 0000000..4102039 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/EditOrderTemplate_1.csproj @@ -0,0 +1,104 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {3BCB9CBC-A3EE-4493-B605-6EBE559F295A} + Library + Properties + EditOrderTemplate_1 + EditOrderTemplate_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\EditOrderTemplate_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\EditOrderTemplate_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + C:\Skyline DataMiner\Files\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + 13.0.3 + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3bd5569 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("EditOrderTemplate_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("EditOrderTemplate_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("3327FB06-0781-4289-BD1C-1B074C1CD2C0")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/Script.cs new file mode 100644 index 0000000..e5b2aaf --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/Script.cs @@ -0,0 +1,85 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace EditOrderTemplate_1 +{ + using System; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + /// + /// DataMiner Script Class. + /// + class Script + { + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + //engine.ShowUI(); + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.SetFlag(RunTimeFlags.NoCheckingSets); + engine.Timeout = TimeSpan.FromHours(10); + + var app = new InteractiveController(engine); + + var helpers = new Helpers(engine, Scripts.EditOrderTemplate); + + var dialog = new EditOrderTemplateDialog(helpers); + + app.Run(dialog); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/app.config new file mode 100644 index 0000000..21fb24c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/EditOrderTemplate_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand.xml new file mode 100644 index 0000000..a24ef6c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand.xml @@ -0,0 +1,31 @@ + + + ExecuteFeenixStopCommand + Script 1.0.1.77 + Automation + YLEAD\VANHEGI8 + FALSE + YLE/Integrations + + + + + + + + + + ID + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/ConfirmDialog.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/ConfirmDialog.cs new file mode 100644 index 0000000..76a2af6 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/ConfirmDialog.cs @@ -0,0 +1,26 @@ +namespace ExecuteFeenixStopCommand_2 +{ + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + + public class ConfirmDialog : Dialog + { + private readonly Label messageLabel = new Label("This will cause a stop notification to be sent to Feenix. Are you sure you want to continue?"); + + public ConfirmDialog(Engine engine) : base(engine) + { + YesButton = new Button("Yes") { Style = ButtonStyle.CallToAction }; + NoButton = new Button("No"); + + int row = -1; + AddWidget(messageLabel, ++row, 0, 1, 2); + + AddWidget(YesButton, ++row, 0, HorizontalAlignment.Left); + AddWidget(NoButton, row, 1, HorizontalAlignment.Right); + } + + public Button YesButton { get; private set; } + + public Button NoButton { get; private set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/ExecuteFeenixStopCommand_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/ExecuteFeenixStopCommand_2.csproj new file mode 100644 index 0000000..bf0f006 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/ExecuteFeenixStopCommand_2.csproj @@ -0,0 +1,107 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {DA97B418-6D04-4FA2-8214-6FE3113E02C7} + Library + Properties + ExecuteFeenixStopCommand_2 + ExecuteFeenixStopCommand_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ExecuteFeenixStopCommand_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ExecuteFeenixStopCommand_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + 1.0.1.12 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/FeenixElementException.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/FeenixElementException.cs new file mode 100644 index 0000000..deb56a5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/FeenixElementException.cs @@ -0,0 +1,30 @@ +namespace ExecuteFeenixStopCommand_2 +{ + using System; + using System.Runtime.Serialization; + + [Serializable] + public class FeenixElementException : Exception + { + public FeenixElementException(string message) : base(message) + { + } + + public FeenixElementException() : base("An error occurred with the Feenix Element") + { + } + + public FeenixElementException(string message, Exception inner) : base(message, inner) + { + } + + protected FeenixElementException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..307e8b3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ExecuteFeenixStopCommand_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ExecuteFeenixStopCommand_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("F1A311D4-C5FC-43F4-A94D-F08C3067BF21")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/Script.cs new file mode 100644 index 0000000..6c1a779 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/Script.cs @@ -0,0 +1,129 @@ +namespace ExecuteFeenixStopCommand_2 +{ + using System; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Feenix; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.YLE.Integrations.Feenix; + using ExceptionDialog = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Reports.ExceptionDialog; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + + /// + /// DataMiner Script Class. + /// + internal class Script : IDisposable + { + // Do not remove this + // Engine.ShowUI(); + + private InteractiveController app; + private Helpers helpers; + + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + engine.Timeout = TimeSpan.FromHours(10); + + app = new InteractiveController(engine); + helpers = new Helpers(engine, Scripts.ExecuteFeenixStopCommand); + + try + { + string liveStreamOrderId = engine.GetScriptParam("ID").Value; + if (!Guid.TryParse(liveStreamOrderId, out Guid orderGuid)) + { + var errorDialog = new MessageDialog(engine, "Error while parsing the order ID") { Title = "Show order details" }; + errorDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Error while parsing the order ID"); + app.Run(errorDialog); + return; + } + + OrderManager orderManager = new OrderManager(helpers); + LiteOrder order = orderManager.GetLiteOrder(orderGuid, true); + if (order == null) + { + var errorDialog = new MessageDialog(engine, "Unable to get the order") { Title = "Show order details" }; + errorDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Unable to get the order"); + app.Run(errorDialog); + return; + } + + string areenaId = order.YleId; + if (String.IsNullOrWhiteSpace(areenaId)) + { + var errorDialog = new MessageDialog(engine, "Areena ID couldn't be found inside this order") { Title = "Show order details" }; + errorDialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Areena ID couldn't be found inside this order"); + app.Run(errorDialog); + return; + } + else + { + OrderManagerElement orderManagerElement = new OrderManagerElement(helpers); + FeenixElement feenixManager = new FeenixElement(orderManagerElement.FeenixElement); + + ConfirmDialog confirmDialog = new ConfirmDialog(engine); + confirmDialog.NoButton.Pressed += (sender, args) => { engine.ExitSuccess(order.Id.ToString()); }; + confirmDialog.YesButton.Pressed += (sender, args) => + { + feenixManager.SendStopNotification(areenaId); + engine.ExitSuccess(order.Id.ToString()); + }; + + app.Run(confirmDialog); + } + } + catch (FeenixElementException f) + { + var errorDialog = new MessageDialog(engine, "Feenix element can not be found or is inactive") { Title = "Unable to show order details" }; + errorDialog.OkButton.Pressed += (sender, args) => engine.ExitFail("Feenix element can not be found or is inactive: " + f.Message); + app.Run(errorDialog); + } + catch (ScriptAbortException) + { + // Do nothing. + } + catch (Exception e) + { + engine.Log("Run|Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitFail("Something went wrong."); + + if (app.IsRunning) app.ShowDialog(dialog); + else app.Run(dialog); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExecuteFeenixStopCommand_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions.xml new file mode 100644 index 0000000..ee958cc --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions.xml @@ -0,0 +1,28 @@ + + + ExportProfileDefinitions + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/Tools + + + + + + + Action + + + FilePath + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/ExportProfileDefinitions_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/ExportProfileDefinitions_1.cs new file mode 100644 index 0000000..11e71e5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/ExportProfileDefinitions_1.cs @@ -0,0 +1,149 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Newtonsoft.Json; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.Library.Solutions.SRM; +using Skyline.DataMiner.Net.Profiles; + +/// +/// DataMiner Script Class. +/// +public class Script +{ + public static void Run(Engine engine) + { + var filePath = engine.GetScriptParam("FilePath").Value; + var directory = Path.GetDirectoryName(filePath); + if (!Directory.Exists(directory)) + { + engine.Log($"Directory {directory} does not exist!"); + return; + } + + var action = engine.GetScriptParam("Action").Value; + switch (action) + { + case "Clear": + Delete(); + break; + case "Import": + Import(filePath); + break; + case "ClearAndImport": + Delete(); + Import(filePath); + break; + case "Export": + Export(filePath); + break; + default: + engine.Log("Unsupported action: " + action); + return; + } + } + + private static void Import(string filePath) + { + var json = File.ReadAllText(filePath); + + var profileImportExport = ProfileImportExport.Deserialize(json); + + var profileParameters = profileImportExport.ProfileParameterXmls.Select(x => Parameter.FromXml(x)).ToArray(); + SrmManagers.ProfileHelper.ProfileParameters.AddOrUpdateBulk(profileParameters); + + var profileDefinitions = profileImportExport.ProfileDefinitionXmls.Select(x => ProfileDefinition.FromXml(x)).ToArray(); + SrmManagers.ProfileHelper.ProfileDefinitions.AddOrUpdateBulk(profileDefinitions); + } + + private static void Export(string filePath) + { + var allProfileParameters = SrmManagers.ProfileHelper.ProfileParameters.ReadAll().Select(p => p.ToXml()).ToList(); + var allProfileDefinitions = SrmManagers.ProfileHelper.ProfileDefinitions.ReadAll().Select(p => p.ToXml()).ToList(); + + var profileImportExport = new ProfileImportExport + { + ProfileParameterXmls = allProfileParameters, + ProfileDefinitionXmls = allProfileDefinitions + }; + + File.WriteAllText(filePath, profileImportExport.Serialize()); + } + + private static void Delete() + { + var allProfileDefinitions = SrmManagers.ProfileHelper.ProfileDefinitions.ReadAll().ToArray(); + SrmManagers.ProfileHelper.ProfileDefinitions.RemoveBulk(allProfileDefinitions); + + var allProfileParameters = SrmManagers.ProfileHelper.ProfileParameters.ReadAll().ToArray(); + SrmManagers.ProfileHelper.ProfileParameters.RemoveBulk(allProfileParameters); + } + + private sealed class ProfileImportExport + { + public List ProfileParameterXmls { get; set; } + + public List ProfileDefinitionXmls { get; set; } + + public static ProfileImportExport Deserialize(string json) + { + return JsonConvert.DeserializeObject(json); + } + + public string Serialize() + { + return JsonConvert.SerializeObject(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/ExportProfileDefinitions_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/ExportProfileDefinitions_1.csproj new file mode 100644 index 0000000..05d4d0e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/ExportProfileDefinitions_1.csproj @@ -0,0 +1,93 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {54742C48-894C-4B28-B0D6-BF4F6CE7E76B} + Library + Properties + ExportProfileDefinitions_1 + ExportProfileDefinitions_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ExportProfileDefinitions_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ExportProfileDefinitions_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + 13.0.3 + + + 10.3.5 + + + 7.0.1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a734380 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ExportProfileDefinitions_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ExportProfileDefinitions_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("36025BAD-C396-4D01-8A6F-88EE4BFF2B3D")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/app.config new file mode 100644 index 0000000..57e666a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportProfileDefinitions_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools.xml new file mode 100644 index 0000000..3220ffe --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools.xml @@ -0,0 +1,32 @@ + + + ExportResourcePools + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/Tools + + + + + + + + + + Action + + + FilePath + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/ExportResourcePools_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/ExportResourcePools_1.cs new file mode 100644 index 0000000..1cd787d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/ExportResourcePools_1.cs @@ -0,0 +1,146 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using Newtonsoft.Json; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.Library.Solutions.SRM; +using Skyline.DataMiner.Net.Messages; + +/// +/// DataMiner Script Class. +/// +public class Script +{ + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + var filePath = engine.GetScriptParam("FilePath").Value; + var directory = Path.GetDirectoryName(filePath); + if (!Directory.Exists(directory)) + { + engine.Log($"Directory {directory} does not exist!"); + return; + } + + var action = engine.GetScriptParam("Action").Value; + switch (action) + { + case "Clear": + Delete(); + break; + case "Import": + Import(filePath); + break; + case "ClearAndImport": + Delete(); + Import(filePath); + break; + case "Export": + Export(filePath); + break; + default: + engine.Log("Unsupported action: " + action); + return; + } + } + + private static void Delete() + { + var resourcePools = SrmManagers.ResourceManager.GetResourcePools(); + SrmManagers.ResourceManager.RemoveResourcePools(resourcePools); + } + + private static void Import(string filePath) + { + var json = File.ReadAllText(filePath); + + var resourcePoolImportExport = ResourcePoolImportExport.Deserialize(json); + + var resourcePools = resourcePoolImportExport.ResourcePools.Select(p => new ResourcePool(p.Key) { Name = p.Value }).ToArray(); + SrmManagers.ResourceManager.AddOrUpdateResourcePools(resourcePools); + } + + private static void Export(string filePath) + { + var resourcePools = SrmManagers.ResourceManager.GetResourcePools(); + + var resourcePoolImportExport = new ResourcePoolImportExport + { + ResourcePools = resourcePools.ToDictionary(p => p.ID, p => p.Name) + }; + + File.WriteAllText(filePath, resourcePoolImportExport.Serialize()); + } + + private sealed class ResourcePoolImportExport + { + public Dictionary ResourcePools { get; set; } + + public static ResourcePoolImportExport Deserialize(string json) + { + return JsonConvert.DeserializeObject(json); + } + + public string Serialize() + { + return JsonConvert.SerializeObject(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/ExportResourcePools_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/ExportResourcePools_1.csproj new file mode 100644 index 0000000..0f16d75 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/ExportResourcePools_1.csproj @@ -0,0 +1,92 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {60637559-5F48-44A1-B1F6-16AEA6B1BA01} + Library + Properties + ExportResourcePools_1 + ExportResourcePools_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ExportResourcePools_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ExportResourcePools_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + 13.0.3 + + + 10.3.5 + + + 7.0.1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a9e733e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ExportResourcePools_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ExportResourcePools_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("6DE81B69-0278-44D0-9B5E-2E1167C1D056")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportResourcePools_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions.xml new file mode 100644 index 0000000..12f8829 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions.xml @@ -0,0 +1,28 @@ + + + ExportServiceDefinitions + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/Tools + + + + + + + Action + + + FilePath + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/ExportServiceDefinitions_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/ExportServiceDefinitions_1.cs new file mode 100644 index 0000000..dbba3f1 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/ExportServiceDefinitions_1.cs @@ -0,0 +1,191 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +using System.IO; +using System.Linq; +using Newtonsoft.Json; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.Library; +using Skyline.DataMiner.Library.Solutions.SRM; +using Skyline.DataMiner.Net.Messages; +using Skyline.DataMiner.Net.Messages.SLDataGateway; +using Skyline.DataMiner.Net.ServiceManager.Objects; + +/// +/// DataMiner Script Class. +/// +public class Script +{ + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public static void Run(Engine engine) + { + var filePath = engine.GetScriptParam("FilePath").Value; + var directory = Path.GetDirectoryName(filePath); + if (!Directory.Exists(directory)) + { + engine.Log($"Directory {directory} does not exist!"); + return; + } + + var action = engine.GetScriptParam("Action").Value; + switch (action) + { + case "Clear": + Delete(); + break; + case "Import": + Import(engine, filePath); + break; + case "ClearAndImport": + Delete(); + Import(engine, filePath); + break; + case "Export": + Export(filePath); + break; + default: + engine.Log("Unsupported action: " + action); + return; + } + } + + private static void Delete() + { + var filter = ServiceDefinitionExposers.IsTemplate.Equal(true); + var templateServiceDefinitions = SrmManagers.ServiceManager.GetServiceDefinitions(filter); + + SrmManagers.ServiceManager.RemoveServiceDefinitions(out var error, templateServiceDefinitions.ToArray()); + } + + private static void Import(Engine engine, string filePath) + { + var json = File.ReadAllText(filePath); + + var serviceDefinitionImportExport = ServiceDefinitionImportExport.Deserialize(json); + + var serviceDefinitions = serviceDefinitionImportExport.ServiceDefinitionJsons.Select(s => JsonConvert.DeserializeObject(s)).ToArray(); + SrmManagers.ServiceManager.AddOrUpdateServiceDefinitions(serviceDefinitions, true); + + RegisterServiceDefinitionsProperties(engine, serviceDefinitions); + } + + private static void Export(string filePath) + { + var filter = ServiceDefinitionExposers.IsTemplate.Equal(true); + var templateServiceDefinitions = SrmManagers.ServiceManager.GetServiceDefinitions(filter); + + var serviceDefinitions = templateServiceDefinitions.Where(s => s.Name.StartsWith("_")); + var serviceDefinitionImportExport = new ServiceDefinitionImportExport + { + ServiceDefinitionJsons = serviceDefinitions.Select(s => JsonConvert.SerializeObject(s)).ToArray() + }; + + File.WriteAllText(filePath, serviceDefinitionImportExport.Serialize()); + } + + /// + /// Registers all Service Definition's Properties. + /// This includes Service Definition, Node and Interface Properties. + /// + private static void RegisterServiceDefinitionsProperties(Engine engine, ServiceDefinition[] serviceDefinitions) + { + var serviceDefinitionProperties = serviceDefinitions + .SelectMany(x => x.Properties) + .Select(x => new PropertyInfo { Name = x.Name, Value = "Service" }) + .ToList(); + + var serviceDefinitionNodeProperties = serviceDefinitions + .SelectMany(x => x.Diagram.Nodes.SelectMany(y => y.Properties)) + .Select(x => new PropertyInfo { Name = x.Name, Value = "ServiceDefinitionNode" }); + + var serviceDefinitionInterfaceProperties = serviceDefinitions + .SelectMany(x => x.Diagram.Nodes.SelectMany(y => y.InterfaceConfigurations.SelectMany(z => z.Properties))) + .Select(x => new PropertyInfo { Name = x.Name, Value = "ServiceDefinitionInterface" }); + + serviceDefinitionProperties.AddRange(serviceDefinitionNodeProperties); + serviceDefinitionProperties.AddRange(serviceDefinitionInterfaceProperties); + + var propertiesToAdd = serviceDefinitionProperties.DistinctBy(x => new { x.Name, x.Value }); + + var configuredProperties = DataMinerSystemInfo.GetRegisteredProperties().ToArray(); + + foreach (var property in propertiesToAdd) + { + if (configuredProperties.Any(y => y.Name == property.Name && y.Type == property.Value)) + { + continue; + } + + if (!DataMinerSystemInfo.RegisterPropertyConfig(property, property.Value)) + { + engine.GenerateInformation($"Property with name {property.Name} of type {property.Value} not added."); + } + } + } + + private sealed class ServiceDefinitionImportExport + { + public string[] ServiceDefinitionJsons { get; set; } + + public static ServiceDefinitionImportExport Deserialize(string json) + { + return JsonConvert.DeserializeObject(json); + } + + public string Serialize() + { + return JsonConvert.SerializeObject(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/ExportServiceDefinitions_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/ExportServiceDefinitions_1.csproj new file mode 100644 index 0000000..820c166 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/ExportServiceDefinitions_1.csproj @@ -0,0 +1,94 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {54B5632D-C113-4383-913E-2701501D951D} + Library + Properties + ExportServiceDefinitions_1 + ExportServiceDefinitions_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ExportServiceDefinitions_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ExportServiceDefinitions_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + False + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + 13.0.3 + + + 10.3.5 + + + 7.0.1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..591be3e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ExportServiceDefinitions_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ExportServiceDefinitions_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("65C7FFC1-BC6E-4017-9839-02541BD6FF17")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/app.config new file mode 100644 index 0000000..57e666a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportServiceDefinitions_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm.xml new file mode 100644 index 0000000..7945e40 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm.xml @@ -0,0 +1,26 @@ + + + ExportSrm + Script 1.0.1.77 + Automation + SKYLINE2\ThomasRE + FALSE + YLE/Tools + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/ExportSrm_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/ExportSrm_1.cs new file mode 100644 index 0000000..f41dedd --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/ExportSrm_1.cs @@ -0,0 +1,292 @@ +/* +**************************************************************************** +* Copyright (c) 2023, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2023 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +This script will run the Full Export for all active Booking Manager elements present on the DMA. +Run this script on the same agent as the one that hosts the Booking Managers to be able to create a package. +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using Newtonsoft.Json; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.Core.DataMinerSystem.Common; +using Skyline.DataMiner.Library.Automation; + +/// +/// DataMiner Script Class. +/// +public class Script +{ + private const string FullExportScriptName = "SRM_ExportFullConfiguration"; + private const string FullExportScript_InputData_Key = "Input Data"; + + private const string ResourceExportScriptName = "SRM_DiscoverResources"; + private const string ResourceExportScript_Operation_Key = "Operation"; + private const string ResourceExportScript_FilePath_Key = "File Path"; + private const string ResourceExportScript_InputData_Key = "Input Data"; + + private const string TempOutputFolder = @"C:\.SrmExportTemp"; + private const string OutputFolder = @"C:\Skyline_Data\SRMBackup"; + + private readonly Logger logger = new Logger(); + private readonly List> exportBookingManagerFailureResults = new List>(); + + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + engine.Timeout = TimeSpan.FromHours(3); + + try + { + string outputFolder = PrepareBackup(); + + List outputFiles = new List(); + outputFiles.AddRange(ExportBookingManagers(engine, outputFolder)); + outputFiles.Add(ExportResources(engine, outputFolder)); + + BuildPackage(outputFiles); + + RemoveTempFolder(); + + if (exportBookingManagerFailureResults.Any()) + { + SendEmail(engine); + } + } + catch (Exception e) + { + logger.Log(nameof(Run), $"Something went wrong: {e}"); + SendEmail(engine); + } + } + + private string PrepareBackup() + { + string backupFolder = Path.Combine(TempOutputFolder, $"SrmExport_{DateTime.Now.ToString("MM_dd_yyyy_HH_mm_ss")}"); + if (!Directory.Exists(backupFolder)) Directory.CreateDirectory(backupFolder); + return backupFolder; + } + + private IEnumerable ExportBookingManagers(Engine engine, string outputFolder) + { + IDms dms = Engine.SLNetRaw.GetDms(); + List outputFileLocations = new List(); + + var bookingManagers = dms.GetElements().Where(x => x.State == ElementState.Active && x.Protocol.Name.Equals("Skyline Booking Manager")).ToList(); + + foreach (var bookingManager in bookingManagers) + { + logger.Log(nameof(ExportBookingManagers), $"Exporting {bookingManager.Name}..."); + + Skyline.DataMiner.Library.Solutions.SRM.Model.ExportFullConfiguration.OutputData output; + + output = ExportBookingManager(engine, bookingManager.Name); + + var localDmaInfo = engine.GetLocalDataMinerInfo(); + if (!localDmaInfo.AgentName.Equals(output.AgentName)) + { + // Unable to copy the export files as they are not accessible from this agent + logger.Log(nameof(ExportBookingManagers), $"Unable to copy export files as this script is run on a different agent than the one hosting Booking Manager {bookingManager.Name}"); + continue; + } + + logger.Log(nameof(ExportBookingManagers), $"Export succeeded, file {output.ExportedFilePath} on Agent {output.AgentName}"); + + logger.Log(nameof(ExportBookingManagers), $"Moving export for {bookingManager.Name}..."); + + string fileName = Path.GetFileName(output.ExportedFilePath).Replace("Booking Manager", String.Empty).Split('_')[0].Trim() + Path.GetExtension(output.ExportedFilePath); + string newFilePath = Path.Combine(outputFolder, fileName); + File.Move(output.ExportedFilePath, newFilePath); + + outputFileLocations.Add(newFilePath); + + logger.Log(nameof(ExportBookingManagers), $"Moving export succeeded"); + } + + return outputFileLocations; + } + + private Skyline.DataMiner.Library.Solutions.SRM.Model.ExportFullConfiguration.OutputData ExportBookingManager(IEngine engine, string bookingManagerName) + { + var inputData = new Skyline.DataMiner.Library.Solutions.SRM.Model.ExportFullConfiguration.InputData { BookingManagerName = bookingManagerName, IsInteractive = false }; + + var fullExportScript = engine.PrepareSubScript(FullExportScriptName); + fullExportScript.Synchronous = true; + fullExportScript.SelectScriptParam(FullExportScript_InputData_Key, JsonConvert.SerializeObject(inputData)); + fullExportScript.StartScript(); + + var scriptResults = fullExportScript.GetScriptResult(); + bool succeeded = scriptResults.TryGetValue("Result", out var result); + if (!succeeded) + { + exportBookingManagerFailureResults.Add(scriptResults); + + foreach (var exceptionResult in scriptResults) + { + logger.Log(nameof(ExportBookingManagers), $"SRM full export configuration script returned error message: {exceptionResult.Key}/{exceptionResult.Value}"); + } + + return new Skyline.DataMiner.Library.Solutions.SRM.Model.ExportFullConfiguration.OutputData(); + } + + return JsonConvert.DeserializeObject(result); + } + + private string ExportResources(IEngine engine, string outputFolder) + { + logger.Log(nameof(ExportBookingManagers), $"Exporting Resources..."); + + var inputData = new Skyline.DataMiner.Library.Solutions.SRM.Model.DiscoverResources.InputData { ForceUpdate = false, IsSilent = true }; + string outputFile = Path.Combine(outputFolder, "resources.xlsx"); + + var fullExportScript = engine.PrepareSubScript(ResourceExportScriptName); + fullExportScript.Synchronous = true; + fullExportScript.SelectScriptParam(ResourceExportScript_Operation_Key, "Export"); + fullExportScript.SelectScriptParam(ResourceExportScript_FilePath_Key, outputFile); + fullExportScript.SelectScriptParam(ResourceExportScript_InputData_Key, JsonConvert.SerializeObject(inputData)); + fullExportScript.StartScript(); + + logger.Log(nameof(ExportBookingManagers), $"Exporting Resources succeeded"); + + return outputFile; + } + + private void BuildPackage(IEnumerable files) + { + logger.Log(nameof(ExportBookingManagers), $"Building package..."); + + var zipFiles = files.Where(x => !String.IsNullOrWhiteSpace(x) && Path.GetExtension(x).Equals(".zip", StringComparison.InvariantCultureIgnoreCase)).ToList(); + var otherFiles = files.Where(x => !zipFiles.Contains(x)).ToList(); + + string fileName = $"SrmExport_{DateTime.Now.ToString("MM_dd_yyyy_HH_mm_ss")}.zip"; + string tempFilePath = Path.Combine(TempOutputFolder, fileName); + using (var archive = ZipFile.Open(tempFilePath, ZipArchiveMode.Create)) + { + // Merge zip files + foreach (var zipFile in zipFiles) + { + var zipArchive = ZipFile.OpenRead(zipFile); + + foreach (var zipArchiveEntry in zipArchive.Entries) + { + var fileEntry = archive.CreateEntry($"{Path.GetFileNameWithoutExtension(zipFile)}/" + zipArchiveEntry.FullName); + using (var streamWriter = new StreamWriter(fileEntry.Open())) + { + using (StreamReader reader = new StreamReader(zipArchiveEntry.Open())) + { + streamWriter.Write(reader.ReadToEnd()); + } + } + } + + zipArchive.Dispose(); + } + + // Add additional files + foreach (var otherFile in otherFiles) + { + archive.CreateEntryFromFile(otherFile, Path.GetFileName(otherFile)); + } + } + + // Move zipped archive to backup folder + string backupFilePath = Path.Combine(OutputFolder, fileName); + if (!Directory.Exists(OutputFolder)) Directory.CreateDirectory(OutputFolder); + File.Move(tempFilePath, backupFilePath); + + logger.Log(nameof(ExportBookingManagers), $"Building package succeeded"); + } + + private void RemoveTempFolder() + { + logger.Log("Removing temporary folder..."); + Directory.Delete(TempOutputFolder, true); + logger.Log("Removing temporary folder succeeded"); + } + + private void SendEmail(Engine engine) + { + var localDmaInfo = engine.GetLocalDataMinerInfo(); + engine.SendEmail(new EmailOptions + { + Title = $"Scheduled SRM Backup from {localDmaInfo.Name} failed", + TO = "squad.deploy-the.pioneers@skyline.be", + Message = logger.Logging + }); + } +} + +public class Logger +{ + private readonly StringBuilder logBuilder = new StringBuilder(); + + public string Logging => logBuilder.ToString(); + + public void Log(string message) + { + logBuilder.AppendLine($"{DateTime.Now.ToString("MM_dd_yyyy_HH_mm_ss")}|{message}"); + } + + public void Log(string method, string message) + { + logBuilder.AppendLine($"{DateTime.Now.ToString("MM_dd_yyyy_HH_mm_ss")}|{method}|{message}"); + } + + public void Log(string className, string method, string message) + { + logBuilder.AppendLine($"{DateTime.Now.ToString("MM_dd_yyyy_HH_mm_ss")}|{className}|{method}|{message}"); + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/ExportSrm_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/ExportSrm_1.csproj new file mode 100644 index 0000000..d6357ec --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/ExportSrm_1.csproj @@ -0,0 +1,82 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {E6720C0D-274D-4AEF-A45E-897EBDCE0911} + Library + Properties + ExportSrm_1 + ExportSrm_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ExportSrm_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ExportSrm_1.xml + + + None + + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + 1.1.0.5 + + + 10.3.5 + + + 7.0.1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9376336 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ExportSrm_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ExportSrm_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("017F63FD-8FAD-4A92-954F-014F0990CA8B")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ExportSrm_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval.xml new file mode 100644 index 0000000..fc8de76 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval.xml @@ -0,0 +1,35 @@ + + + FileRetrieval + Script 1.0.1.77 + Automation + SKYLINE2\ThomasRE + FALSE + YLE/Tools + + + + + + + + + + path + + + isSubscript + + + download + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/FileRetrieval_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/FileRetrieval_1.cs new file mode 100644 index 0000000..7557d90 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/FileRetrieval_1.cs @@ -0,0 +1,296 @@ +/* +**************************************************************************** +* Copyright (c) 2023, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2023 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace FileRetrieval_1 +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.IO.Compression; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.Core.DataMinerSystem.Automation; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Utils.InteractiveAutomationScript; + using Skyline.DataMiner.Utils.InteractiveAutomationScript.Components; + + public class Script + { + private const string FileRetrieval_ScriptName = "FileRetrieval"; + + private const string Path_ScriptInputParam = "path"; + private const string Subscript_ScriptInputParam = "isSubscript"; + private const string Download_ScriptInputParam = "download"; + + private const string FileContent_ScriptOutputParam = "fileInfo"; + + private const string LocalTempFolderPath = @"C:\Skyline DataMiner\Documents\.Temp"; + private const string RemoteTempFolderPath = @"\Documents\.Temp"; + + private InteractiveController app; + private string filePath; + private bool isSubscript; + private bool download; + + /// + /// The Script entry point. + /// Engine.ShowUI(); + /// + /// Link with SLScripting process. + public void Run(IEngine engine) + { + try + { + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.Timeout = TimeSpan.FromHours(10); + GetScriptParams(engine); + + RunSafe(engine); + } + catch (ScriptAbortException) + { + throw; + } + catch (Exception e) + { + engine.Log("Run|Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + } + + private void GetScriptParams(IEngine engine) + { + filePath = engine.GetScriptParam(Path_ScriptInputParam).Value; + isSubscript = Convert.ToBoolean(engine.GetScriptParam(Subscript_ScriptInputParam).Value); + download = Convert.ToBoolean(engine.GetScriptParam(Download_ScriptInputParam).Value); + } + + private void RunSafe(IEngine engine) + { + CleanLocalTempFolder(engine); + + List retrievedFiles = new List { GetLocalFile() }; + if (isSubscript) + { + OutputRetrievedFiles(engine, retrievedFiles); + return; + } + else + { + retrievedFiles.AddRange(GetRemoteFiles(engine)); + } + + if (download) + { + DownloadRetrievedFiles(engine, retrievedFiles); + } + else + { + OutputRetrievedFiles(engine, retrievedFiles); + } + } + + private void DownloadRetrievedFiles(IEngine engine, IEnumerable retrievedFiles) + { + // Write contents to temporary folder + if (!Directory.Exists(LocalTempFolderPath)) Directory.CreateDirectory(LocalTempFolderPath); + + string tempDirToZip = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + if (!Directory.Exists(tempDirToZip)) Directory.CreateDirectory(tempDirToZip); + + List tempFilePaths = new List(); + foreach (var file in retrievedFiles) + { + if (String.IsNullOrWhiteSpace(file.Content)) continue; + + string tempFilePath = Path.Combine(tempDirToZip, $"{file.Agent}_{Path.GetFileName(filePath)}"); + File.WriteAllText(tempFilePath, file.Content); + tempFilePaths.Add(tempFilePath); + } + + if (!tempFilePaths.Any()) + { + engine.Log($"Unable to retrieve {filePath} from any agent"); + return; + } + + // Zip retrieved file to Skyline DataMiner\Documents (= accessible through IIS) + string zipArchiveName = $"{Path.GetFileNameWithoutExtension(filePath)}.zip"; + string localZipArchivePath = Path.Combine(LocalTempFolderPath, zipArchiveName); + if (File.Exists(localZipArchivePath)) File.Delete(localZipArchivePath); + ZipFile.CreateFromDirectory(tempDirToZip, localZipArchivePath); + + // Remove temp files + try + { + foreach (var tempFilePath in tempFilePaths) + { + File.Delete(tempFilePath); + } + } + catch (Exception e) + { + engine.Log($"Unable to remove temporary files due to: {e}"); + } + + // Download zipped file + app = new InteractiveController(engine); + Dialog dialog = new DownloadDialog(engine, Path.Combine(RemoteTempFolderPath, zipArchiveName)); + app.Run(dialog); + } + + private static void OutputRetrievedFiles(IEngine engine, IEnumerable retrievedFiles) + { + var serializedOutput = JsonConvert.SerializeObject(retrievedFiles); + engine.AddOrUpdateScriptOutput(FileContent_ScriptOutputParam, serializedOutput); + engine.ExitSuccess("Files retrieved"); + } + + private void ShowExceptionDialog(IEngine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitFail("Something went wrong during the creation of the new event."); + if (app.IsRunning) app.ShowDialog(dialog); else app.Run(dialog); + } + + private RetrievedFile GetLocalFile() + { + var file = new RetrievedFile + { + Agent = Engine.SLNetRaw.ServerDetails.AgentName + }; + + if (!File.Exists(filePath)) return file; + + file.Content = File.ReadAllText(filePath); + return file; + } + + private List GetRemoteFiles(IEngine engine) + { + List files = new List(); + + var thisAgentId = Engine.SLNetRaw.ServerDetails.AgentID; + var dms = engine.GetDms(); + + var otherAgents = dms.GetAgents().Where(x => x.Id != thisAgentId); + foreach (var otherAgent in otherAgents) + { + var executeScriptMessage = new ExecuteScriptMessage + { + ScriptName = FileRetrieval_ScriptName, + DataMinerID = otherAgent.Id, + HostingDataMinerID = otherAgent.Id, + Options = new SA(new[] + { + "DEFER:FALSE", + $"PARAMETERBYNAME:{Path_ScriptInputParam}:{filePath}", + $"PARAMETERBYNAME:{Subscript_ScriptInputParam}:true", + $"PARAMETERBYNAME:{Download_ScriptInputParam}:false", + }) + }; + + try + { + var response = (ExecuteScriptResponseMessage)engine.SendSLNetSingleResponseMessage(executeScriptMessage); + if (response.ScriptOutput.TryGetValue(FileContent_ScriptOutputParam, out string output) && !String.IsNullOrWhiteSpace(output)) + { + files.AddRange(JsonConvert.DeserializeObject>(output)); + } + } + catch (Exception e) + { + engine.Log($"Unable to retrieve file {filePath} from agent {otherAgent.Name} due to {e}"); + } + } + + return files; + } + + private static void CleanLocalTempFolder(IEngine engine) + { + try + { + DateTime now = DateTime.Now; + var filesToRemove = Directory.EnumerateFiles(LocalTempFolderPath).Where(x => now.Subtract(File.GetLastWriteTime(x)) > TimeSpan.FromMinutes(5)).ToList(); + foreach (var file in filesToRemove) File.Delete(file); + } + catch (Exception e) + { + engine.Log($"Unable to clean local temp folder due to: {e}"); + } + } + } + + public class DownloadDialog : Dialog + { + private readonly DownloadButton downloadButton = new DownloadButton(); + + public DownloadDialog(IEngine engine, string remoteFilePath) : base(engine) + { + downloadButton.RemoteFilePath = remoteFilePath; + downloadButton.DownloadedFileName = Path.GetFileName(remoteFilePath); + downloadButton.StartDownloadImmediately = true; + downloadButton.DownloadStarted += (s, e) => engine.ExitSuccess("Files downloaded"); + + AddWidget(new Label("Download will start immediately"), 0, 0); + AddWidget(downloadButton, 1, 0); + } + } + + public class RetrievedFile + { + public string Agent { get; set; } + + public string Content { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/FileRetrieval_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/FileRetrieval_1.csproj new file mode 100644 index 0000000..d51ce4f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/FileRetrieval_1.csproj @@ -0,0 +1,81 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {56BC6E17-FC0B-4AB5-BFB2-B92344E707FA} + Library + Properties + FileRetrieval_1 + FileRetrieval_1 + v4.6.2 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\FileRetrieval_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\FileRetrieval_1.xml + + + None + + + + + + + + + + + + + + 1.1.1.2 + + + 10.3.5 + + + 7.0.1 + + + 1.1.118 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..848402d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("FileRetrieval_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("FileRetrieval_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("DA55302C-2F46-407A-8C8B-95EFCD2CA246")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/stylecop.json new file mode 100644 index 0000000..b2d519d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FileRetrieval_1/stylecop.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "indentation": { + "useTabs": true, + "tabSize": 4 + }, + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/FinnishBroadcastingCompany_CustomerUI_Launcher_2.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/FinnishBroadcastingCompany_CustomerUI_Launcher_2.cs new file mode 100644 index 0000000..888d300 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/FinnishBroadcastingCompany_CustomerUI_Launcher_2.cs @@ -0,0 +1,12086 @@ +// --- auto-generated code --- do not modify --- + +/* +{{StartPackageInfo}} + + + + Class Library + 1.2.0.10 + + + + + + YLE + 1.0.0.3 + + + + +{{EndPackageInfo}} +*/ + +namespace Skyline.DataMiner +{ + namespace Library.Common.Attributes + { + /// + /// This attribute indicates a DLL is required. + /// + [System.AttributeUsage(System.AttributeTargets.All, AllowMultiple = true)] + public sealed class DllImportAttribute : System.Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// The name of the DLL to be imported. + public DllImportAttribute(string dllImport) + { + DllImport = dllImport; + } + + /// + /// Gets the name of the DLL to be imported. + /// + public string DllImport + { + get; + private set; + } + } + } + + namespace DeveloperCommunityLibrary.YLE + { + public class ProgressReporter + { + public event System.EventHandler ProgressLogging; + public void LogMethodStart(string nameOfClass, string nameOfMethod, string nameOfObject = null) + { + LogProgress(nameOfClass, nameOfMethod, "Start", nameOfObject); + } + + public void LogMethodCompleted(string nameOfClass, string nameOfMethod, string nameOfObject = null, System.Diagnostics.Stopwatch stopwatch = null) + { + LogProgress(nameOfClass, nameOfMethod, $"Completed{(stopwatch != null ? $" [{stopwatch.Elapsed}]" : string.Empty)}", nameOfObject); + } + + public void LogProgress(string nameOfClass, string nameOfMethod, string message, string nameOfObject = null) + { + LogProgress(new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressLog(nameOfClass, nameOfMethod, message, nameOfObject)); + } + + public void LogProgress(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressLog progress) + { + ProgressLogging?.Invoke(this, new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressLoggingEventArgs(progress.ToString())); + } + } + + public class ProgressLoggingEventArgs : System.EventArgs + { + public ProgressLoggingEventArgs(string progress) + { + Progress = progress; + } + + public string Progress + { + get; + private set; + } + } + + public struct ProgressLog + { + private readonly string className; + private readonly string methodName; + private readonly string objectName; + private readonly string message; + public ProgressLog(string methodName, string message): this(string.Empty, methodName, message, string.Empty) + { + } + + public ProgressLog(string className, string methodName, string message): this(className, methodName, message, string.Empty) + { + } + + public ProgressLog(string className, string methodName, string message, string objectName) + { + this.className = className; + this.methodName = methodName; + this.message = message; + this.objectName = objectName; + } + + public override string ToString() + { + var sb = new System.Text.StringBuilder(); + if (!string.IsNullOrWhiteSpace(className)) + { + sb.Append(className); + sb.Append("|"); + } + + sb.Append(methodName); + sb.Append("|"); + if (!string.IsNullOrWhiteSpace(objectName)) + { + sb.Append(objectName); + sb.Append("|"); + } + + sb.Append(message); + return sb.ToString(); + } + } + + namespace AvidInterplayPAM + { + public enum InterplayPamElements + { + [System.ComponentModel.Description("IPLAY Helsinki")] + Helsinki, + [System.ComponentModel.Description("IPLAY Tampere")] + Tampere, + [System.ComponentModel.Description("IPLAY Vaasa")] + Vaasa, + [System.ComponentModel.Description("IPLAY UA")] + UA + } + } + + namespace ChangeTracking + { + public class ChangeInfo + { + public ChangeInfo() + { + ProfileParameterChangeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo(); + ResourceChangeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo(); + TimingChangeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo(); + } + + public bool IsChanged => ProfileParameterChangeInfo.ProfileParametersChanged || ResourceChangeInfo.ResourcesChanged || TimingChangeInfo.TimingChanged || CustomPropertiesChanged || ServiceDefinitionChanged || SecurityViewIdsChanged; + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo ProfileParameterChangeInfo + { + get; + private set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo ResourceChangeInfo + { + get; + private set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo TimingChangeInfo + { + get; + private set; + } + + public bool CustomPropertiesChanged + { + get; + private set; + } + + public bool SecurityViewIdsChanged + { + get; + set; + } + + public bool ServiceDefinitionChanged + { + get; + private set; + } + + public void CombineWith(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo second) + { + ProfileParameterChangeInfo.CombineWith(second.ProfileParameterChangeInfo); + ResourceChangeInfo.CombineWith(second.ResourceChangeInfo); + TimingChangeInfo.CombineWith(second.TimingChangeInfo); + CustomPropertiesChanged |= second.CustomPropertiesChanged; + ServiceDefinitionChanged |= second.ServiceDefinitionChanged; + } + + public void MarkCustomPropertiesChanged() + { + CustomPropertiesChanged = true; + } + + public void MarkServiceDefinitionChanged() + { + ServiceDefinitionChanged = true; + } + + public override string ToString() + { + return System.String.Format("( Profile Parameters changed = {0}; Resources changed = {1}; Timing changed = {2}; custom properties changed = {3}; Service Definition changed = {4} )", ProfileParameterChangeInfo.ProfileParametersChanged, ResourceChangeInfo.ResourcesChanged, TimingChangeInfo.TimingChanged, CustomPropertiesChanged, ServiceDefinitionChanged); + } + } + + public interface IYleChangeTracking : System.ComponentModel.IChangeTracking + { + /// + /// Gets a boolean indicating if Change Tracking is enabled. + /// + bool ChangeTrackingEnabled + { + get; + } + + /// + /// Gets an object containing all change info since object construction or since last call. + /// + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo ChangeInfo + { + get; + } + } + + public class ProfileParameterChangeInfo + { + [System.Flags] + private enum TypesOfProfileParameterChanges + { + None = 0, + AudioProcessingProfileParametersChanged = 1, + VideoProcessingProfileParametersChanged = 2, + GraphicsProcessingProfileParametersChanged = 4, + CapabilitiesChanged = 8, + OtherProfileParametersChanged = 16 + } + + private const Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges AllTypesOfProfileParametersChanges = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.AudioProcessingProfileParametersChanged | Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.GraphicsProcessingProfileParametersChanged | Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.VideoProcessingProfileParametersChanged | Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.CapabilitiesChanged | Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.OtherProfileParametersChanged; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges typesOfChanges = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.None; + public bool ProfileParametersChanged => typesOfChanges != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.None; + public bool AudioProcessingProfileParametersChanged => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.AudioProcessingProfileParametersChanged) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.AudioProcessingProfileParametersChanged; + public bool VideoProcessingProfileParametersHaveChanged => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.VideoProcessingProfileParametersChanged) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.VideoProcessingProfileParametersChanged; + public bool GraphicsProcessingProfileParametersHaveChanged => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.GraphicsProcessingProfileParametersChanged) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.GraphicsProcessingProfileParametersChanged; + public bool CapabilitiesChanged => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.CapabilitiesChanged) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.CapabilitiesChanged; + public bool OtherProfileParametersChanged => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.OtherProfileParametersChanged) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.OtherProfileParametersChanged; + public bool OnlyAudioProcessingProfileParametersChanged => (typesOfChanges & AllTypesOfProfileParametersChanges) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.AudioProcessingProfileParametersChanged; + public bool OnlyVideoProcessingProfileParametersChanged => (typesOfChanges & AllTypesOfProfileParametersChanges) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.VideoProcessingProfileParametersChanged; + public bool OnlyGraphicsProcessingProfileParametersChanged => (typesOfChanges & AllTypesOfProfileParametersChanges) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.GraphicsProcessingProfileParametersChanged; + public bool OnlyCapabilitiesChanged => (typesOfChanges & AllTypesOfProfileParametersChanges) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.CapabilitiesChanged; + public bool OnlyOtherProfileParametersChanged => (typesOfChanges & AllTypesOfProfileParametersChanges) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.OtherProfileParametersChanged; + public void CombineWith(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo second) + { + typesOfChanges |= second.typesOfChanges; + } + + public void MarkAudioProcessingProfileParametersChanged() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.AudioProcessingProfileParametersChanged; + } + + public void MarkVideoProcessingProfileParametersChanged() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.VideoProcessingProfileParametersChanged; + } + + public void MarkGraphicsProcessingProfileParametersChanged() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.GraphicsProcessingProfileParametersChanged; + } + + public void MarkDtrProfileParametersChanged() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.CapabilitiesChanged; + } + + public void MarkOtherProfileParametersChanged() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ProfileParameterChangeInfo.TypesOfProfileParameterChanges.OtherProfileParametersChanged; + } + } + + public class ResourceChangeInfo + { + [System.Flags] + private enum TypesOfResourceChanges + { + None = 0, + ResourceWasAddedOrSwapped = 1, + ResourceWasRemoved = 2, + ResourceAtBeginningOfServiceDefinitionHasChanged = 4, + ResourceAtEndOfServiceDefinitionHasChanged = 8 + } + + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges typesOfChanges = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.None; + public bool ResourcesChanged => typesOfChanges != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.None; + public bool ResourcesAddedOrSwapped => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceWasAddedOrSwapped) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceWasAddedOrSwapped; + public bool ResourcesRemoved => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceWasRemoved) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceWasRemoved; + public bool ResourceAtBeginningOfServiceDefinitionChanged => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceAtBeginningOfServiceDefinitionHasChanged) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceAtBeginningOfServiceDefinitionHasChanged; + public bool ResourceAtEndOfServiceDefinitionChanged => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceAtEndOfServiceDefinitionHasChanged) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceAtEndOfServiceDefinitionHasChanged; + public void CombineWith(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo second) + { + typesOfChanges |= second.typesOfChanges; + } + + public void MarkResourceAddedOrSwapped() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceWasAddedOrSwapped; + } + + public void MarkResourceRemoved() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceWasRemoved; + } + + public void MarkResourceAtBeginningOfServiceDefinitionAddedOrSwapped() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceWasAddedOrSwapped; + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceAtBeginningOfServiceDefinitionHasChanged; + } + + public void MarkResourceAtEndOfServiceDefinitionAddedOrSwapped() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceWasAddedOrSwapped; + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ResourceChangeInfo.TypesOfResourceChanges.ResourceAtEndOfServiceDefinitionHasChanged; + } + } + + public class TimingChangeInfo + { + [System.Flags] + private enum TypesOfTimingChanges + { + None = 0, + StartTimingChanged = 1, + EndTimingChanged = 2 + } + + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo.TypesOfTimingChanges typesOfChanges; + public bool TimingChanged => typesOfChanges != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo.TypesOfTimingChanges.None; + public bool StartTimingChanged => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo.TypesOfTimingChanges.StartTimingChanged) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo.TypesOfTimingChanges.StartTimingChanged; + public bool EndTimingChanged => (typesOfChanges & Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo.TypesOfTimingChanges.EndTimingChanged) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo.TypesOfTimingChanges.EndTimingChanged; + public void CombineWith(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo second) + { + typesOfChanges |= second.typesOfChanges; + } + + public void MarkStartTimingChanged() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo.TypesOfTimingChanges.StartTimingChanged; + } + + public void MarkEndTimingChanged() + { + typesOfChanges |= Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.TimingChangeInfo.TypesOfTimingChanges.EndTimingChanged; + } + } + } + + namespace Configuration + { + public static class Constants + { + public static readonly string None = "None"; + public static readonly string NotApplicable = "N/A"; + public static readonly int MaximumAllowedCharacters = 400; + public static readonly string OrderLoggingDirectoryName = "OrderLogging"; + } + + public static class FunctionGuids + { + public static readonly System.Guid Satellite = new System.Guid(SatelliteString); + public const string SatelliteString = "b4ac401c-455c-4e62-85fc-d0261dd9b922"; + public static readonly System.Guid Antenna = new System.Guid(AntennaString); + public const string AntennaString = "3e578238-3588-4c74-820f-def427cc9953"; + public static readonly System.Guid Demodulating = new System.Guid(DemodulatingString); + public const string DemodulatingString = "f6af0f47-fc8c-4be2-9eba-50593e1488bf"; + public static readonly System.Guid Decoding = new System.Guid(DecodingString); + public const string DecodingString = "89c8f8ae-ef77-45b1-b6d3-6a2d8a87d9f1"; + public static readonly System.Guid FiberDecoding = new System.Guid("f52e89f0-c646-4bf9-84ee-1fb126c247d1"); + public static readonly System.Guid FiberSource = new System.Guid("5ab13709-198d-42e2-b0ed-cb48caa96852"); + public static readonly System.Guid FiberDestination = new System.Guid("9ab71ea5-13ce-4bc8-b412-9bd2df69a66f"); + public static readonly System.Guid LiveUPasilaSource = new System.Guid("0f855e47-797a-4fae-b4ea-bf581ab57b8e"); + public const string LiveUPasilaSourceString = "0f855e47-797a-4fae-b4ea-bf581ab57b8e"; + public static readonly System.Guid GenericEncoding = new System.Guid("a6c7084d-c0b8-4b37-be7a-014f15eed3b4"); + public static readonly System.Guid GenericModulating = new System.Guid("24042a26-41e0-47d7-9ba9-59b14f11f21c"); + public static readonly System.Guid MatrixInputAsi = new System.Guid("7bd8d399-b503-4fd9-9b2e-8dc188d591b8"); + public static readonly System.Guid MatrixOutputAsi = new System.Guid("a33a13bd-b40f-4080-9ac4-aa77585f83db"); + public static readonly System.Guid MatrixInputLband = new System.Guid("8c58be38-b7ed-4369-bb89-1a7ad49b29db"); + public static readonly System.Guid MatrixOutputLband = new System.Guid("3492292d-4ba4-47f3-9bd7-7d983d95c064"); + public static readonly System.Guid MatrixInputSdi = new System.Guid("605fa59e-ca49-431c-8874-438e47f3851a"); + public static readonly System.Guid MatrixOutputSdi = new System.Guid("de7c117c-6161-4172-8b4a-35ccb0304765"); + public static readonly System.Collections.Generic.IEnumerable AllMatrixGuids = new[]{MatrixInputAsi, MatrixOutputAsi, MatrixInputSdi, MatrixOutputSdi, MatrixInputLband, MatrixOutputLband}; + public static readonly System.Collections.Generic.IEnumerable AllMatrixInputGuids = new[]{MatrixInputSdi, MatrixInputAsi, MatrixInputLband}; + public static readonly System.Collections.Generic.Dictionary MatrixFunctionPairs = new System.Collections.Generic.Dictionary{{MatrixInputAsi, MatrixOutputAsi}, {MatrixInputLband, MatrixOutputLband}, {MatrixInputSdi, MatrixOutputSdi}, {MatrixOutputAsi, MatrixInputAsi}, {MatrixOutputLband, MatrixInputLband}, {MatrixOutputSdi, MatrixInputSdi}}; + public static bool IsMatrixFunction(System.Guid functionID) + { + return System.Linq.Enumerable.Contains(AllMatrixGuids, functionID); + } + } + + public static class OrderManagerProtocol + { + public const string Name = "Finnish Broadcasting Company Order Manager"; + public const int LockRequestParameterId = 5200; + } + + public static class ProfileParameterGuids + { + public static readonly System.Guid _ServiceConfiguration = new System.Guid("9083c73c-7eb3-4fc9-85ea-02fea98312a9"); + public static readonly System.Guid _Matrix = new System.Guid("bce4b6a3-4045-4ec0-88d3-ba61c15f8038"); + public static readonly System.Guid _OrbitalPosition = new System.Guid("a9810b80-c127-47a1-9e08-777dbb758ea1"); + public static readonly System.Guid _TvChannel = new System.Guid("26560675-38a6-4dba-af61-e23d75b3af1d"); + public static readonly System.Guid _FeedType = new System.Guid("07278965-6138-46de-b1d6-1f02861c240d"); + public static readonly System.Guid AreenaCopy = new System.Guid("798393c6-4ddf-48c2-92ae-668433de3428"); + public static readonly System.Guid AreenaDestinationLocation = new System.Guid("96cc6585-2b3a-4129-a7d3-85c58b61b5de"); + public static readonly System.Guid AudioDeembeddingRequired = new System.Guid("1d51086a-ca66-4e1d-b84f-6fd05a24ee68"); + public static readonly System.Guid AudioEmbeddingRequired = new System.Guid("a2726fd1-cc4b-4b23-b464-3684a0db4dd6"); + public static readonly System.Guid AudioShufflingRequired = new System.Guid("01682ff9-2cc4-4cd5-8252-d5956424479a"); + public static readonly System.Guid AudioDolbyDecodingRequired = new System.Guid("35215bb4-0faa-423f-beed-58ada9b604b3"); + public static readonly System.Guid AudioChannel1 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel1String); + public static readonly System.Guid AudioChannel2 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel2String); + public static readonly System.Guid AudioChannel3 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel3String); + public static readonly System.Guid AudioChannel4 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel4String); + public static readonly System.Guid AudioChannel5 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel5String); + public static readonly System.Guid AudioChannel6 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel6String); + public static readonly System.Guid AudioChannel7 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel7String); + public static readonly System.Guid AudioChannel8 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel8String); + public static readonly System.Guid AudioChannel9 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel9String); + public static readonly System.Guid AudioChannel10 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel10String); + public static readonly System.Guid AudioChannel11 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel11String); + public static readonly System.Guid AudioChannel12 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel12String); + public static readonly System.Guid AudioChannel13 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel13String); + public static readonly System.Guid AudioChannel14 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel14String); + public static readonly System.Guid AudioChannel15 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel15String); + public static readonly System.Guid AudioChannel16 = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.AudioChannel16String); + public static readonly System.Guid AudioChannel1Description = new System.Guid("fab7b647-df5f-43ac-9396-511fc6ba9f81"); + public static readonly System.Guid AudioChannel2Description = new System.Guid("f08209ca-898b-40d3-835d-e5bca4420960"); + public static readonly System.Guid AudioChannel3Description = new System.Guid("c4dc3e48-1d7e-48f0-832e-af4eecf716d4"); + public static readonly System.Guid AudioChannel4Description = new System.Guid("8b2499e6-653b-409c-8c6c-ed9d56f989fe"); + public static readonly System.Guid AudioChannel5Description = new System.Guid("19e761d7-31d1-48fe-8265-9b24f386eafd"); + public static readonly System.Guid AudioChannel6Description = new System.Guid("cf014313-b2d3-46a3-8cc3-c7bb57946c5c"); + public static readonly System.Guid AudioChannel7Description = new System.Guid("4a7c08cf-67a1-4e37-85fd-89bfe39331a8"); + public static readonly System.Guid AudioChannel8Description = new System.Guid("0e478f07-4c48-4cb2-bd44-615cc197141a"); + public static readonly System.Guid AudioChannel9Description = new System.Guid("145eda52-eb24-49bd-87b5-31edf8e1002f"); + public static readonly System.Guid AudioChannel10Description = new System.Guid("868a72c4-7ed5-4d81-b8fd-c4e803681100"); + public static readonly System.Guid AudioChannel11Description = new System.Guid("5b65ad74-d72b-42be-b1d6-87319580df88"); + public static readonly System.Guid AudioChannel12Description = new System.Guid("bd8065e8-72d7-4907-a910-9f47ad48e79f"); + public static readonly System.Guid AudioChannel13Description = new System.Guid("f114e37c-3627-4dda-8bd2-b0ce466c446b"); + public static readonly System.Guid AudioChannel14Description = new System.Guid("3887c50c-c1fc-45aa-97bc-c24eeca812a4"); + public static readonly System.Guid AudioChannel15Description = new System.Guid("45f43ff0-9c3b-4dd1-a50a-34faac268612"); + public static readonly System.Guid AudioChannel16Description = new System.Guid("f28b5c26-639c-4881-80d1-dc1d6a95c422"); + public static readonly System.Guid AudioReturnChannel = new System.Guid("b765fd4c-92ee-48f1-b858-4d04e3172dd9"); + public static readonly System.Guid LiveUAudioReturnInfo = new System.Guid("97dcf302-7cf5-4350-bbf5-9efe6cf0480c"); + public static readonly System.Guid DownlinkFrequency = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.DownlinkFrequencyString); + public static readonly System.Guid Encoding = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.EncodingString); + public static readonly System.Guid EncryptionKey = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.EncryptionKeyString); + public static readonly System.Guid Fec = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.FecString); + public static readonly System.Guid FastRerun = new System.Guid("9100b6ea-5b40-4fce-8066-532bea045f65"); + public static readonly System.Guid FeedName = new System.Guid("50e277dc-e0b5-4ba8-8384-d7b1764a3815"); + public static readonly System.Guid FixedTieLineSource = new System.Guid("bfe1faa3-62a1-44d6-9db1-6ff7ac07605f"); + public static readonly System.Guid Polarization = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.PolarizationString); + public static readonly System.Guid ResourceInputConnectionsAsi = new System.Guid("58a7e9e4-6a39-42c9-b275-92f9dc7f9003"); + public static readonly System.Guid ResourceInputConnectionsLband = new System.Guid("5c8ea48d-fafb-4fae-9f43-8ce2e9347d90"); + public static readonly System.Guid ResourceInputConnectionsSdi = new System.Guid("3fab320b-6059-47ee-aad3-bf98fbba9f06"); + public static readonly System.Guid ResourceOutputConnectionsAsi = new System.Guid("3c08c3a7-d1fb-46f2-877b-8927345cf931"); + public static readonly System.Guid ResourceOutputConnectionsLband = new System.Guid("a12733e0-1ba5-48b8-a253-1f353eaeae79"); + public static readonly System.Guid ResourceOutputConnectionsSdi = new System.Guid("1f5d4759-1d66-4cbe-a4c0-6bb6fb6937d6"); + public static readonly System.Guid RemoteGraphics = new System.Guid("7504c7e2-4c65-4230-8302-41e4fc90d210"); + public static readonly System.Guid SubtitleProxy = new System.Guid("7610d0f7-e068-4cd9-a014-0308b277d4f2"); + public static readonly System.Guid SymbolRate = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.SymbolRateString); + public static readonly System.Guid ModulationStandard = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.ModulationStandardString); + public static readonly System.Guid Modulation = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.ModulationString); + public static readonly System.Guid EncryptionType = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.EncryptionTypeString); + public static readonly System.Guid VideoFormat = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.VideoFormatString); + public static readonly System.Guid RecordingVideoFormat = new System.Guid("105baed9-4031-4d7c-a436-d26fe608af7b"); + public static readonly System.Guid ExternalCompaniesDestinationLocation = new System.Guid("62e5716c-85d8-4d01-a308-b87cc461b1b3"); + public static readonly System.Guid EbuDestinationLocation = new System.Guid("b4213f38-3bb7-48a4-a61c-3ec0b609785e"); + public static readonly System.Guid YleHelsinkiDestinationLocation = new System.Guid("603c52e0-ca2b-4171-bba9-9469250031d4"); + public static readonly System.Guid YleMediapolisDestinationLocation = new System.Guid("ea655627-a17d-442a-9e51-5ddebee9755f"); + public static readonly System.Guid FixedLineExternalCompaniesSourceLocation = new System.Guid("f0c352c7-5fa6-4338-a201-94c18fdb8d4e"); + public static readonly System.Guid FixedLineHelsinkiCityConnectionsSourceLocation = new System.Guid("b1224510-bfbf-4506-9120-1eb33ad353d4"); + public static readonly System.Guid FixedLineYleHelsinkiSourceLocation = new System.Guid("b9565c0d-a26f-4fa9-985a-cc162e8524d7"); + public static readonly System.Guid FixedLineEbuSourceLocation = new System.Guid("b6877c1e-99c3-4971-a4da-7c47bcf274e3"); + public static readonly System.Guid FixedLineLySourcePlasmaUserCode = new System.Guid("7bab8775-841d-4b14-ae83-e665d4768b47"); + public static readonly System.Guid Channel = new System.Guid("af8e34b9-6a5b-4126-b65e-ec670e4099bd"); + public static readonly System.Guid ServiceSelection = new System.Guid(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Strings.ServiceSelectionString); + public static readonly System.Guid OtherSatelliteName = new System.Guid("c375a18f-60d7-497f-88b3-2b113f18f3ce"); + public static readonly System.Guid[] AllAudioProcessingRequiredGuids = new[]{AudioDeembeddingRequired, AudioDolbyDecodingRequired, AudioEmbeddingRequired, AudioShufflingRequired}; + public static readonly System.Guid[] AllAudioChannelConfigurationGuids = new[]{AudioDeembeddingRequired, AudioEmbeddingRequired, AudioShufflingRequired, AudioDolbyDecodingRequired, AudioChannel1, AudioChannel1Description, AudioChannel2, AudioChannel2Description, AudioChannel3, AudioChannel3Description, AudioChannel4, AudioChannel4Description, AudioChannel5, AudioChannel5Description, AudioChannel6, AudioChannel6Description, AudioChannel7, AudioChannel7Description, AudioChannel8, AudioChannel8Description, AudioChannel9, AudioChannel9Description, AudioChannel10, AudioChannel10Description, AudioChannel11, AudioChannel11Description, AudioChannel12, AudioChannel12Description, AudioChannel13, AudioChannel13Description, AudioChannel14, AudioChannel14Description, AudioChannel15, AudioChannel15Description, AudioChannel16, AudioChannel16Description}; + public static readonly System.Guid[] AllResourceInputConnectionGuids = new[]{ResourceInputConnectionsSdi, ResourceInputConnectionsLband, ResourceInputConnectionsAsi}; + public static readonly System.Guid[] AllResourceOutputConnectionGuids = new[]{ResourceOutputConnectionsSdi, ResourceOutputConnectionsLband, ResourceOutputConnectionsAsi}; + public static class Strings + { + public const string AudioChannel1String = "d4f1e0fe-1a72-4ec3-9fd8-aefd4785ebdf"; + public const string AudioChannel2String = "bce7eff1-a884-47af-a182-559e0cfa4379"; + public const string AudioChannel3String = "471d52de-b90c-4d8d-9cb5-b11916a06d08"; + public const string AudioChannel4String = "5f014774-c3ce-492e-96c3-cd7402dbe171"; + public const string AudioChannel5String = "fad366e6-2f29-466b-a286-434446cf6437"; + public const string AudioChannel6String = "5c68fb8a-5c8f-4970-aeb4-b04b5f465724"; + public const string AudioChannel7String = "83b3d476-39dd-4660-854f-27bbe6436914"; + public const string AudioChannel8String = "e9aeb156-a027-4898-b41e-6af88169a3ff"; + public const string AudioChannel9String = "5eadca8d-f96a-464d-81a4-139dc6da0fba"; + public const string AudioChannel10String = "7178133a-d8a8-485d-99fa-b909ef73d848"; + public const string AudioChannel11String = "052babfe-b396-4d3f-a305-21442b3e0fd1"; + public const string AudioChannel12String = "acb1bef4-f80b-424b-abd1-a51a05586a6d"; + public const string AudioChannel13String = "fa83f575-0935-4952-b561-ce349c7e59fb"; + public const string AudioChannel14String = "f60e0b3e-840a-47f1-b521-9e1dbdc28562"; + public const string AudioChannel15String = "2712a2f9-273a-439f-b85a-5101789782cf"; + public const string AudioChannel16String = "cc76cdc0-925c-472f-985f-c0c5e477639c"; + public const string DownlinkFrequencyString = "d045fe27-2163-4e9b-b4e6-41ec3eac2a5d"; + public const string EncodingString = "3efcc36d-2cb9-4f22-a1e1-fae50def51ca"; + public const string EncryptionKeyString = "09995fd9-9526-485c-99cb-1d9eb6178195"; + public const string EncryptionTypeString = "27465703-cd3c-40a7-81e4-cf72119a1e3b"; + public const string FecString = "3f6fb925-e996-496c-8760-34436590c47e"; + public const string PolarizationString = "3f5f30c2-a4b1-4ab6-be06-ecec2e35cd5d"; + public const string SymbolRateString = "9a752cb7-77f2-4f75-8b9a-9a290eaf81b5"; + public const string ModulationString = "ea300fb7-527f-4b14-aff9-7985875b82e3"; + public const string ModulationStandardString = "ed8446e9-e373-419d-9b9f-8a1c94ec8ae7"; + public const string ServiceSelectionString = "0e4008ca-5dd8-40f5-b141-cd8b631444ee"; + public const string VideoFormatString = "8dc6df35-c574-4412-bf52-de7e3c78201c"; + } + } + + /// + /// A static class containing all the names of custom properties on service reservations as defined in the Booking + /// Managers. + /// + public static class ServicePropertyNames + { + public const string StatusPropertyName = "Status"; + public const string VirtualPlatformPropertyName = "Virtual Platform"; + public const string ShortDescription = "Short Description"; + public const string ReportedIssuePropertyName = "Reported_Issue"; + public const string ServiceLevelPropertyName = "ServiceLevel"; + public const string IsEventLevelReceptionPropertyName = "IsEventLevelReception"; + public const string IsGlobalEventLevelReceptionPropertyName = "IsGlobalEventLevelReception"; + public const string IntegrationTypePropertyName = "Integration"; + public const string IntegrationIsMasterPropertyName = "IntegrationIsMaster"; + public const string LinkedServiceIdPropertyName = "LinkedServiceId"; + public const string EurovisionIdPropertyName = "EurovisionId"; + public const string EurovisionTransmissionNumberPropertyName = "EurovisionTransmissionNumber"; + public const string EurovisionBookingDetailsPropertyName = "EurovisionBookingDetails"; + public const string LinkedEventIdPropertyName = "LinkedEventId"; + public const string CommentsPropertyName = "Comments"; + public const string OrderIdsPropertyName = "OrderIds"; + public const string ContactInformationNamePropertyName = "ContactInformationName"; + public const string ContactInformationTelephoneNumberPropertyName = "ContactInformationTelephoneNumber"; + public const string LiveUDeviceNamePropertyName = "LiveUDeviceName"; + public const string VidigoStreamSourceLinkPropertyName = "VidigoStreamSourceLink"; + public const string RecordingConfigurationPropertyName = "RecordingConfiguration"; + public const string BackupServicePropertyName = "UI_Backup"; + public const string CommentaryAudioPropertyName = "UI_Comm_Audio"; + public const string OrderReferencesPropertyName = "OrderIds"; + public const string NameOfServiceToTransmitPropertyName = "NameOfServiceToTransmit"; + public const string OrderNamePropertyName = "OrderName"; + public const string AudioReturnInfoPropertyName = "AudioReturnInfo"; + } + } + + namespace Contracts + { + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + public class ContractManager : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts.IContractManager + { + public const string DataminerUserLoginName = "DataMiner Agent"; + private readonly Skyline.DataMiner.Automation.IEngine engine; + /// + /// Initializes a new instance of the ContractManager class. + /// + /// Link with DataMiner. + /// Thrown when the provided Engine is null. + /// Thrown when no Finnish Broadcasting Company Contract Manager element running the production version of the protocol was found on the DMS. + /// Thrown when the found Finnish Broadcasting Company Contract Manager element is not running. + public ContractManager(Skyline.DataMiner.Automation.IEngine engine) + { + this.engine = engine ?? throw new System.ArgumentNullException(nameof(engine)); + Element = System.Linq.Enumerable.FirstOrDefault(engine.FindElementsByProtocol("Finnish Broadcasting Company Contract Manager", "Production")); + if (Element == null) + throw new Skyline.DataMiner.Library.Exceptions.ElementNotFoundException("Unable to find a Contract Manager element"); + if (!Element.IsActive) + throw new Skyline.DataMiner.Library.Exceptions.ElementNotStartedException("The Contract Manager element is not running"); + } + + /// + /// Gets the ContractManager element that this class instance interacts with. + /// + public Skyline.DataMiner.Automation.Element Element + { + get; + private set; + } + } + + public interface IContractManager + { + } + } + + namespace Event + { + public enum Status + { + /// + /// Event which may or may not happen. + /// + [System.ComponentModel.Description("Preliminary")] + Preliminary = 0, + /// + /// Event that does not contain any orders. + /// + [System.ComponentModel.Description("Planned")] + Planned = 1, + /// + /// Event that contains at least one order. + /// + [System.ComponentModel.Description("Confirmed")] + Confirmed = 2, + /// + /// Event that contains at least one order and where start time is passed and end time is not reached. + /// + [System.ComponentModel.Description("Ongoing")] + Ongoing = 3, + /// + /// Event that contains at least one order and where end time is passed. + /// + [System.ComponentModel.Description("Completed")] + Completed = 4, + /// + /// Event that was cancelled. + /// + [System.ComponentModel.Description("Cancelled")] + Cancelled = 5 + } + + // TODO: move methods from EventManager to Event that directly manipulate the Event object itself + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Skyline.DataMiner.Storage.Types.dll")] + public class Event : System.ICloneable + { + public const string OrderReservationFieldDescriptorName = "Order Reservation Field Descriptor"; + public const string OrderIsIntegrationFieldDescriptorName = "Order Is Integration Field Descriptor"; + public const string PropertyNameName = "Name"; + public const string PropertyNameStartTime = "Start Time"; + public const string PropertyNameEndTime = "End Time"; + public const string PropertyNameInfo = "Info"; + public const string PropertyNameProjectNumber = "Project Number"; + public const string PropertyNameProductNumbers = "Product Number"; + public const string PropertyNameAttachments = "Attachments"; + public const string PropertyNameContract = "Contract"; + public const string PropertyNameStatus = "Status"; + public const string PropertyNameCompany = "Company"; + public const string PropertyNameInternal = "Internal"; + public const string PropertyNameIntegration = "Integration"; + public const string PropertyNameOperatorNotes = "Operator Notes"; + public const string PropertyNameCompanyOfCreator = "Company Of Creator"; + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.JobManager jobManager; + private readonly Skyline.DataMiner.Net.Jobs.Job job; + private readonly Skyline.DataMiner.Net.Sections.SectionDefinition customEventSectionDefinition; + private readonly Skyline.DataMiner.Net.Sections.Section customEventSection; + private readonly Skyline.DataMiner.Net.Sections.SectionDefinition orderSectionDefinition; + public Event(Skyline.DataMiner.Net.Sections.SectionDefinition orderSectionDefinition, Skyline.DataMiner.Net.Sections.SectionDefinition customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + if (orderSectionDefinition == null) + throw new System.ArgumentNullException(nameof(orderSectionDefinition)); + if (customEventSectionDefinition == null) + throw new System.ArgumentNullException(nameof(customEventSectionDefinition)); + progressReporter?.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), "Constructor"); + var stopwatch = System.Diagnostics.Stopwatch.StartNew(); + jobManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.JobManager(Skyline.DataMiner.Automation.Engine.SLNetRaw, progressReporter); + job = new Skyline.DataMiner.Net.Jobs.Job(); + var defaultJobDomain = jobManager.GetDefaultJobDomain(); + if (defaultJobDomain == null) + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.AddOrUpdateEventFailedException("Default job domain not found"); + job.JobDomainID = defaultJobDomain.ID; + this.customEventSectionDefinition = customEventSectionDefinition; + this.customEventSection = new Skyline.DataMiner.Net.Sections.Section(customEventSectionDefinition); + job.Sections.Add(customEventSection); + this.orderSectionDefinition = orderSectionDefinition; + IsInternal = false; // Default value. Should be set to make sure Event is visible in app UI. + progressReporter?.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), "Constructor", null, stopwatch); + } + + public Event(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.LiteOrder order): this(helpers?.EventManager?.OrderSectionDefinition, helpers?.EventManager?.CustomEventSectionDefinition, helpers?.ProgressReporter) + { + if (helpers == null) + throw new System.ArgumentNullException(nameof(helpers)); + if (order == null) + throw new System.ArgumentNullException(nameof(order)); + helpers.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), "Constructor", out var stopwatch); + Name = order.RecurringSequenceInfo?.Name ?? order.Name; + Start = order.Start; + End = order.End; + Status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Status.Confirmed; + Contract = order.Contract; + Company = order.Company; + CompanyOfCreator = order.Company; + IntegrationType = order.IntegrationType; + SecurityViewIds = order.SecurityViewIds; + if (order.Id != System.Guid.Empty) + { + AddOrUpdateOrderSection(order, helpers.ProgressReporter); + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), "Constructor", $"Added order section with ID '{order.Id}' to job object."); + } + else + { + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), "Constructor", $"Order ID is empty, no order section added to job object."); + } + + helpers.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), "Constructor", null, stopwatch); + } + + public Event(Skyline.DataMiner.Net.Jobs.Job job, Skyline.DataMiner.Net.Sections.SectionDefinition orderSectionDefinition, Skyline.DataMiner.Net.Sections.SectionDefinition customEventSectionDefinition) + { + this.job = job ?? throw new System.ArgumentNullException(nameof(job)); + jobManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.JobManager(Skyline.DataMiner.Automation.Engine.SLNetRaw); + this.customEventSectionDefinition = customEventSectionDefinition; + this.customEventSection = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetCustomEventSection(job, customEventSectionDefinition.GetID().Id); + this.orderSectionDefinition = orderSectionDefinition; + Id = job.ID.Id; + } + + public System.Guid Id + { + get; + set; + } + + public string Name + { + get => Skyline.DataMiner.Net.Sections.DefaultJobSectionExtensions.GetJobName(job); + set => Skyline.DataMiner.Net.Sections.DefaultJobSectionExtensions.SetJobName(job, value); + } + + public System.DateTime Start + { + get => Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetStartTime(job); + set => Skyline.DataMiner.Net.Sections.DefaultJobSectionExtensions.SetJobStartTime(job, value); + } + + public System.DateTime End + { + get => Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetEndTime(job); + set => Skyline.DataMiner.Net.Sections.DefaultJobSectionExtensions.SetJobEndTime(job, value); + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Status Status + { + get => Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.StringExtensions.GetEnumValue(System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameStatus) ?? string.Empty)); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameStatus, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescription(value)); + } + + public string ProjectNumber + { + get => System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameProjectNumber) ?? string.Empty); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameProjectNumber, value ?? string.Empty); + } + + public System.Collections.Generic.IEnumerable ProductNumbers + { + get => System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameProductNumbers) ?? string.Empty).Split('/') ?? new string[0]; + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameProductNumbers, value != null ? string.Join("/", value) : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.Constants.NotApplicable); + } + + public string Info + { + get => System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameInfo) ?? string.Empty); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameInfo, value ?? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.Constants.NotApplicable); + } + + public System.Collections.Generic.IEnumerable Attachments + { + get => System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameInfo) ?? string.Empty).Split('\n'); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameAttachments, value != null ? string.Join("\n", value) : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.Constants.NotApplicable); + } + + /// + /// The Contract for this Event. + /// + public string Contract + { + get => System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, PropertyNameContract) ?? string.Empty); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameContract, value ?? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.Constants.NotApplicable); + } + + /// + /// The Company of this Event. + /// + public string Company + { + get => System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, PropertyNameCompany) ?? string.Empty); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameCompany, value ?? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.Constants.NotApplicable); + } + + /// + /// The Company of the user who created this Event. + /// + public string CompanyOfCreator + { + get => System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, PropertyNameCompanyOfCreator)); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameCompanyOfCreator, value ?? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.Constants.NotApplicable); + } + + public bool IsInternal + { + get => System.Convert.ToBoolean(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameInternal)); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameInternal, value.ToString()); + } + + public string OperatorNotes + { + get => System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameOperatorNotes)); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameOperatorNotes, value ?? string.Empty); + } + + public System.Collections.Generic.List EventLevelServices + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType IntegrationType + { + get => Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.StringExtensions.GetEnumValue(System.Convert.ToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameIntegration))); + set => jobManager.UpdateSectionField(customEventSection, customEventSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameIntegration, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescription(value)); + } + + /// + /// Gets a collection of Cube View IDs of views where this event is visible. + /// + public System.Collections.Generic.HashSet SecurityViewIds + { + get => new System.Collections.Generic.HashSet(job.SecurityViewIDs); + set => job.SecurityViewIDs = value != null ? System.Linq.Enumerable.ToList(value) : new System.Collections.Generic.List(); + } + + /// + /// A collection of Guids representing the Orders that belong to this Event. + /// + public System.Collections.Generic.HashSet OrderIds => new System.Collections.Generic.HashSet(System.Linq.Enumerable.Select(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetOrderSections(job), s => s.OrderId)); + /// + /// A Dictionary indicating whether an order is made by an integration or not. Used for performance reasons when merging events. + /// + public System.Collections.Generic.Dictionary OrderIsIntegrations => System.Linq.Enumerable.ToDictionary(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetOrderSections(job), s => s.OrderId, s => s.OrderIsIntegration); + public void AddOrUpdateOrderSection(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.LiteOrder order, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + if (order == null) + throw new System.ArgumentNullException(nameof(order)); + progressReporter?.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), nameof(AddOrUpdateOrderSection)); + var stopwatch = System.Diagnostics.Stopwatch.StartNew(); + bool addOrUpdateNotRequired = order.Id == System.Guid.Empty || (HasOrder(order.Id) && OrderSectionIsValid(order.Id)); + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), nameof(AddOrUpdateOrderSection), $"Add or Update Order Section is {(addOrUpdateNotRequired ? "not " : string.Empty)}required"); + if (addOrUpdateNotRequired) + { + stopwatch.Stop(); + progressReporter?.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), nameof(AddOrUpdateOrderSection), null, stopwatch); + return; + } + + var newOrUpdatedOrderSection = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.OrderSection(order, orderSectionDefinition, progressReporter); + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.AddOrUpdateOrderSection(job, newOrUpdatedOrderSection); + stopwatch.Stop(); + progressReporter?.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event), nameof(AddOrUpdateOrderSection), null, stopwatch); + } + + public bool HasOrder(System.Guid orderId) + { + return OrderIds.Contains(orderId); + } + + public bool OrderSectionIsValid(System.Guid orderId) + { + var orderSection = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetOrderSection(job, orderId); + if (orderSection == null) + return false; + return orderSection.IsValid; + } + + public object Clone() + { + return new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event((Skyline.DataMiner.Net.Jobs.Job)job.Clone(), orderSectionDefinition, customEventSectionDefinition); + } + + public override string ToString() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.None); + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Skyline.DataMiner.Storage.Types.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLNetTypes.dll")] + public class EventManager : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.IEventManager + { + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.JobManager jobManager; + private Skyline.DataMiner.Net.Sections.SectionDefinition orderSectionDefinition; // saved for performance reasons + private Skyline.DataMiner.Net.Sections.SectionDefinition customEventSectionDefinition; // saved for performance reasons + public EventManager(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers) + { + Helpers = helpers ?? throw new System.ArgumentNullException(nameof(helpers)); + jobManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.JobManager(Skyline.DataMiner.Automation.Engine.SLNetRaw, Helpers.ProgressReporter); + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers Helpers + { + get; + } + + public Skyline.DataMiner.Net.Sections.SectionDefinition OrderSectionDefinition => orderSectionDefinition ?? (orderSectionDefinition = jobManager.GetOrderSectionDefinition()); + public Skyline.DataMiner.Net.Sections.SectionDefinition CustomEventSectionDefinition => customEventSectionDefinition ?? (customEventSectionDefinition = jobManager.GetCustomEventSectionDefinition()); + public System.Collections.Generic.IEnumerable GetAllEvents() + { + var @events = new System.Collections.Generic.List(); + var jobs = jobManager.GetJobs(Skyline.DataMiner.Net.Jobs.JobExposerExtensions.JobStartGreaterThan(Skyline.DataMiner.Net.Jobs.JobExposers.FieldValues, default(System.DateTime))); + foreach (var job in jobs) + @events.Add(new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event(job, OrderSectionDefinition, CustomEventSectionDefinition)); + return @events; + } + } + + public interface IEventManager + { + System.Collections.Generic.IEnumerable GetAllEvents(); + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Skyline.DataMiner.Storage.Types.dll")] + public class JobManager + { + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter; + private readonly Skyline.DataMiner.Net.Jobs.JobManagerHelper helper; + private System.Collections.Generic.IEnumerable allSectionDefinitions; + public JobManager(Skyline.DataMiner.Net.Connection connection, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + this.progressReporter = progressReporter; + helper = new Skyline.DataMiner.Net.Jobs.JobManagerHelper(m => connection.HandleMessages(m)); + } + + public System.Collections.Generic.IEnumerable AllSectionDefinitions => allSectionDefinitions ?? (allSectionDefinitions = helper.SectionDefinitions.Read(Skyline.DataMiner.Net.Messages.SLDataGateway.ExposerExtensions.NotEqual(Skyline.DataMiner.Net.Sections.SectionDefinitionExposers.Name, string.Empty))); + public System.Collections.Generic.List GetJobs(Skyline.DataMiner.Net.Messages.SLDataGateway.FilterElement filter) + { + var jobs = helper.Jobs.Read(filter); + if (jobs == null) + return new System.Collections.Generic.List(); + helper.StitchJobs(jobs); + return jobs; + } + + public Skyline.DataMiner.Net.Jobs.JobDomain GetDefaultJobDomain() + { + var eventSectionDefinition = GetCustomEventSectionDefinition(); + if (eventSectionDefinition == null) + return null; + var eventSectionDefinitionId = eventSectionDefinition.GetID(); + if (eventSectionDefinitionId == null) + return null; + var jobDomains = helper.JobDomains.Read(Skyline.DataMiner.Net.Messages.SLDataGateway.ListManagedFilterExtensions.Contains(Skyline.DataMiner.Net.Jobs.JobDomainExposers.SectionDefinitionIDs, eventSectionDefinitionId.Id)); + if (jobDomains == null) + return null; + return System.Linq.Enumerable.FirstOrDefault(jobDomains); + } + + public void UpdateSectionField(Skyline.DataMiner.Net.Sections.Section section, Skyline.DataMiner.Net.Sections.SectionDefinition sectionDefinition, string name, string value) + { + if (section == null) + throw new System.ArgumentNullException(nameof(section)); + if (sectionDefinition == null) + throw new System.ArgumentNullException(nameof(sectionDefinition)); + if (string.IsNullOrWhiteSpace(name)) + throw new System.ArgumentNullException(nameof(name)); + var fieldDescriptor = GetFieldDescriptor(sectionDefinition, name); + if (fieldDescriptor == null) + return; + section.AddOrReplaceFieldValue(new Skyline.DataMiner.Net.Sections.FieldValue(fieldDescriptor) + {Value = new Skyline.DataMiner.Net.Sections.ValueWrapper(value)}); + } + + public Skyline.DataMiner.Net.Sections.SectionDefinition GetCustomEventSectionDefinition() + { + LogMethodStart(nameof(GetCustomEventSectionDefinition), out var stopwatch); + var customEventSectionDefinition = System.Linq.Enumerable.FirstOrDefault(AllSectionDefinitions, x => System.Linq.Enumerable.Any(x.GetAllFieldDescriptors(), y => y.Name.Equals("Status", System.StringComparison.OrdinalIgnoreCase))); + LogMethodCompleted(nameof(GetCustomEventSectionDefinition), stopwatch); + // search for a section with a field named Status + return customEventSectionDefinition; + } + + public Skyline.DataMiner.Net.Sections.SectionDefinition GetOrderSectionDefinition() + { + LogMethodStart(nameof(GetOrderSectionDefinition), out var stopwatch); + var orderSectionDefinition = System.Linq.Enumerable.FirstOrDefault(AllSectionDefinitions, sd => sd.GetName().Equals("Orders", System.StringComparison.OrdinalIgnoreCase)); + LogMethodCompleted(nameof(GetOrderSectionDefinition), stopwatch); + return orderSectionDefinition; + } + + public Skyline.DataMiner.Net.Sections.FieldDescriptor GetFieldDescriptor(Skyline.DataMiner.Net.Sections.SectionDefinition sectionDefinition, string name) + { + if (sectionDefinition == null) + throw new System.ArgumentNullException(nameof(sectionDefinition)); + if (string.IsNullOrWhiteSpace(name)) + throw new System.ArgumentNullException(nameof(name)); + var sectionDefinitionFieldDescriptors = sectionDefinition.GetAllFieldDescriptors(); + return System.Linq.Enumerable.FirstOrDefault(sectionDefinitionFieldDescriptors, d => d.Name.Contains(name)); + } + + public Skyline.DataMiner.Net.Sections.ReservationFieldDescriptor GetOrCreateOrderReservationIdFieldDescriptor(Skyline.DataMiner.Net.Sections.SectionDefinition sectionDefinition) + { + var fieldDescriptors = sectionDefinition.GetAllFieldDescriptors(); + var reservationIdFieldDescriptor = System.Linq.Enumerable.FirstOrDefault(fieldDescriptors, f => f is Skyline.DataMiner.Net.Sections.ReservationFieldDescriptor); + if (reservationIdFieldDescriptor == null) + throw new System.Exception("Unable to find field descriptor"); + return reservationIdFieldDescriptor as Skyline.DataMiner.Net.Sections.ReservationFieldDescriptor; + /* + VSC 04/11/2021: No longer necessary + + var newReservationFieldDescriptor = new ReservationFieldDescriptor + { + FieldType = typeof(Guid), + Name = Event.OrderReservationFieldDescriptorName, + IsHidden = false, + IsOptional = true + }; + + sectionDefinition.AddOrReplaceFieldDescriptor(newReservationFieldDescriptor); + UpdateSectionDefinition(sectionDefinition); + */ + } + + public Skyline.DataMiner.Net.Sections.FieldDescriptor GetOrCreateOrderIsIntegrationFieldDescriptor(Skyline.DataMiner.Net.Sections.SectionDefinition sectionDefinition) + { + var fieldDescriptors = sectionDefinition.GetAllFieldDescriptors(); + var orderIsIntegrationFieldDescriptor = System.Linq.Enumerable.FirstOrDefault(fieldDescriptors, f => f.Name == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.OrderIsIntegrationFieldDescriptorName); + if (orderIsIntegrationFieldDescriptor == null) + throw new System.Exception("Unable to find field descriptor"); + return orderIsIntegrationFieldDescriptor; + /* + VSC 04/11/2021: No longer necessary + + + var newOrderIsIntegrationFieldDescriptor = new FieldDescriptor + { + FieldType = typeof(bool), + Name = Event.OrderIsIntegrationFieldDescriptorName, + IsHidden = false, + IsOptional = true + }; + + sectionDefinition.AddOrReplaceFieldDescriptor(newOrderIsIntegrationFieldDescriptor); + UpdateSectionDefinition(sectionDefinition); + */ + } + + protected void LogMethodStart(string nameOfMethod, out System.Diagnostics.Stopwatch stopwatch) + { + Log(nameOfMethod, "Start"); + stopwatch = System.Diagnostics.Stopwatch.StartNew(); + } + + protected void LogMethodCompleted(string nameOfMethod, System.Diagnostics.Stopwatch stopwatch = null) + { + stopwatch?.Stop(); + Log(nameOfMethod, $"Completed [{stopwatch?.Elapsed}]"); + } + + protected void Log(string nameOfMethod, string message, string nameOfObject = null) + { + progressReporter?.LogProgress(new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressLog(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.EventManager), nameOfMethod, message, nameOfObject)); + } + } + + public class OrderSection : Skyline.DataMiner.Net.Sections.Section + { + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter; + private Skyline.DataMiner.Net.Sections.ReservationFieldDescriptor reservationFieldDescriptor; + private Skyline.DataMiner.Net.Sections.FieldDescriptor isIntegrationFieldDescriptor; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.JobManager jobManager; + private readonly Skyline.DataMiner.Net.Sections.SectionDefinition orderSectionDefinition; + private System.Guid orderId; + private bool orderIdIsValid; + private bool orderIsIntegration; + private bool orderIsIntegrationIsValid; + public OrderSection(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.LiteOrder order, Skyline.DataMiner.Net.Sections.SectionDefinition orderSectionDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + if (order == null) + throw new System.ArgumentNullException(nameof(order)); + this.orderSectionDefinition = orderSectionDefinition ?? throw new System.ArgumentNullException(nameof(orderSectionDefinition)); + this.progressReporter = progressReporter; + this.jobManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.JobManager(Skyline.DataMiner.Automation.Engine.SLNetRaw, progressReporter); + GetFieldDescriptors(); + Section = new Skyline.DataMiner.Net.Sections.Section(orderSectionDefinition); + OrderId = order.Id; + OrderIsIntegration = order.IntegrationType != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.None; + } + + public OrderSection(Skyline.DataMiner.Net.Sections.Section section) + { + this.Section = section; + foreach (var fieldValue in section.FieldValues) + { + var fieldDescriptor = fieldValue.GetFieldDescriptor(); + if (fieldDescriptor == null) + continue; + if (fieldDescriptor is Skyline.DataMiner.Net.Sections.ReservationFieldDescriptor) + { + if (fieldValue?.Value == null || fieldValue.Value.Type != typeof(System.Guid)) + throw new System.Exception($"fieldDescriptor {fieldDescriptor.ID} does not contain a Guid"); + orderId = (System.Guid)fieldValue.Value.Value; + orderIdIsValid = true; + } + else if (fieldDescriptor.Name == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.OrderIsIntegrationFieldDescriptorName) + { + if (fieldValue?.Value == null || fieldValue.Value.Type != typeof(bool)) + throw new System.Exception($"fieldDescriptor {fieldDescriptor.ID} does not contain a boolean"); + orderIsIntegration = (bool)fieldValue.Value.Value; + orderIsIntegrationIsValid = true; + } + } + } + + public bool IsValid => orderIdIsValid && orderIsIntegrationIsValid; + public Skyline.DataMiner.Net.Sections.Section Section + { + get; + } + + public System.Guid OrderId + { + get => orderId; + set + { + orderId = value; + Section.AddOrReplaceFieldValue(new Skyline.DataMiner.Net.Sections.FieldValue(reservationFieldDescriptor) + {Value = new Skyline.DataMiner.Net.Sections.ValueWrapper(orderId)}); + orderIdIsValid = true; + } + } + + public bool OrderIsIntegration + { + get => orderIsIntegration; + set + { + orderIsIntegration = value; + Section.AddOrReplaceFieldValue(new Skyline.DataMiner.Net.Sections.FieldValue(isIntegrationFieldDescriptor) + {Value = new Skyline.DataMiner.Net.Sections.ValueWrapper(orderIsIntegration)}); + orderIsIntegrationIsValid = true; + } + } + + private void GetFieldDescriptors() + { + reservationFieldDescriptor = jobManager.GetOrCreateOrderReservationIdFieldDescriptor(orderSectionDefinition); + if (reservationFieldDescriptor == null) + throw new System.Exception($"Unable to get or create reservation Id field descriptor"); + isIntegrationFieldDescriptor = jobManager.GetOrCreateOrderIsIntegrationFieldDescriptor(orderSectionDefinition); + if (isIntegrationFieldDescriptor == null) + throw new System.Exception($"Unable to get or create order is integration field descriptor"); + } + } + } + + namespace Exceptions + { + public class AddOrUpdateEventFailedException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public AddOrUpdateEventFailedException() + { + } + + public AddOrUpdateEventFailedException(string message): base(message) + { + } + + public AddOrUpdateEventFailedException(string message, System.Exception inner): base(message, inner) + { + } + } + + public class EdgeNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public EdgeNotFoundException() + { + } + + public EdgeNotFoundException(int NodeId, System.Guid serviceDefinitionId): base($"Unable to find Edge connected to node {NodeId} in service definition {serviceDefinitionId}") + { + } + + public EdgeNotFoundException(string message): base(message) + { + } + + public EdgeNotFoundException(string message, System.Exception inner): base(message, inner) + { + } + } + + [System.Serializable] + public class ElementByProtocolNotFoundException : System.Exception + { + public ElementByProtocolNotFoundException(string protocolName): base($"Unable to find any active elements with protocol {protocolName} on the DMA.") + { + } + } + + public class ElementNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public ElementNotFoundException() + { + } + + public ElementNotFoundException(string protocol): base($"Unable to find Element with protocol {protocol}") + { + } + + public ElementNotFoundException(string protocol, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.AvidInterplayPAM.InterplayPamElements elementName): base($"Unable to find {protocol} {elementName.ToString()} Element") + { + } + + public ElementNotFoundException(string message, System.Exception inner): base(message, inner) + { + } + } + + public class FunctionDefinitionNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public FunctionDefinitionNotFoundException() + { + } + + public FunctionDefinitionNotFoundException(string name): base($"Unable to find Function Definition with name {name}") + { + } + + public FunctionDefinitionNotFoundException(System.Guid ID): base($"Unable to find Function Definition with ID {ID}") + { + } + + public FunctionDefinitionNotFoundException(string name, System.Guid ID): base($"Unable to find Function Definition with name {name} and ID {ID}") + { + } + + public FunctionDefinitionNotFoundException(string message, System.Exception inner): base(message, inner) + { + } + } + + public class FunctionNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public FunctionNotFoundException() + { + } + + public FunctionNotFoundException(string name, bool labelInsteadOfName = false): base(labelInsteadOfName ? $"Unable to find Function with label {name}" : $"Unable to find Function with name {name}") + { + } + + public FunctionNotFoundException(string name, System.Collections.Generic.IEnumerable options, bool labelInsteadOfName = false): base($"Unable to find Function with {(labelInsteadOfName ? "label" : "name")} {name} among options {string.Join(", ", options)}") + { + } + + public FunctionNotFoundException(System.Guid ID): base($"Unable to find Function with ID {ID}") + { + } + + public FunctionNotFoundException(int NodeId): base($"Unable to find Function with Node ID {NodeId}") + { + } + + public FunctionNotFoundException(string name, System.Guid ID): base($"Unable to find Function with name {name} and ID {ID}") + { + } + + public FunctionNotFoundException(string message, System.Exception inner): base(message, inner) + { + } + } + + public class FunctionParameterNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public FunctionParameterNotFoundException() + { + } + + public FunctionParameterNotFoundException(string name): base($"Unable to find Function Parameter with name {name}") + { + } + + public FunctionParameterNotFoundException(string message, System.Exception inner): base(message, inner) + { + } + } + + [System.Serializable] + public abstract class MediaServicesException : System.Exception + { + protected MediaServicesException() + { + } + + protected MediaServicesException(string message): base(message) + { + } + + protected MediaServicesException(string message, System.Exception inner): base(message, inner) + { + } + + protected MediaServicesException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context): base(info, context) + { + } + } + + public class NodeNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public NodeNotFoundException() + { + } + + public NodeNotFoundException(string message): base(message) + { + } + + public NodeNotFoundException(System.Guid ID): base($"Unable to find Function with ID {ID}") + { + } + + public NodeNotFoundException(string message, System.Exception inner): base(message, inner) + { + } + } + + public class ProfileParameterNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public ProfileParameterNotFoundException() + { + } + + public ProfileParameterNotFoundException(string name, string functionName = null, System.Collections.Generic.IEnumerable collectionThatShouldContainProfileParameter = null): base($"Unable to find Profile Parameter with name {name}{(!string.IsNullOrWhiteSpace(functionName) ? $" in function {functionName}" : string.Empty)}{(collectionThatShouldContainProfileParameter != null ? $" between {string.Join(",", System.Linq.Enumerable.Select(collectionThatShouldContainProfileParameter, p => p.Name))}" : string.Empty)}") + { + } + + public ProfileParameterNotFoundException(System.Guid ID, System.Collections.Generic.IEnumerable options = null): base($"Unable to find Profile Parameter with ID {ID} among options '{string.Join(", ", options)}'") + { + } + + public ProfileParameterNotFoundException(string name, System.Guid ID): base($"Unable to find Profile Parameter with name {name} and ID {ID}") + { + } + + public ProfileParameterNotFoundException(string message, System.Exception inner): base(message, inner) + { + } + } + + public class ReservationNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public ReservationNotFoundException() + { + } + + public ReservationNotFoundException(string name): base($"Unable to find Reservation with name {name}") + { + } + + public ReservationNotFoundException(System.Guid ID): base($"Unable to find Reservation with ID {ID}") + { + } + + public ReservationNotFoundException(string message, System.Exception inner): base($"No Reservation Instance found with ID {message}", inner) + { + } + } + + public class ResourcePoolNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public ResourcePoolNotFoundException() + { + } + + public ResourcePoolNotFoundException(string name): base($"Unable to find Resource Pool with name {name}") + { + } + + public ResourcePoolNotFoundException(string message, System.Exception inner): base(message, inner) + { + } + } + + public class ServiceReservationPropertyNotFoundException : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.MediaServicesException + { + public ServiceReservationPropertyNotFoundException() + { + } + + public ServiceReservationPropertyNotFoundException(string propertyName, string serviceName): base($"Unable to find property {propertyName} on service {serviceName}") + { + } + + public ServiceReservationPropertyNotFoundException(string message, System.Exception inner): base(message, inner) + { + } + } + } + + namespace Function + { + public class Function : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.IYleChangeTracking + { + private Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource resource; + private Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource initialResource; + private System.Collections.Generic.List selectableResources; + public Function() + { + Parameters = new System.Collections.Generic.List(); + InterfaceParameters = new System.Collections.Generic.List(); + SelectableResources = new System.Collections.Generic.List(); + } + + public Function(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservation, Skyline.DataMiner.Net.ServiceManager.Objects.Node serviceDefinitionNode, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition serviceDefinition) + { + if (reservation == null) + throw new System.ArgumentNullException(nameof(reservation)); + if (serviceDefinitionNode == null) + throw new System.ArgumentNullException(nameof(serviceDefinitionNode)); + if (serviceDefinition == null) + throw new System.ArgumentNullException(nameof(serviceDefinition)); + helpers.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function), nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function), out var stopwatch); + var optionsProperty = System.Linq.Enumerable.FirstOrDefault(serviceDefinitionNode.Properties, p => p.Name == "Options"); + var isOptional = optionsProperty != null && optionsProperty.Value.Contains("Optional"); + var configurationOrderProperty = System.Linq.Enumerable.FirstOrDefault(serviceDefinitionNode.Properties, p => p.Name == "ConfigurationOrder"); + var configurationOrder = configurationOrderProperty != null ? System.Convert.ToInt32(configurationOrderProperty.Value) : 0; + var functionDefinition = System.Linq.Enumerable.FirstOrDefault(serviceDefinition.FunctionDefinitions, f => f.Label == serviceDefinitionNode.Label); + Id = serviceDefinitionNode.Configuration.FunctionID; + NodeId = serviceDefinitionNode.ID; + Definition = functionDefinition; + Name = functionDefinition.Name; + ConfigurationOrder = configurationOrder; + Parameters = new System.Collections.Generic.List(); + InterfaceParameters = new System.Collections.Generic.List(); + IsOptional = isOptional; + // update function parameters and resource + var functionInReservation = System.Linq.Enumerable.FirstOrDefault(Skyline.DataMiner.Library.Solutions.SRM.ReservationInstanceExtensions.GetFunctionData(reservation), f => f.Id == NodeId); + var resourceUsageDefinition = System.Linq.Enumerable.FirstOrDefault(reservation.ResourcesInReservationInstance, r => (r is Skyline.DataMiner.Net.ResourceManager.Objects.ServiceResourceUsageDefinition) && (r as Skyline.DataMiner.Net.ResourceManager.Objects.ServiceResourceUsageDefinition).ServiceDefinitionNodeID == NodeId); + UpdateFunctionProfileParametersAndResource(helpers, functionInReservation, resourceUsageDefinition); + helpers.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function), nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function), null, stopwatch); + } + + /// + /// The id of this function, this matches the Id of the FunctionDefinition. + /// Only required when action is "NEW" or "EDIT" + /// s + public System.Guid Id + { + get; + set; + } + + /// + /// The name of this function, this matches the name of the FunctionDefinition. + /// + public string Name + { + get; + set; + } + + /// + /// The node id of this function node in the service definition + /// Only required when action is "NEW" or "EDIT" + /// + public int NodeId + { + get; + set; + } + + /// + /// The configuration order property value in the service definition. + /// + public int ConfigurationOrder + { + get; + set; + } + + /// + /// The list of parameters for the service + /// Only required when action is "NEW" or "EDIT" + /// + public System.Collections.Generic.List Parameters + { + get; + set; + } + + public System.Collections.Generic.List InterfaceParameters + { + get; + set; + } + + [Newtonsoft.Json.JsonIgnore] + public System.Collections.Generic.IEnumerable NonDtrNonAudioProfileParameters + { + get + { + return System.Linq.Enumerable.Where(Parameters, p => !p.IsNonInterfaceDtrParameter && !System.Linq.Enumerable.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.AllAudioChannelConfigurationGuids, p.Id)); + } + } + + public System.Collections.Generic.IEnumerable Capabilities => System.Linq.Enumerable.Concat(System.Linq.Enumerable.Where(Parameters, p => p.IsCapability), System.Linq.Enumerable.Where(InterfaceParameters, p => p.IsCapability)); + /// + /// Gets or sets the resource used for this function. + /// Should never be passed (internal property). + /// + public Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource Resource + { + get => resource; + set + { + if (resource != null && resource.Equals(value)) + return; + resource = value; + // Clear Other Satellite Name profile parameter in case of Satellite Function and selected Resource is not Other + if (Name.Equals("Satellite", System.StringComparison.InvariantCultureIgnoreCase) && resource != null && !resource.Name.Equals("Other", System.StringComparison.InvariantCultureIgnoreCase)) + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter otherSatelliteNameProfileParameter = System.Linq.Enumerable.FirstOrDefault(Parameters, x => x.Name.Equals("Other Satellite Name", System.StringComparison.InvariantCultureIgnoreCase)); + if (otherSatelliteNameProfileParameter != null) + otherSatelliteNameProfileParameter.Value = System.String.Empty; + } + + ResourceChanged?.Invoke(this, new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function.ResourceChangedEventArgs(ResourceName)); + } + } + + /// + /// Property used by UI. + /// + public string ResourceName => Resource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(Resource, Id) : "None"; + public event System.EventHandler ResourceChanged; + /// + /// A collection of selectable Resources. Set by Controller and used by UI. + /// + [Newtonsoft.Json.JsonIgnore] + public System.Collections.Generic.List SelectableResources + { + get => selectableResources; + set + { + selectableResources = value; + SelectableResourcesChanged?.Invoke(this, new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function.SelectableResourcesChangedEventArgs(SelectableResourceNames)); + } + } + + /// + /// Property used by UI. + /// + [Newtonsoft.Json.JsonIgnore] + public System.Collections.Generic.IEnumerable SelectableResourceNames + { + get + { + var selectableResourceNames = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Select(SelectableResources, r => Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(r, Id))); + selectableResourceNames.Add("None"); + return selectableResourceNames; + } + } + + public event System.EventHandler SelectableResourcesChanged; + /// + /// Gets a boolean indicating if Change Tracking is enabled. + /// + /// + [Newtonsoft.Json.JsonIgnore] + public bool ChangeTrackingEnabled + { + get; + private set; + } + + /// + /// Gets a boolean indicating if this object has been changed since object construction or since last call. + /// + /// + [Newtonsoft.Json.JsonIgnore] + public bool IsChanged => ChangeInfo.IsChanged; + /// + /// Gets an object containing all change info since object construction or since last call. + /// + /// + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo ChangeInfo => GetChanges(); + /// + /// Function Definition for this function. + /// Used in the function sections. + /// + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.FunctionDefinition Definition + { + get; + set; + } + + /// + /// Indicates if this node is optional or not + /// Only required when action is "NEW" or "EDIT" + /// This can be read out from the "Options" property on the node, value will be "Optional" in case the node is optional + /// + public bool IsOptional + { + get; + set; + } + + public bool RequiresResource + { + get; + set; + } + + = true; + public bool McrHasOverruledFixedTieLineLogic + { + get; + set; + } + + = false; + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Configuration.FunctionConfiguration Configuration + { + get + { + var functionConfiguration = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Configuration.FunctionConfiguration{Id = Id, Name = Name, ResourceId = Resource?.ID ?? System.Guid.Empty, ResourceName = ResourceName, ProfileParameters = new System.Collections.Generic.Dictionary(), RequiresResource = RequiresResource, McrHasOverruledFixedTieLineLogic = McrHasOverruledFixedTieLineLogic}; + if (Parameters != null) + { + foreach (var functionParameter in Parameters) + functionConfiguration.ProfileParameters[functionParameter.Id] = functionParameter.Value; + } + + if (InterfaceParameters != null) + { + foreach (var functionParameter in InterfaceParameters) + functionConfiguration.ProfileParameters[functionParameter.Id] = functionParameter.Value; + } + + return functionConfiguration; + } + } + + public void UpdateFunctionProfileParametersAndResource(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.Library.Solutions.SRM.Model.Function functionInReservation, Skyline.DataMiner.Net.Messages.ResourceUsageDefinition resourceUsageDefinition) + { + if (functionInReservation == null) + throw new System.ArgumentNullException(nameof(functionInReservation)); + foreach (var reservationProfileParameter in functionInReservation.Parameters) + { + var functionProfileParameter = System.Linq.Enumerable.FirstOrDefault(Parameters, p => p.Id == reservationProfileParameter.Id); + if (functionProfileParameter == null) + { + functionProfileParameter = helpers.ProfileManager.GetProfileParameter(reservationProfileParameter.Id); + Parameters.Add(functionProfileParameter); + } + + functionProfileParameter.Value = reservationProfileParameter.Value; + } + + foreach (var reservationInterfaceProfileParameter in System.Linq.Enumerable.SelectMany(functionInReservation.AllInterfacesInFunction, i => i.Parameters)) + { + var functionInterfaceProfileParameter = System.Linq.Enumerable.FirstOrDefault(InterfaceParameters, p => p.Id == reservationInterfaceProfileParameter.Id); + if (functionInterfaceProfileParameter == null) + { + functionInterfaceProfileParameter = helpers.ProfileManager.GetProfileParameter(reservationInterfaceProfileParameter.Id); + InterfaceParameters.Add(functionInterfaceProfileParameter); + } + + functionInterfaceProfileParameter.Value = reservationInterfaceProfileParameter.Value; + } + + if (resourceUsageDefinition != null && resourceUsageDefinition.GUID != System.Guid.Empty) + { + Resource = (Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource)Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ResourceManager.GetResource(resourceUsageDefinition.GUID); + } + else + { + Resource = null; + } + } + + /// + /// Gets the types of changes that this function underwent since construction or since last call. + /// + /// A flags enum containing the types of changes that this function underwent. + /// + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo GetChanges() + { + var changeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo(); + bool resourceWasAdded = initialResource == null && Resource != null; + bool resourceWasRemoved = initialResource != null && Resource == null; + bool resourceWasChanged = initialResource != null && Resource != null && initialResource.ID != Resource.ID; + if (resourceWasAdded || resourceWasChanged) + changeInfo.ResourceChangeInfo.MarkResourceAddedOrSwapped(); + else if (resourceWasRemoved) + changeInfo.ResourceChangeInfo.MarkResourceRemoved(); + var allProfileParameters = System.Linq.Enumerable.Concat(Parameters, InterfaceParameters); + foreach (var parameter in allProfileParameters) + changeInfo.CombineWith(parameter.ChangeInfo); + return changeInfo; + } + + /// + /// Resets Change Tracking. + /// + /// + public void AcceptChanges() + { + initialResource = Resource; + foreach (var parameter in System.Linq.Enumerable.Concat(Parameters, InterfaceParameters)) + parameter.AcceptChanges(); + } + + public class ResourceChangedEventArgs : System.EventArgs + { + internal ResourceChangedEventArgs(string resourceName) + { + ResourceName = resourceName; + } + + public string ResourceName + { + get; + private set; + } + } + + public class SelectableResourcesChangedEventArgs : System.EventArgs + { + internal SelectableResourcesChangedEventArgs(System.Collections.Generic.IEnumerable selectableResourceNames) + { + SelectableResourceNames = selectableResourceNames; + } + + public System.Collections.Generic.IEnumerable SelectableResourceNames + { + get; + private set; + } + } + } + + public class FunctionDefinition + { + public System.Guid Id + { + get; + set; + } + + public string Name + { + get; + set; + } + + /// + /// The label assigned to this function definition in the service definition. + /// + public string Label + { + get; + set; + } + + public int ConfigurationOrder + { + get; + internal set; + } + + public string Options + { + get; + internal set; + } + + public string ResourcePool + { + get; + internal set; + } + + public bool IsHidden + { + get; + internal set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileDefinition ProfileDefinition + { + get; + internal set; + } + + public System.Collections.Generic.Dictionary InterfaceProfileDefinitions + { + get; + internal set; + } + + public System.Collections.Generic.List Children + { + get; + internal set; + } + + /// + /// Indicates if manual resource selection is allowed for this node in the service definition. + /// Note that this is only applicable when retrieved via the service definition. + /// + public bool IsManualResourceSelectionAllowed + { + get; + internal set; + } + } + } + + namespace IngestExport + { + public enum Type + { + [System.ComponentModel.Description("Export")] + Export = 0, + [System.ComponentModel.Description("Import")] + Import = 1, + [System.ComponentModel.Description("Iplay Folder Creation")] + IplayFolderCreation = 2, + [System.ComponentModel.Description("Iplay WG Transfer")] + IplayWgTransfer = 3, + [System.ComponentModel.Description("Non-Interplay Project")] + NonInterplayProject = 4 + } + + public enum State + { + [System.ComponentModel.Description("Preliminary")] + Preliminary = 0, + [System.ComponentModel.Description("Submitted")] + Submitted = 1, + [System.ComponentModel.Description("Work in Progress")] + WorkInProgress = 2, + [System.ComponentModel.Description("Change Requested")] + ChangeRequested = 3, + [System.ComponentModel.Description("Completed")] + Completed = 4, + [System.ComponentModel.Description("Cancelled")] + Cancelled = 5 + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("InteractiveAutomationToolkit.dll")] + public abstract class NonLiveOrder + { + public const string DefaultOwner = "None"; + public const string OrderDescriptionTicketField = "Order Description"; + public const string DeadlineTicketField = "Deadline"; + public const string StartTimeTicketField = "Start Time"; + public const string OwnerTicketField = "Owner"; + public const string TypeTicketField = "Type"; + public const string DataTicketField = "Data"; + public const string StateTicketField = "State"; + public const string MaterialSourceTicketField = "Material Source"; + public const string ProgramNameTicketField = "Program Name"; + public const string DeliveryDateTicketField = "Delivery Date"; + public const string SourceFolderPathTicketField = "Source Folder Path"; + public const string TargetFolderPathTicketField = "Target Folder Path"; + public const string InterplayFolderPathTicketField = "Interplay Folder Path"; + public const string ExportInformationSubtitleAttachmentsPathTicketField = "Subtitle Attachments Path"; + public const string AdditionalInformationTicketField = "Additional Information"; + public const string CreatedByTicketField = "Created By"; + public const string ModifiedByTicketField = "Modified By"; + public const string LastModifiedByTicketField = "Last Modified By"; + public const string ShortDescriptionTicketField = "Short Description"; + public const string ReasonOfRejectionField = "Reason of Rejection"; + public const string TeamHkiField = "Team_HKI"; + public const string TeamNewsField = "Team_NEWS"; + public const string TeamTreField = "Team_TRE"; + public const string TeamVsaField = "Team_VSA"; + public const string TeamMgmtField = "Team_MGMT"; + /// + /// Default constructor that was added so all fields are always included in the auto-generated EXE block in the Automation Scripts. + /// This caused issues in the past were data was lost because properties were not filled out when deserializing and serializing an object of this type. + /// HIGHLY RECOMMENDED for all classes that are serialized in a Class Library. + /// + protected NonLiveOrder() + { + DataMinerId = default(int? ); + TicketId = default(int? ); + State = default(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.State); + OrderDescription = default(string); + Deadline = default(System.DateTime); + Owner = default(string); + CreatedBy = default(string); + ModifiedBy = new System.Collections.Generic.HashSet(); + ReasonOfRejection = default(string); + TeamHki = default(bool); + TeamNews = default(bool); + TeamTre = default(bool); + TeamVsa = default(bool); + TeamMgmt = default(bool); + } + + public abstract Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.Type OrderType + { + get; + } + + public abstract string ShortDescription + { + get; + } + + public int? DataMinerId + { + get; + set; + } + + public int? TicketId + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.State State + { + get; + set; + } + + public string OrderDescription + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty] + public System.DateTime Deadline + { + get; + set; + } + + public System.DateTime StartTime + { + get + { + return Deadline - System.TimeSpan.FromHours(1); + } + } + + /// + /// Gets or sets the user to which the ticket is assigned. + /// + public string Owner + { + get; + set; + } + + /// + /// Gets or sets the user that created the ticket. + /// + public string CreatedBy + { + get; + set; + } + + /// + /// Gets or sets the user that updated the ticket. + /// + public string LastModifiedBy + { + get; + set; + } + + /// + /// Gets or sets the uses that modified the ticket. + /// + public System.Collections.Generic.HashSet ModifiedBy + { + get; + set; + } + + public string ReasonOfRejection + { + get; + set; + } + + public bool TeamHki + { + get; + set; + } + + public bool TeamNews + { + get; + set; + } + + public bool TeamTre + { + get; + set; + } + + public bool TeamVsa + { + get; + set; + } + + public bool TeamMgmt + { + get; + set; + } + + public bool IsAssignedToSomeone => !string.IsNullOrWhiteSpace(Owner) && Owner.ToLower() != DefaultOwner.ToLower(); + } + + namespace Transfer + { + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class Transfer : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.NonLiveOrder + { + /// + /// Default constructor that was added so all fields are always included in the auto-generated EXE block in the Automation Scripts. + /// This caused issues in the past were data was lost because properties were not filled out when deserializing and serializing an object of this type. + /// HIGHLY RECOMMENDED for all classes that are serialized in a Class Library. + /// + public Transfer() + { + Source = default(string); + SourceFolder = default(string); + FileUrls = default(string[]); + FileType = default(string); + Destination = default(string); + ReceiverEmailAddress = default(string); + InterplayDestinationFolder = default(string); + AdditionalCustomerInformation = default(string); + } + + [Newtonsoft.Json.JsonProperty] + public override Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.Type OrderType + { + get + { + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.Type.IplayWgTransfer; + } + } + + [Newtonsoft.Json.JsonIgnore] + public override string ShortDescription + { + get => OrderDescription + " - " + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.Type.IplayWgTransfer) + " - " + Source + " to " + Destination; + } + + public string Source + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string SourceFolder + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string[] FileUrls + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string FileType + { + get; + set; + } + + public string Destination + { + get; + set; + } + + public string ReceiverEmailAddress + { + get; + set; + } + + public string InterplayDestinationFolder + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty] + public string AdditionalCustomerInformation + { + get; + set; + } + } + } + } + + namespace Integrations + { + public enum IntegrationType + { + [System.ComponentModel.Description("None")] + None = 0, + [System.ComponentModel.Description("Ceiton")] + Ceiton = 1, + [System.ComponentModel.Description("Plasma")] + Plasma = 2, + [System.ComponentModel.Description("Feenix")] + Feenix = 3, + [System.ComponentModel.Description("Eurovision")] + Eurovision = 4, + [System.ComponentModel.Description("Pebble Beach Marina")] + PebbleBeachMarina = 5 + } + + namespace Eurovision + { + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class AudioChannel + { + public string AudioChannelCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string AudioChannelOtherText + { + get; + set; + } + } + + public enum Type + { + [System.ComponentModel.Description("None")] + None, + [System.ComponentModel.Description("News Event")] + NewsEvent, + [System.ComponentModel.Description("Program Event")] + ProgramEvent, + [System.ComponentModel.Description("Satellite Capacity")] + SatelliteCapacity, + [System.ComponentModel.Description("Unilateral Transmission")] + UnilateralTransmission, + [System.ComponentModel.Description("OSS Transmission")] + OSSTransmission + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class EurovisionBookingDetails + { + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.Type Type + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string EventId + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string MultilateralTransmissionId + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string SatelliteId + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string TransportableId + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.DateTime? Start + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.DateTime? End + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string DestinationOrganizationCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string DestinationCityCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string OriginOrganizationCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string OriginCityCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Contact + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Description + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Note + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string LineUp + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Phone + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Email + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string ContractCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string FeedpointCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string FacilityProductId + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string VideoDefinitionCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string VideoResolutionCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string VideoAspectRatioCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string VideoBitrateCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string VideoFrameRateCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string VideoBandwidthCode + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.AudioChannel AudioChannel1 + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.AudioChannel AudioChannel2 + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.AudioChannel AudioChannel3 + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.AudioChannel AudioChannel4 + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.AudioChannel AudioChannel5 + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.AudioChannel AudioChannel6 + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.AudioChannel AudioChannel7 + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.AudioChannel AudioChannel8 + { + get; + set; + } + } + } + } + + namespace Locking + { + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class ExternalRequestLockResponse + { + [Newtonsoft.Json.JsonProperty("Id", Required = Newtonsoft.Json.Required.Always)] + public string Id + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty("ObjectType", Required = Newtonsoft.Json.Required.Always)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking.ObjectTypes ObjectType + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty("ObjectId", Required = Newtonsoft.Json.Required.Always)] + public string ObjectId + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty("Username", Required = Newtonsoft.Json.Required.Always)] + public string Username + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty("ReleaseLocksAfter", Required = Newtonsoft.Json.Required.Always)] + public System.TimeSpan ReleaseLocksAfter + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty("IsLockGranted", Required = Newtonsoft.Json.Required.Always)] + public bool IsLockGranted + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty("IsLockExtended", Required = Newtonsoft.Json.Required.Always)] + public bool IsLockExtended + { + get; + set; + } + } + + public class LockManager + { + private readonly Skyline.DataMiner.Automation.Element orderManagerElement; + private readonly string username; + private readonly Skyline.DataMiner.Automation.IEngine engine; + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter; + private readonly System.Collections.Generic.Dictionary> locks = new System.Collections.Generic.Dictionary>(); + /// + /// Initializes a new LockManager. + /// + /// Link with DataMiner. + /// Thrown when the provided Engine is null. + /// Thrown when no active Order Manager Element is found on the DMS. + public LockManager(Skyline.DataMiner.Automation.IEngine engine, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + this.engine = engine ?? throw new System.ArgumentNullException(nameof(engine)); + this.engine.SetFlag(Skyline.DataMiner.Automation.RunTimeFlags.NoKeyCaching); + this.progressReporter = progressReporter; + username = engine.UserLoginName; + orderManagerElement = System.Linq.Enumerable.FirstOrDefault(engine.FindElementsByProtocol(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.OrderManagerProtocol.Name)) ?? throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ElementByProtocolNotFoundException(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.OrderManagerProtocol.Name); + locks.Add(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking.ObjectTypes.Event, new System.Collections.Generic.Dictionary()); + locks.Add(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking.ObjectTypes.Order, new System.Collections.Generic.Dictionary()); + } + + private System.Collections.Generic.Dictionary InternalEventLocks + { + get + { + return locks[Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking.ObjectTypes.Event]; + } + } + + private System.Collections.Generic.Dictionary InternalOrderLocks + { + get + { + return locks[Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking.ObjectTypes.Order]; + } + } + + /// + /// Returns a value indicating if all of the requested Event locks are granted or not. + /// + public bool AreEventLocksGranted + { + get + { + return System.Linq.Enumerable.All(InternalEventLocks, x => x.Value.IsLockGranted); + } + } + + /// + /// Returns a value indicating if all of the requested Order locks are granted or not. + /// + public bool AreOrderLocksGranted + { + get + { + return System.Linq.Enumerable.All(InternalOrderLocks, x => x.Value.IsLockGranted); + } + } + + /// + /// Returns a value indicating if all of the requested locks (regardless if they are Event or Order locks) are granted or not. + /// + public bool AreLocksGranted + { + get + { + return AreEventLocksGranted && AreOrderLocksGranted; + } + } + } + + public enum ObjectTypes + { + Event = 0, + Order = 1 + } + } + + namespace Notes + { + public interface INoteManager + { + } + + public class NoteManager : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notes.INoteManager + { + private const string TicketDomainName = "Notes"; + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Ticketing.TicketingManager ticketingManager; + public NoteManager(Skyline.DataMiner.Automation.IEngine engine) + { + if (engine == null) + throw new System.ArgumentNullException("engine"); + ticketingManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Ticketing.TicketingManager(engine, TicketDomainName); + } + } + } + + namespace Order + { + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class BillingInfo + { + public BillingInfo() + { + BillableCompany = default(string); + CustomerCompany = default(string); + } + + public string BillableCompany + { + get; + set; + } + + public string CustomerCompany + { + get; + set; + } + } + + public enum BackupType + { + [System.ComponentModel.Description("None")] + None = 0, + [System.ComponentModel.Description("Cold Backup")] + Cold = 1, + [System.ComponentModel.Description("Standby Backup")] + StandBy = 2, + [System.ComponentModel.Description("Active Backup")] + Active = 3 + } + + public enum OrderType + { + Video = 0, + Radio = 1 + } + + public enum Status + { + /// + /// Order which may or may not happen. + /// Could be that only generic order details are filled in. + /// Mandatory fields in service configurations are at this point not mandatory yet. + /// + [System.ComponentModel.Description("Preliminary")] + Preliminary = 0, + /// + /// Preliminary order is completed. + /// This means the order has at least one source and one destination. + /// + [System.ComponentModel.Description("Planned")] + Planned = 1, + /// + /// Order which is rejected by an operator. + /// This will be the case if the order is not possible to be produced or is wrongly configured. + /// + [System.ComponentModel.Description("Rejected")] + Rejected = 2, + /// + /// Order which is confirmed by operator manually or is automatically generated with proper information. + /// + [System.ComponentModel.Description("Confirmed")] + Confirmed = 3, + /// + /// Order which was previously confirmed by operator but was changed after that by customer. + /// Order which was created automatically by integrations and set as confirmed and was changed withing 24h of the start of the order. + /// + [System.ComponentModel.Description("Change Requested")] + ChangeRequested = 4, + /// + /// Order where at least one service is in running state. + /// Only routing and recording services can be added at this point. + /// + [System.ComponentModel.Description("Running")] + Running = 5, + /// + /// Order that contains running recording services and all live services are completed. + /// + [System.ComponentModel.Description("File Processing")] + FileProcessing = 6, + /// + /// All services are in post roll or successfully completed in the order. + /// + [System.ComponentModel.Description("Completed")] + Completed = 7, + /// + /// One or more services are completed with errors in the order. + /// + [System.ComponentModel.Description("Completed With Errors")] + CompletedWithErrors = 8, + /// + /// Order was cancelled. + /// + [System.ComponentModel.Description("Cancelled")] + Cancelled = 9, + /// + /// EBU Order was manually booked and a request for one or more services has been sent to EBU. + /// When an order has this state it is saved until booked by the HandleIntegrationUpdate script with the synopsis information received from EBU. + /// + [System.ComponentModel.Description("Waiting for EBU")] + WaitingOnEbu = 10, + /// + /// When an order has this state it is saved until the mcr operator fills in the missing details and confirms. Then the order will be booked if the timespan is within 1 week. + /// + [System.ComponentModel.Description("Planned Unknown Source")] + PlannedUnknownSource = 11 + } + + public interface IOrderManager + { + System.Collections.Generic.IEnumerable GetAllOrders(); + } + + public class LiteOrder + { + public static readonly char[] OrderNameDisallowedCharacters = new[]{'<', '>', ':', '"', '/', '\\', '|', '?', '*'}; + public const string PropertyNameEventId = "EventId"; + public const string PropertyNameType = "Type"; + public const string PropertyNameIntegration = "Integration"; + public const string PropertyNameStatus = "Status"; + public const string PropertyNameUsergroups = "UserGroups"; + public const string PropertyNameInternal = "Internal"; + public const string PropertyNamePlasmaId = "PlasmaId"; + public const string PropertyNameEurovisionId = "EurovisionId"; + public const string PropertyNameEurovisionTransmissionNumber = "EurovisionTransmissionNumber"; + public const string PropertyNameOrderchanges = "OrderChanges"; + public const string PropertyNameCreatedBy = "CreatedBy"; + public const string PropertyNameLastUpdatedBy = "Last Updated By"; + public const string PropertyNameOperatorNotes = "OperatorNotes"; + public const string PropertyNameErrorDescription = "ErrorDescription"; + public const string PropertyNameReasonForCancellationOrRejection = "ReasonForCancellationOrRejection"; + public const string PropertyNameComments = "Comments"; + public const string PropertyNameShortDescription = "Short Description"; + public const string PropertyNameRecurrence = "Recurrence"; + public const string PropertyNameFromTemplate = "FromTemplate"; + public const string PropertyNameBillingInfo = "BillingInfo"; + //public const string PropertyNameStartWithoutPreroll = "StartWithoutPreroll"; + //public const string PropertyNameEndWithoutPostroll = "EndWithoutPostroll"; + public const string PropertyNameUiTeamMessiLive = "UI_Team_Messi_Live"; + public const string PropertyNameUiTeamMessiNews = "UI_Team_Messi_News"; + public const string PropertyNameUiAreena = "UI_Areena"; + public const string PropertyNameUiPlasma = "UI_Plasma"; + public const string PropertyNameUiMessiNewsRec = "UI_Messi_News_Rec"; + public const string PropertyNameUiTomTre = "UI_TRE"; + public const string PropertyNameUiTomSho = "UI_SHO"; + public const string PropertyNameUiTomNews = "UI_News"; + public const string PropertyNameUiTomSvenska = "UI_Svenska"; + public const string PropertyNameUiMcrChange = "UI_MCR_Change"; + public const string PropertyNameUiRecording = "UI_Recording"; + public const string PropertyNameUiOffice = "UI_Office"; + public const string PropertyNameUiMcrSpecialist = "UI_Fiber"; + public const string PropertyNameIsLocked = "IsLocked"; + public const string PropertyNameSportsplanningSport = "SportsPlanning_Sport"; + public const string PropertyNameSportsplanningDescr = "SportsPlanning_Description"; + public const string PropertyNameSportsplanningCommentary = "SportsPlanning_Commentary"; + public const string PropertyNameSportsplanningCommentary2 = "SportsPlanning_Commentary2"; + public const string PropertyNameSportsplanningCompetitionTime = "SportsPlanning_CompetitionTime"; + public const string PropertyNameSportsplanningJournalist1 = "SportsPlanning_JournalistOne"; + public const string PropertyNameSportsplanningJournalist2 = "SportsPlanning_JournalistTwo"; + public const string PropertyNameSportsplanningJournalist3 = "SportsPlanning_JournalistThree"; + public const string PropertyNameSportsplanningLocation = "SportsPlanning_Location"; + public const string PropertyNameSportsplanningTechResources = "SportsPlanning_TechnicalResources"; + public const string PropertyNameSportsplanningLivehighlights = "SportsPlanning_LiveHighlightsFile"; + public const string PropertyNameSportsplanningReqBroadcastTime = "SportsPlanning_RequestedBroadcastTime"; + public const string PropertyNameSportsplanningProdNrPlasmaId = "SportsPlanning_ProductionNumberPlasmaId"; + public const string PropertyNameSportsplanningProdNrCeiton = "SportsPlanning_ProductNumberCeiton"; + public const string PropertyNameSportsplanningCostDep = "SportsPlanning_CostDepartment"; + public const string PropertyNameSportsplanningAdditionalInformation = "SportsPlanning_AdditionalInformation"; + public const string PropertyNameNewsInformationNewsCameraOperator = "NewsInformation_NewsCameraOperator"; + public const string PropertyNameNewsInformationJournalist = "NewsInformation_Journalist"; + public const string PropertyNameNewsInformationVirveCommandGroupOne = "NewsInformation_VirveCommandGroupOne"; + public const string PropertyNameNewsInformationVirveCommandGroupTwo = "NewsInformation_VirveCommandGroupTwo"; + public const string PropertyNameNewsInformationAdditionalInformation = "NewsInformation_AdditionalInformation"; + public const string PropertyNameAudioReturnInfo = "AudioReturnInfo"; + public const string PropertyNameLiveUDeviceNames = "LiveUDeviceNames"; + public const string PropertyNameVidigoStreamSourceLinks = "VidigoStreamSourceLinks"; + public const string PropertyNamePlasmaIdsForArchiving = "PlasmaIdsForArchiving"; + public const string PropertyNameServiceConfigurations = "ServiceConfigurations"; + public const string PropertyNameStartnow = "StartNow"; + public const string PropertyNameFixedSourcePlasma = "Fixed_Source_Plasma"; + public const string PropertyNameYleId = "YleId"; + public const string PropertyNameSources = "Sources"; + public const string PropertyNameDestinations = "Destinations"; + public const string PropertyNameRecordings = "Recordings"; + public const string PropertyNameTransmissions = "Transmissions"; + private System.DateTime start; + private System.DateTime end; + /// + /// Reservation object for the order. Saved as property for performance reasons. + /// + public Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance Reservation + { + get; + set; + } + + /// + /// Reservation instance ID of the order. + /// + public System.Guid Id + { + get; + set; + } + + /// + /// The event this order belongs to. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event Event + { + get; + set; + } + + /// + /// Name of the order. + /// + public string Name + { + get; + set; + } + + /// + /// Used by UI. + /// + public string ShortDescription => Name; + /// + /// Start date and time of the order. + /// + public System.DateTime Start + { + get => start; + set + { + if (start != value) + { + start = value; + StartChanged?.Invoke(this, start); + } + } + } + + internal event System.EventHandler StartChanged; + /// + /// End date and time of the order. + /// + public System.DateTime End + { + get => end; + set + { + if (end != value) + { + end = value; + EndChanged?.Invoke(this, end); + } + } + } + + internal event System.EventHandler EndChanged; + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurringSequenceInfo RecurringSequenceInfo + { + get; + set; + } + + /// + /// The status of this order. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status Status + { + get; + set; + } + + /// + /// Comments for the order. + /// + public string Comments + { + get; + set; + } + + /// + /// The type of this order. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderType Type + { + get; + set; + } + + /// + /// Indicates which integration created this Order. + /// If not specified this will be set to None. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType IntegrationType + { + get; + set; + } + + /// + /// Id of the Program provided by the Plasma/MediaGenix integration. + /// This will only applicable when the IntegrationType is Plasma. + /// + public string PlasmaId + { + get; + set; + } + + /// + /// Id of the Plasma Program or Feenix Order in YLE. + /// + public string YleId + { + get; + set; + } + + /// + /// A list containing IDs of the User Groups that are allowed to see/edit this order. + /// + public System.Collections.Generic.HashSet UserGroupIds + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.SportsPlanning SportsPlanning + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.NewsInformation NewsInformation + { + get; + set; + } + + /// + /// The name of the contract that should be used to create the event. + /// + public string Contract + { + get; + set; + } + + /// + /// The name of the company that should be used to create the event. + /// + public string Company + { + get; + set; + } + + /// + /// Gets or sets a value indicating whether an order is part of an internal event or not. + /// + public bool IsInternal + { + get; + set; + } + + /// + /// Login name of the user that created the Order. + /// + public string CreatedByUserName + { + get; + set; + } + + /// + /// Login name of the user that last modified the Order. + /// + public string LastUpdatedBy + { + get; + set; + } + + /// + /// Notes that can only be seen and updated by an MCR user from the CustomerUI. + /// + public string OperatorNotes + { + get; + set; + } + + /// + /// Gets or sets the description that should be filled out by an MCR user when the Order was completed with errors. + /// If the order was completed with errors and this value is not filled out, then the order should be visible in the UI_MCR_Change and UI_Recording views. + /// + public string ErrorDescription + { + get; + set; + } + + /// + /// Gets or sets a property containing the reason why a user has rejected or canceled an Order. + /// + public string ReasonForCancellationOrRejection + { + get; + set; + } + + /// + /// A list of the changes that were made to the order. + /// + public System.Collections.Generic.List OrderChanges + { + get; + set; + } + + /// + /// Gets a collection of Cube View IDs of views where this order is visible. + /// + public System.Collections.Generic.HashSet SecurityViewIds + { + get; + set; + } + + = new System.Collections.Generic.HashSet(); + /// + /// Indicates whether the Order should start as soon as possible or not. + /// + public bool StartNow + { + get; + set; + } + + = false; + /// + /// Indicates whether the Order should stop immediately. + /// + public bool StopNow + { + get; + set; + } + + = false; + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.BillingInfo BillingInfo + { + get; + set; + } + + /// + /// Indicates if this order can be cancelled. + /// + public bool CanCancel + { + get + { + return Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Preliminary || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.WaitingOnEbu || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Planned || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Rejected || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Confirmed || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.ChangeRequested || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.FileProcessing || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Running; + } + } + + /// + /// Indicates if this order can be rejected. + /// + public bool CanReject + { + get => Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Planned; + } + + /// + /// Indicates if this order can be confirmed. + /// + public bool CanConfirm + { + get + { + return Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Planned || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.ChangeRequested; + } + } + + /// + /// Indicates if this order can be deleted. + /// + public bool CanDelete + { + get + { + return Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Rejected || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Cancelled || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Completed || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.CompletedWithErrors; + } + } + + public bool IsSaved => (Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Preliminary || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.WaitingOnEbu || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.PlannedUnknownSource); + /// + /// Indication if the order is generated from a template. + /// + public bool IsCreatedFromTemplate + { + get; + set; + } + + public string ExternalJsonFilePath + { + get; + set; + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class NewsInformation : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.IYleChangeTracking + { + private string initialNewsCameraOperator; + private string initialJournalist; + private string initialVirveCommandGroupOne; + private string initialVirveCommandGroupTwo; + private string initialAdditionalInformation; + public string NewsCameraOperator + { + get; + set; + } + + public string Journalist + { + get; + set; + } + + public string VirveCommandGroupOne + { + get; + set; + } + + public string VirveCommandGroupTwo + { + get; + set; + } + + public string AdditionalInformation + { + get; + set; + } + + /// + /// Gets a boolean indicating if Change Tracking has been enabled for this object. + /// + /// + public bool ChangeTrackingEnabled + { + get; + private set; + } + + /// + /// Gets a boolean indicating if this object has been changed since object construction or since last call. + /// + /// + public bool IsChanged => ChangeInfo.IsChanged; + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo ChangeInfo => GetChanges(); + /// + /// Gets the type of changes that have happened since object creation or since last call. + /// + /// A flags enum containing the types of changes. + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo GetChanges() + { + var changeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo(); + if (initialNewsCameraOperator != NewsCameraOperator) + changeInfo.MarkCustomPropertiesChanged(); + if (initialJournalist != Journalist) + changeInfo.MarkCustomPropertiesChanged(); + if (initialVirveCommandGroupOne != VirveCommandGroupOne) + changeInfo.MarkCustomPropertiesChanged(); + if (initialVirveCommandGroupTwo != VirveCommandGroupTwo) + changeInfo.MarkCustomPropertiesChanged(); + if (initialAdditionalInformation != AdditionalInformation) + changeInfo.MarkCustomPropertiesChanged(); + return changeInfo; + } + + /// + /// Resets Change Tracking. + /// + /// + public void AcceptChanges() + { + initialNewsCameraOperator = NewsCameraOperator; + initialJournalist = Journalist; + initialVirveCommandGroupOne = VirveCommandGroupOne; + initialVirveCommandGroupTwo = VirveCommandGroupTwo; + initialAdditionalInformation = AdditionalInformation; + } + + public override string ToString() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.None); + } + + public override bool Equals(object obj) + { + if (!(obj is NewsInformation other)) + return false; + bool equal = true; + foreach (var property in typeof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.NewsInformation).GetProperties()) + { + equal &= property.GetValue(this).Equals(property.GetValue(other)); + } + + return equal; + } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 23 + NewsCameraOperator.GetHashCode(); + hash = hash * 23 + Journalist.GetHashCode(); + hash = hash * 23 + VirveCommandGroupOne.GetHashCode(); + hash = hash * 23 + VirveCommandGroupTwo.GetHashCode(); + hash = hash * 23 + AdditionalInformation.GetHashCode(); + return hash; + } + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + public class Order : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.LiteOrder + { + public const int StartNowDelayInMinutes = 30; + public const int StartInTheFutureDelayInMinutes = 10; + public const string ServiceBookingEventName = "Service Booking"; + public const string HandleOrderActionScriptName = "HandleOrderAction"; + public const string HandleOrderActionScriptReservationGuidParameterName = "ReservationGuid"; + public const string HandleOrderActionScriptActionParameterName = "Action"; + public const string HandleOrderActionScriptBookingManagerInfoParameterName = "Booking Manager Info"; + /// + /// Initializes a new instance of the class. + /// + public Order() + { + } + + /// + /// Initializes a new instance of the class based on the existing Order. + /// The new Order will have new GUIDs assigned to its ID parameter and the IDs of the Services. + /// + /// Order to copy. + public Order(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order) + { + System.Reflection.PropertyInfo[] propertyInfo = typeof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order).GetProperties(); + foreach (System.Reflection.PropertyInfo property in propertyInfo) + { + if (property.CanWrite) + property.SetValue(this, property.GetValue(order)); + } + + Id = System.Guid.Empty; + foreach (var service in Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManager.FlattenServices(Sources)) + { + service.Id = System.Guid.NewGuid(); + service.IsBooked = false; + } + } + + /// + /// Preroll of the order. Equal to the duration between the start of the first preroll among its services and the first start among its services. + /// + public System.TimeSpan PreRoll + { + get + { + if (Sources == null || !System.Linq.Enumerable.Any(Sources) || System.Linq.Enumerable.All(AllServices, s => s.IsEventLevelReception || s.IsGlobalEventLevelReception)) + return System.TimeSpan.Zero; + var earliestServicePreRollStart = System.Linq.Enumerable.Min(System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(AllServices, s => !s.IsEventLevelReception && !s.IsGlobalEventLevelReception), s => s.StartWithPreRoll)); + var earliestServiceStart = System.Linq.Enumerable.Min(System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(AllServices, s => !s.IsEventLevelReception && !s.IsGlobalEventLevelReception), s => s.Start)); + bool earliestServicePreRollStartIsBeforeEarliestServiceStart = earliestServicePreRollStart < earliestServiceStart; + return earliestServicePreRollStartIsBeforeEarliestServiceStart ? earliestServiceStart - earliestServicePreRollStart : System.TimeSpan.Zero; + } + } + + public System.DateTime StartWithPreRoll => Start - PreRoll; + /// + /// Postroll of the order. Equal to the duration between the start of the latest postroll among its services and the latest end among its services. + /// + public System.TimeSpan PostRoll + { + get + { + if (Sources == null || !System.Linq.Enumerable.Any(Sources) || System.Linq.Enumerable.All(AllServices, s => s.IsEventLevelReception || s.IsGlobalEventLevelReception)) + return System.TimeSpan.Zero; + var latestServicePostRollEnd = System.Linq.Enumerable.Max(System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(AllServices, s => !s.IsEventLevelReception && !s.IsGlobalEventLevelReception), s => s.EndWithPostRoll)); + var latestServiceEnd = System.Linq.Enumerable.Max(System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(AllServices, s => !s.IsEventLevelReception && !s.IsGlobalEventLevelReception), s => s.End)); + bool latestServicePostRollEndIsLaterThanLatestServiceEnd = latestServiceEnd < latestServicePostRollEnd; + return latestServicePostRollEndIsLaterThanLatestServiceEnd ? latestServicePostRollEnd - latestServiceEnd : System.TimeSpan.Zero; + } + } + + public System.DateTime EndWithPostRoll => End + PostRoll; + /// + /// The list of sources in this order. + /// + public System.Collections.Generic.List Sources + { + get; + set; + } + + /// + /// The service definition used by the order. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition Definition + { + get; + set; + } + + /// + /// Work Order Id of the eurovision service that was requested through the LiveOrderForm + /// + public string EurovisionWorkOrderId + { + get + { + foreach (var service in AllServices) + { + if (!string.IsNullOrWhiteSpace(service.EurovisionWorkOrderId)) + return service.EurovisionWorkOrderId; + } + + return string.Empty; + } + } + + /// + /// Transmission Number of the Eurovision Synopsis. + /// Used for uniquely identifying Eurovision Orders. + /// Only applicable for Orders that use Eurovision Services or Orders generated by the Eurovision Integration. + /// + public string EurovisionTransmissionNumber + { + get + { + foreach (var service in AllServices) + { + if (!string.IsNullOrWhiteSpace(service.EurovisionTransmissionNumber)) + return service.EurovisionTransmissionNumber; + } + + return string.Empty; + } + } + + /// + /// Gets a IEnumerable containing all Services in the Order. + /// + public System.Collections.Generic.List AllServices => FlattenServices(Sources); + /// + /// Gets a boolean indicating if the order contains cueing (preroll) services. + /// + public bool HasCueingServices + { + get => System.Linq.Enumerable.Any(AllServices, x => x.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ServiceCueing); + } + + public bool HasPostRollServices + { + get => System.Linq.Enumerable.Any(AllServices, x => x.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.PostRoll); + } + + /// + /// Gets a boolean indicating if the order contains a fixed plasma source. Used by UI to filter. + /// + public bool HasFixedPlasmaSource + { + get + { + var sourceService = System.Linq.Enumerable.FirstOrDefault(Sources, s => s.BackupType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.BackupType.None); + if (sourceService == null) + return false; + bool sourceIsFixedLineLy = sourceService.Definition.Name == "_Fixed Line RX LY"; + bool sourceIsMadeFromPlasmaIntegration = sourceService.IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma; + return sourceIsMadeFromPlasmaIntegration && sourceIsFixedLineLy; + } + } + + /// + /// Booking can only be edited when Order is not running and has no cueing or post roll services. + /// + public bool CanEditBooking + { + get => !HasCueingServices && !HasPostRollServices && Status != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Running; + } + + public bool UI_Team_Messi_Live + { + get + { + return System.Linq.Enumerable.Any(AllServices, s => s != null && s.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && (s.Definition.Description == "Messi Live" || s.Definition.Description == "Messi Live Backup")); + } + } + + public bool UI_Team_Messi_News + { + get + { + return System.Linq.Enumerable.Any(AllServices, s => s != null && s.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && s.Definition.Description == "Messi News"); + } + } + + /// + /// Gets a boolean indicating if this order is visible on Areena Monitoring page. + /// + public bool UI_Areena + { + get + { + return System.Linq.Enumerable.Any(AllServices, s => s.Definition.Description == "Areena"); + } + } + + /// + /// Gets a boolean indicating if this order is visible on TOM News page. + /// + public bool UI_News + { + get + { + if (AllServices == null) + return false; + foreach (var service in AllServices) + { + if (service.Definition != null && service.Definition.Description?.Contains("News") == true) + return true; + foreach (var function in System.Linq.Enumerable.Where(service.Functions, f => f != null)) + { + var sourceOrDestinationLocation = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p != null && (p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.FixedLineYleHelsinkiSourceLocation || p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.YleHelsinkiDestinationLocation)); + if (sourceOrDestinationLocation != null && (sourceOrDestinationLocation.StringValue == "Uutisalue" || sourceOrDestinationLocation.StringValue == "Uutisstudiot" || sourceOrDestinationLocation.StringValue == "Uutisstudio ST 27/28")) + return true; + if (HasFunctionMatchingPlasmaSource(function, new string[]{"ST-24", "ST-25", "ST-26", "ST-27", "NOPSA", "SU28O"})) + return true; + } + } + + return false; + } + } + + /// + /// Gets a boolean indicating if this order is visible on TOM Studio Helsinki page. + /// + public bool UI_Sho + { + get + { + if (AllServices == null) + return false; + foreach (var service in AllServices) + { + foreach (var function in System.Linq.Enumerable.Where(service.Functions, f => f != null)) + { + var sourceOrDestinationLocation = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p != null && (p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.FixedLineYleHelsinkiSourceLocation || p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.YleHelsinkiDestinationLocation)); + if (sourceOrDestinationLocation != null && (sourceOrDestinationLocation.StringValue == "Studio Helsinki" || sourceOrDestinationLocation.StringValue == "Studio Helsinki UT")) + return true; + if (HasFunctionMatchingPlasmaSource(function, new string[]{"SHO1", "SHO2", "SHO3", "SHO4", "SHO5"})) + return true; + } + } + + return false; + } + } + + /// + /// Gets a boolean indicating if this order is visible on TOM Mediapolis page. + /// + public bool UI_Tre + { + get + { + if (System.Linq.Enumerable.Any(AllServices, s => s != null && (s.Definition.Description == "YLE Mediapolis" || s.Definition.Description == "LiveU Mediapolis"))) + return true; + var orderServices = AllServices; + if (orderServices == null) + return false; + foreach (var service in orderServices) + { + foreach (var function in System.Linq.Enumerable.Where(service.Functions, f => f != null)) + { + if (HasFunctionMatchingPlasmaSource(function, new string[]{"TRE 01"})) + return true; + } + } + + return false; + } + } + + /// + /// Gets a boolean indicating if this order is visible on TOM SVENSKA page. + /// + public bool UI_Svenska + { + get + { + var orderServices = AllServices; + if (orderServices == null) + return false; + foreach (var service in orderServices) + { + foreach (var function in System.Linq.Enumerable.Where(service.Functions, f => f != null)) + { + var sourceOrDestinationLocation = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p != null && (p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.FixedLineYleHelsinkiSourceLocation || p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.YleHelsinkiDestinationLocation)); + if (sourceOrDestinationLocation != null && (sourceOrDestinationLocation.StringValue == "Shohub")) + { + return true; + } + + if (HasFunctionMatchingPlasmaSource(function, new string[]{"SHOHUB"})) + return true; + } + } + + return false; + } + } + + /// + /// The order will be shown on the TOM News page if the integration type is Plasma. + /// + public bool UI_Plasma + { + get + { + return IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma; + } + } + + /// + /// The order will be shown on the TOM News page if it contains one or more recording services. + /// + public bool UI_Messi_News_Rec + { + get + { + return System.Linq.Enumerable.Any(AllServices, s => s?.Definition != null && !string.IsNullOrEmpty(s.Definition.Description) && s.Definition.Description.Contains("News")); + } + } + + /// + /// Gets a boolean indicating if this order is visible on MCR Operator Task List page. + /// + public bool UI_McrChange + { + get + { + bool orderIsStartedWithIncompletedUsertasks = System.DateTime.Now >= StartWithPreRoll && System.Linq.Enumerable.Any(AllServices, s => s.UserTasks != null && System.Linq.Enumerable.Any(s.UserTasks, u => u.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete)); + bool containsOrderNonBookedServices = System.Linq.Enumerable.Any(AllServices, s => s != null && !s.IsBooked) && IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma; + bool orderPlannedMoreThanOneWeek = System.Linq.Enumerable.Any(AllServices, s => s != null && s.StartWithPreRoll.ToLocalTime().Subtract(System.DateTime.Now) > new System.TimeSpan(days: 7, hours: 0, minutes: 1, seconds: 0)); + if (Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.PlannedUnknownSource) + { + return true; + } + + if (IsSaved || (containsOrderNonBookedServices || orderPlannedMoreThanOneWeek) && (IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma || IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Feenix)) + { + return false; //When non plasma orders are saved or where plasma/feenix orders contain one or more services where the start time with preroll is larger than 7 days, with other words services that aren't booked yet. + } + + if (Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.CompletedWithErrors && !System.String.IsNullOrWhiteSpace(OperatorNotes)) + { + return false; + } + + if (Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.FileProcessing && EndWithPostRoll <= System.DateTime.Now && System.Linq.Enumerable.Any(AllServices, s => s != null && System.Linq.Enumerable.Any(s.UserTasks, u => u != null && u.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete && u.Description.IndexOf("File Processing", System.StringComparison.OrdinalIgnoreCase) != -1))) + { + return false; + } + + if (Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Planned || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.ChangeRequested) + { + return true; // All orders where ORDER status = Planned (Use case: Operator confirms/rejects an order) + } + + if (System.Linq.Enumerable.Any(AllServices, s => s != null && s.Definition?.VirtualPlatform != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && (s.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ResourceOverbooked || s.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ServiceCompletedWithErrors && System.String.IsNullOrWhiteSpace(ErrorDescription)))) + { + // This caused issues when booking new orders + // Services were having status ResourceOverbooked + return true; // All orders where one or more SERVICES are having status Resources Overbooked (excluding Recordings) OR having status “Service completed with errors” and error description field (txt) is empty + } + + if (orderIsStartedWithIncompletedUsertasks) + { + return true; // All orders where one or more USER TASK are INCOMPLETE when pre-roll has begun + } + + if (IntegrationType != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma && System.Linq.Enumerable.Any(AllServices, s => s.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionSatellite && s.Start - System.DateTime.Now < new System.TimeSpan(hours: 72, minutes: 1, seconds: 0) && s.UserTasks != null && System.Linq.Enumerable.Any(s.UserTasks, u => u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.SatelliteReception.SpaceNeeded) && u.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete))) + { + return true; // All orders which include RX SERVICE (Satellite RX or Backup Satellite RX) related USER TASK: Satellite space needed + } + + if (IntegrationType != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma && System.Linq.Enumerable.Any(AllServices, s => (s.IsEbuDummyReception || s.IsEbuDummyTransmission) && s.UserTasks != null && System.Linq.Enumerable.Any(s.UserTasks, u => u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.Dummy.SelectTechnicalSystem)))) + { + return true; // All orders which include DUMMY EBU SERVICE with USER TASK: Select Technical System from EBU Synopsis + } + + if (IntegrationType != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma && System.Linq.Enumerable.Any(AllServices, s => System.Linq.Enumerable.Any(s.Functions, f => System.Linq.Enumerable.Any(f.Parameters, p => (p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.FixedLineEbuSourceLocation || p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.EbuDestinationLocation) && p.StringValue == "Nordic Ring"))) && Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Planned) + { + return true; // All orders where source or destination is Fixed Line Nordic Ring and status is Planned (Included in rule 1) + } + + return false; + } + } + + /// + /// Gets a boolean indicating if this order is visible on Booking Office Task List page. + /// + public bool UI_Office + { + get + { + if (System.Linq.Enumerable.Any(AllServices, s => s.Definition?.VirtualPlatformServiceName == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformName.Satellite && s.UserTasks != null && System.Linq.Enumerable.Any(s.UserTasks, u => u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.SatelliteReception.SpaceNeeded) && u.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete))) + return true; // All orders which include RX Service (Sat RX or Backup Sat RX) related user task: Satellite space needed + if (System.Linq.Enumerable.Any(AllServices, s => s.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionFiber && s.UserTasks != null && System.Linq.Enumerable.Any(s.UserTasks, u => u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.FiberReception.AllocationNeeded) && u.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete))) + return true; // All orders which include RX service (ad hoc fiber RX or backup Ad Hoc Fiber RX) related user task: fiber allocation needed + if (System.Linq.Enumerable.Any(AllServices, s => s.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionMicrowave && s.UserTasks != null && System.Linq.Enumerable.Any(s.UserTasks, u => u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.MicrowaveReception.EquipmentAllocation) && u.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete))) + return true; // All orders which include RX Service (MW link RX or backup MW RX) related user task: MW equipment allocation needed + return false; + } + } + + /// + /// Gets a boolean indicating if this order is visible on MCR Specialist Task List page. + /// + public bool UI_McrSpecialist + { + get + { + if (Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Completed || Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.CompletedWithErrors) + return false; + if (System.Linq.Enumerable.Any(AllServices, s => s.Definition?.VirtualPlatformServiceName == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformName.Fiber && s.UserTasks != null && System.Linq.Enumerable.Any(s.UserTasks, u => (u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.FiberReception.AllocationNeeded) || u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.FiberReception.EquipmentAllocation) || u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.FiberTransmission.Configure)) && u.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete))) + return true; // All orders which include (backup) Ad Hoc Fiber RX related user tasks + if (System.Linq.Enumerable.Any(AllServices, s => s.Definition?.VirtualPlatformServiceName == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformName.Microwave && s.UserTasks != null && System.Linq.Enumerable.Any(s.UserTasks, u => (u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.MicrowaveReception.EquipmentAllocation) || u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.MicrowaveReception.EquipmentConfiguration) || u.Name.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.Descriptions.MicrowaveTransmission.Configure)) && u.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete))) + return true; // All orders which include (backup) Microwave RX related user tasks + if (System.Linq.Enumerable.Any(AllServices, s => s.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionIp && s.UserTasks != null && System.Linq.Enumerable.Any(s.UserTasks, u => u.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete))) + return true; // All orders which include RX SERVICE (IP Transmission) + return false; + } + } + + /// + /// Gets a boolean indicating if this order is visible on Media Operator Task List page. + /// + public bool UI_Recording + { + get + { + bool containsOrderNonBookedServices = System.Linq.Enumerable.Any(AllServices, s => s != null && !s.IsBooked) && IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma; + bool orderPlannedMoreThanOneWeek = System.Linq.Enumerable.Any(AllServices, s => s != null && s.StartWithPreRoll.ToLocalTime().Subtract(System.DateTime.Now) > new System.TimeSpan(days: 7, hours: 0, minutes: 1, seconds: 0)); + if (IsSaved || (containsOrderNonBookedServices || orderPlannedMoreThanOneWeek) && (IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma || IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Feenix)) + { + return false; //When non plasma orders are saved or where plasma/feenix orders contain one or more services where the start time with preroll is larger than 7 days, with other words services that aren't booked yet. + } + + if (Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.CompletedWithErrors && !System.String.IsNullOrWhiteSpace(OperatorNotes)) + { + return false; + } + + var recordingServiceCount = 0; + bool recordingServiceHasSubtitleProxy = false; + var orderServices = AllServices; + foreach (var service in orderServices) + { + bool isRecording = service.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording; + if (!isRecording) + continue; + recordingServiceCount++; + var status = service.Status; + // return true when there is a recording service with service completed with errors status and an empty error description + if (status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ServiceCompletedWithErrors && System.String.IsNullOrWhiteSpace(OperatorNotes)) + { + return true; + } + + // return true when there is a recording service with resource overbooked status + if (status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ResourceOverbooked) + { + return true; + } + + // return false when recording service is part of a Plasma Live News order + if (IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma && service != null && service.RecordingConfiguration?.IsPlasmaLiveNews == true) + { + return false; + } + + // return true when there is a recording service with a non-real time code + if (service.RecordingConfiguration?.RecordingFileTimeCodec == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.TimeCodec.NonReal && IntegrationType != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma) + { + return true; + } + + // return true when there is a recording service with sub recordings + if (service.RecordingConfiguration?.SubRecordings != null && System.Linq.Enumerable.Any(service.RecordingConfiguration.SubRecordings) && IntegrationType != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma) + { + return true; + } + + if (recordingServiceCount == 2 && IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.None && Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status.Completed) + { + return false; + } + + // Return true if a plasma order has more than 3 recordings (more means that extra recordings are added manually), default plasma orders has 2-3 recording services + if (recordingServiceCount > 1 && IntegrationType != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma || recordingServiceCount > 3 && IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma) + { + return true; + } + + // check if the recording service is a day change and requires subtitle proxy + if (service.RecordingConfiguration?.SubtitleProxy == true && service.Start.Date != service.End.Date) + recordingServiceHasSubtitleProxy = true; + // return true in case of a Plasma order with a day change and more than 1 recording + if (recordingServiceCount >= 1 && recordingServiceHasSubtitleProxy) + { + return true; + } + } + + return false; + } + } + + /// + /// Returns a list of all resources used for this order. + /// + public System.Collections.Generic.IEnumerable AllServiceResources => GetAllServiceResources(); + /// + /// Retrieving the audio return information from the source services. + /// Only news users can fill in this field for every type of service. + /// Other users will only see this field when LiveU source service is used. + /// + public string AudioReturnInfo + { + get + { + if (AllServices == null) + return System.String.Empty; + System.Collections.Generic.List audioReturnInfos = new System.Collections.Generic.List(); + foreach (var sourceService in Sources) + { + if (sourceService == null) + continue; + if (!System.String.IsNullOrWhiteSpace(sourceService.AudioReturnInfo)) + { + audioReturnInfos.Add(sourceService.AudioReturnInfo); + } + } + + return string.Join(";", audioReturnInfos); + } + } + + /// + /// Additional information for reception/transmission LiveU device name. + /// Only applicable for LiveU receptions/transmissions. + /// Will be saved in a custom property + /// + public string LiveUDeviceNames + { + get + { + var orderServices = AllServices; + if (orderServices == null) + return System.String.Empty; + System.Collections.Generic.List liveUDeviceNamesToAdd = new System.Collections.Generic.List(); + foreach (var service in orderServices) + { + if (service == null) + continue; + bool isServiceLiveUReceptionOrTransmission = service.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionLiveU || service.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionLiveU; + if (isServiceLiveUReceptionOrTransmission && !System.String.IsNullOrEmpty(service.LiveUDeviceName)) + { + liveUDeviceNamesToAdd.Add(service.LiveUDeviceName); + } + } + + return System.String.Join(";", liveUDeviceNamesToAdd); + } + } + + /// /// + /// Returns a dot comma separated list containing the Vidigo stream source links if the order contains Messi News Recordings. + /// + public string VidigoStreamSourceLinks + { + get + { + var vidigoStreamSourceLinks = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(AllServices, s => !string.IsNullOrWhiteSpace(s.VidigoStreamSourceLink)), s => s.VidigoStreamSourceLink)); + return string.Join(";", vidigoStreamSourceLinks); + } + } + + /// + /// Returns a dot comma separated list containing all existing plasma ids for archiving from all live recording services within this order. + /// + public string PlasmaIdsForArchiving + { + get + { + var orderServices = AllServices; + if (orderServices == null) + return System.String.Empty; + System.Collections.Generic.List plasmaIdsForArchiveToAdd = new System.Collections.Generic.List(); + foreach (var service in orderServices) + { + if (service == null) + continue; + bool isServiceLiveRecording = service.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && service.Definition.Description != null && service.Definition.Description.Contains("Live"); + if (isServiceLiveRecording && service.RecordingConfiguration != null && !string.IsNullOrWhiteSpace(service.RecordingConfiguration.PlasmaIdForArchive)) + { + plasmaIdsForArchiveToAdd.Add(service.RecordingConfiguration.PlasmaIdForArchive); + } + } + + return System.String.Join(";", plasmaIdsForArchiveToAdd); + } + } + + /// + /// Returns a dot comma separated list containing the Short Descriptions of the Source Services. + /// + public string SourceDescriptions + { + get + { + if (Sources == null || !System.Linq.Enumerable.Any(Sources)) + return System.String.Empty; + return System.String.Join(";", System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(Sources, x => x.Definition.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Reception), x => x.GetShortDescription(this))); + } + } + + /// + /// Returns a dot comma separated list containing the Short Descriptions of the Destination Services. + /// + public string DestinationDescriptions + { + get + { + System.Collections.Generic.List resultDescriptions = new System.Collections.Generic.List(); + string umxLineResourceName = GetUmxLineResourceNameForMessiNewsRecordings(); + var destinationShortDescriptions = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(AllServices, x => x.Definition.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Destination), x => x.GetShortDescription(this))); + if (!System.Linq.Enumerable.Any(destinationShortDescriptions, x => x.Replace(" ", string.Empty).Equals(umxLineResourceName, System.StringComparison.InvariantCultureIgnoreCase))) + { + resultDescriptions.Add(umxLineResourceName); + } + + resultDescriptions.AddRange(destinationShortDescriptions); + return System.String.Join(";", System.Linq.Enumerable.Distinct(System.Linq.Enumerable.Where(resultDescriptions, x => !string.IsNullOrWhiteSpace(x)))); + } + } + + /// + /// Returns a dot comma separated list containing the Short Descriptions of the Recording Services. + /// + public string RecordingDescriptions + { + get + { + return System.String.Join(";", System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(AllServices, x => x.Definition.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Recording), x => x.GetShortDescription(this))); + } + } + + /// + /// Returns a dot comma separated list containing the Short Descriptions of the Transmission Services. + /// + public string TransmissionDescriptions + { + get + { + return System.String.Join(";", System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(AllServices, x => x.Definition.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Transmission), x => x.GetShortDescription(this))); + } + } + + public System.Collections.Generic.IEnumerable GetAllServiceResources(System.Guid? serviceToIgnoreId = null, string functionToIgnoreLabel = null) + { + return System.Linq.Enumerable.ToList(System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(System.Linq.Enumerable.SelectMany(System.Linq.Enumerable.Where(AllServices, s => s.Id != serviceToIgnoreId), s => s.Functions), f => f.Definition.Label != functionToIgnoreLabel && f.Resource != null), f => f.Resource)); + } + + public static System.Collections.Generic.List FlattenServices(System.Collections.Generic.IEnumerable services) + { + var flattenedServices = new System.Collections.Generic.List(); + foreach (var service in services) + { + flattenedServices.Add(service); + flattenedServices.AddRange(FlattenServices(service.Children)); + } + + return flattenedServices; + } + + private string GetUmxLineResourceNameForMessiNewsRecordings() + { + var result = new System.Text.StringBuilder(); + var allOrderServices = AllServices; + var newsRecordingService = System.Linq.Enumerable.FirstOrDefault(allOrderServices, s => s != null && s.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && s.Definition.Description.Contains("News")); + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service routingService = null; + if (newsRecordingService != null) + { + routingService = System.Linq.Enumerable.Single(allOrderServices, s => s != null && s.Children?.Contains(newsRecordingService) == true); + if (routingService != null && routingService.Functions != null && System.Linq.Enumerable.Any(routingService.Functions)) + { + var matrixOutputFunction = System.Linq.Enumerable.Single(routingService.Functions, f => f != null && routingService.Definition?.FunctionIsFirst(f) == true); + var matrixOutputResource = matrixOutputFunction.Resource; + string matrixOutputResourceName = matrixOutputResource != null ? matrixOutputResource.Name : "None"; + string matrixOutputResourceDisplayName = System.Linq.Enumerable.Last(matrixOutputResourceName.Split('.')); + if (!string.IsNullOrEmpty(matrixOutputResourceDisplayName)) + { + result.Append(matrixOutputResourceDisplayName.Contains("UMX") ? matrixOutputResourceDisplayName : string.Empty); + } + } + } + + return result.ToString(); + } + + /// + /// Checks if a function uses a matching plasma source + /// + /// Function that contains the plasma user code profile parameter + /// Regular expression to search matching plasma source + /// + private bool HasFunctionMatchingPlasmaSource(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function function, string[] applicablePlasmaUserCodes) + { + var sourcePlasmaUserCode = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p != null && p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.FixedLineLySourcePlasmaUserCode); + if (sourcePlasmaUserCode == null) + return false; + if (System.Linq.Enumerable.Contains(applicablePlasmaUserCodes, sourcePlasmaUserCode.StringValue.ToUpper())) + return true; + return false; + } + + public override string ToString() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.AppendLine(System.String.Format("Name: {0}", Name)); + sb.AppendLine(System.String.Format("\tStatus: {0}", Status)); + sb.AppendLine(System.String.Format("\tStart: {0}", Start)); + sb.AppendLine(System.String.Format("\tEnd: {0}", End)); + sb.AppendLine(System.String.Format("\tStart With Pre Roll: {0}", StartWithPreRoll)); + sb.AppendLine(System.String.Format("\tEnd With Post Roll: {0}", EndWithPostRoll)); + sb.AppendLine(System.String.Format("\tService Definition: {0}", Definition.Id)); + sb.AppendLine(System.String.Format("\tIntegration Type: {0}", IntegrationType)); + sb.AppendLine(System.String.Format("\tPlasma ID: {0}", PlasmaId)); + sb.AppendLine(System.String.Format("\tEurovision ID: {0}", EurovisionWorkOrderId)); + sb.AppendLine(System.String.Format("\tTransmission Number: {0}", EurovisionTransmissionNumber)); + sb.AppendLine(System.String.Format("\tContract: {0}", Contract)); + sb.AppendLine(System.String.Format("\tCompany: {0}", Company)); + sb.AppendLine("\tServices:"); + foreach (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service in AllServices) + { + sb.AppendLine("\t" + service.ToString()); + } + + return sb.ToString(); + } + + /// + /// Checks if the Order matches the (basic) requirements to be booked. + /// + public bool CanBeBooked + { + get + { + bool hasReceptionService = false; + bool hasRecordingService = false; + bool hasTransmissionService = false; + bool hasDestinationService = false; + foreach (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service in FlattenServices(System.Linq.Enumerable.Where(Sources, x => x.BackupType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.BackupType.None))) + { + if (service?.Definition?.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Reception) + hasReceptionService = true; + if (service?.Definition?.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Recording) + hasRecordingService = true; + if (service?.Definition?.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Transmission) + hasTransmissionService = true; + if (service?.Definition?.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Destination) + hasDestinationService = true; + } + + return hasReceptionService && (hasRecordingService || hasTransmissionService || hasDestinationService); + } + } + + /// + /// Checks if the Order contains Eurovision services that should be manually booked from the LiveOrderForm. + /// + public bool HasEurovisionServices + { + get + { + foreach (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service in AllServices) + { + if (service?.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionEurovision) + return true; + if (service?.Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionEurovision) + return true; + } + + return false; + } + } + } + + public class OrderChange + { + public string UserLoginName + { + get; + set; + } + + public System.DateTime TimeStamp + { + get; + set; + } + + = System.DateTime.Now; + public System.Collections.Generic.List PropertyChanges + { + get; + set; + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Skyline.DataMiner.Storage.Types.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLNetTypes.dll")] + public class OrderManager : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.IOrderManager + { + public const string OrderBookingManagerElementName = "Order Booking Manager"; + public OrderManager(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers) + { + Helpers = helpers ?? throw new System.ArgumentNullException(nameof(helpers)); + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers Helpers + { + get; + set; + } + + public System.Collections.Generic.IEnumerable GetAllOrders() + { + System.Collections.Generic.IEnumerable allOrderReservations = Skyline.DataMiner.Library.Solutions.SRM.ResourceManagerExtensions.GetReservationInstancesByProperty(Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ResourceManager, "Type", "Video"); + return System.Linq.Enumerable.Select(allOrderReservations, x => new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order{Id = x.ID, Name = x.Name, Comments = GetOrderEventGuid(x).ToString()}); + } + + /// + /// Creates a list containing the provided services and all their underlying child services. + /// + /// To get all Services in an Order, you can use the AllServices property on Order. + /// Services to check. These services are included in the returned collection. + /// Collection containing the provided services and all of their underlying child services. + public static System.Collections.Generic.List FlattenServices(System.Collections.Generic.IEnumerable services) + { + System.Collections.Generic.List flattenedServices = new System.Collections.Generic.List(); + foreach (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service in services) + { + flattenedServices.Add(service); + flattenedServices.AddRange(FlattenServices(service.Children)); + } + + return flattenedServices; + } + + public System.Guid GetOrderEventGuid(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservationInstance) + { + object eventId = null; + if (!reservationInstance.Properties.Dictionary.TryGetValue(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.LiteOrder.PropertyNameEventId, out eventId)) + { + return System.Guid.Empty; + } + + if (!System.Guid.TryParse(eventId.ToString(), out var eventGuid)) + { + // TODO: check to use custom Exception + throw new System.Exception($"Unable to parse GUID: '{eventId.ToString()}'"); + } + + return eventGuid; + } + } + + public enum UpdateType + { + Add, + Remove, + Change + } + + public class PropertyChange + { + public string PropertyName + { + get; + set; + } + + public string OriginalValue + { + get; + set; + } + + public string UpdatedValue + { + get; + set; + } + + public System.Type PropertyType + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.UpdateType UpdateType + { + get; + set; + } + + public System.Guid ServiceId + { + get; + set; + } + + = System.Guid.Empty; + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class SportsPlanning : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.IYleChangeTracking + { + private string initialSport; + private string initialDescription; + private string initialCommentary; + private string initialCommentary2; + private double initialCompetitionTime; + private string initialJournalistOne; + private string initialJournalistTwo; + private string initialJournalistThree; + private string initialLocation; + private string initialTechnicalResources; + private string initialLiveHighlightsFile; + private double initialRequestedBroadcastTime; + private string initialProductNumberCeiton; + private string initialProductionNumberPlasmaId; + private string initialCostDepartment; + private string initialAdditionalInfo; + public string Sport + { + get; + set; + } + + public string Description + { + get; + set; + } + + public string Commentary + { + get; + set; + } + + public string Commentary2 + { + get; + set; + } + + /// + /// Milliseconds since 01/01/1970 + /// + public double CompetitionTime + { + get; + set; + } + + public string JournalistOne + { + get; + set; + } + + public string JournalistTwo + { + get; + set; + } + + public string JournalistThree + { + get; + set; + } + + public string Location + { + get; + set; + } + + public string TechnicalResources + { + get; + set; + } + + public string LiveHighlightsFile + { + get; + set; + } + + /// + /// Milliseconds since 01/01/1970 + /// + public double RequestedBroadcastTime + { + get; + set; + } + + public string ProductionNumberPlasmaId + { + get; + set; + } + + public string ProductNumberCeiton + { + get; + set; + } + + public string CostDepartment + { + get; + set; + } + + public string AdditionalInformation + { + get; + set; + } + + /// + /// Gets a boolean indicating if Change Tracking has been enabled for this object. + /// + /// + public bool ChangeTrackingEnabled + { + get; + private set; + } + + /// + /// Gets a boolean indicating if this object has been changed since object construction or since last call. + /// + /// + public bool IsChanged => ChangeInfo.IsChanged; + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo ChangeInfo => GetChanges(); + /// + /// Gets the type of changes that have happened since object creation or since last call. + /// + /// A flags enum containing the types of changes. + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo GetChanges() + { + var changeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo(); + if (initialSport != Sport) + changeInfo.MarkCustomPropertiesChanged(); + if (initialDescription != Description) + changeInfo.MarkCustomPropertiesChanged(); + if (initialCommentary != Commentary) + changeInfo.MarkCustomPropertiesChanged(); + if (initialCommentary2 != Commentary2) + changeInfo.MarkCustomPropertiesChanged(); + if (System.Math.Abs(initialCompetitionTime - CompetitionTime) > 0.01) + changeInfo.MarkCustomPropertiesChanged(); + if (initialJournalistOne != JournalistOne) + changeInfo.MarkCustomPropertiesChanged(); + if (initialJournalistTwo != JournalistTwo) + changeInfo.MarkCustomPropertiesChanged(); + if (initialJournalistThree != JournalistThree) + changeInfo.MarkCustomPropertiesChanged(); + if (initialLocation != Location) + changeInfo.MarkCustomPropertiesChanged(); + if (initialTechnicalResources != TechnicalResources) + changeInfo.MarkCustomPropertiesChanged(); + if (initialLiveHighlightsFile != LiveHighlightsFile) + changeInfo.MarkCustomPropertiesChanged(); + if (System.Math.Abs(initialRequestedBroadcastTime - RequestedBroadcastTime) > 0.01) + changeInfo.MarkCustomPropertiesChanged(); + if (initialProductNumberCeiton != ProductNumberCeiton) + changeInfo.MarkCustomPropertiesChanged(); + if (initialProductionNumberPlasmaId != ProductionNumberPlasmaId) + changeInfo.MarkCustomPropertiesChanged(); + if (initialCostDepartment != CostDepartment) + changeInfo.MarkCustomPropertiesChanged(); + if (initialAdditionalInfo != AdditionalInformation) + changeInfo.MarkCustomPropertiesChanged(); + return changeInfo; + } + + /// + /// Resets Change Tracking. + /// + /// + public void AcceptChanges() + { + initialSport = Sport; + initialDescription = Description; + initialCommentary = Commentary; + initialCommentary2 = Commentary2; + initialCompetitionTime = CompetitionTime; + initialJournalistOne = JournalistOne; + initialJournalistTwo = JournalistTwo; + initialJournalistThree = JournalistThree; + initialLocation = Location; + initialTechnicalResources = TechnicalResources; + initialLiveHighlightsFile = LiveHighlightsFile; + initialRequestedBroadcastTime = RequestedBroadcastTime; + initialProductNumberCeiton = ProductNumberCeiton; + initialProductionNumberPlasmaId = ProductionNumberPlasmaId; + initialCostDepartment = CostDepartment; + initialAdditionalInfo = AdditionalInformation; + } + + public override string ToString() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.None); + } + + public override bool Equals(object obj) + { + if (!(obj is SportsPlanning other)) + return false; + bool equal = true; + foreach (var property in typeof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.SportsPlanning).GetProperties()) + { + equal &= property.GetValue(this).Equals(property.GetValue(other)); + } + + return equal; + } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 23 + Sport.GetHashCode(); + hash = hash * 23 + Description.GetHashCode(); + hash = hash * 23 + Commentary.GetHashCode(); + hash = hash * 23 + Commentary2.GetHashCode(); + hash = hash * 23 + CompetitionTime.GetHashCode(); + hash = hash * 23 + JournalistOne.GetHashCode(); + hash = hash * 23 + JournalistTwo.GetHashCode(); + hash = hash * 23 + JournalistThree.GetHashCode(); + hash = hash * 23 + Location.GetHashCode(); + hash = hash * 23 + TechnicalResources.GetHashCode(); + return hash; + } + } + } + + namespace Recurrence + { + public enum RecurrenceFrequencyUnit + { + [System.ComponentModel.Description("day(s)")] + Days, + [System.ComponentModel.Description("week(s)")] + Weeks, + [System.ComponentModel.Description("month(s)")] + Months, + [System.ComponentModel.Description("year(s)")] + Years + } + + public enum RecurrenceRepeatType + { + None, + DaysOfTheWeek, + UmpteenthDayOfTheMonth, + UmpteenthWeekDayOfTheMonth + } + + [System.Flags] + public enum DaysOfTheWeek + { + None = 0, + [System.ComponentModel.Description("Monday")] + Monday = 1, + [System.ComponentModel.Description("Tuesday")] + Tuesday = 2, + [System.ComponentModel.Description("Wednesday")] + Wednesday = 4, + [System.ComponentModel.Description("Thursday")] + Thursday = 8, + [System.ComponentModel.Description("Friday")] + Friday = 16, + [System.ComponentModel.Description("Saturday")] + Saturday = 32, + [System.ComponentModel.Description("Sunday")] + Sunday = 64 + } + + public enum EndingType + { + [System.ComponentModel.Description("Never")] + Never, + [System.ComponentModel.Description("On a specific date")] + SpecificDate, + [System.ComponentModel.Description("After certain amount of repeats")] + CertainAmountOfRepeats + } + + public enum RecurrenceAction + { + New = 0, + [System.ComponentModel.Description("Edit this order only")] + ThisOrderOnly = 1, + [System.ComponentModel.Description("Edit all orders in recurring sequence")] + AllOrdersInSequence = 2 + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class Recurrence + { + public Recurrence() + { + StartTime = default(System.DateTime); + RecurrenceFrequency = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceFrequency(); + RecurrenceRepeat = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceRepeat(); + RecurrenceEnding = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceEnding(); + } + + /// + /// The date time indicating the start of the recurring order sequence. + /// + public System.DateTime StartTime + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceFrequency RecurrenceFrequency + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceRepeat RecurrenceRepeat + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceEnding RecurrenceEnding + { + get; + set; + } + + /// + /// The date time indicating the end of the recurring order sequence. + /// + public System.DateTime EffectiveEndDate + { + get + { + var effectiveEndDateOfRecurringOrder = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.Truncate(System.DateTime.Now.AddYears(1), System.TimeSpan.FromMinutes(1)); // default value for never-ending recurrence + if (RecurrenceEnding.EndingType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.EndingType.SpecificDate) + { + effectiveEndDateOfRecurringOrder = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.Truncate(RecurrenceEnding.EndingDateTime, System.TimeSpan.FromMinutes(1)); + } + else if (RecurrenceEnding.EndingType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.EndingType.CertainAmountOfRepeats) + { + System.TimeSpan timespan; + switch (RecurrenceFrequency.FrequencyUnit) + { + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceFrequencyUnit.Days: + timespan = System.TimeSpan.FromDays(1); + break; + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceFrequencyUnit.Weeks: + timespan = System.TimeSpan.FromDays(7); + break; + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceFrequencyUnit.Months: + timespan = System.TimeSpan.FromDays(31); + break; + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceFrequencyUnit.Years: + timespan = System.TimeSpan.FromDays(365); + break; + default: + timespan = System.TimeSpan.Zero; + break; + } + + var multiplier = RecurrenceFrequency.Frequency * RecurrenceEnding.AmountOfRepeats; + effectiveEndDateOfRecurringOrder = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.Truncate(StartTime, System.TimeSpan.FromMinutes(1)) + SLDataGateway.API.Tools.TimeSpanExtensions.Multiply(timespan, multiplier); + } + + return effectiveEndDateOfRecurringOrder; + } + } + } + + public class RecurrenceFrequency + { + public RecurrenceFrequency() + { + Frequency = 0; + FrequencyUnit = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceFrequencyUnit.Days; + } + + public int Frequency + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceFrequencyUnit FrequencyUnit + { + get; + set; + } + } + + public class RecurrenceRepeat + { + public RecurrenceRepeat() + { + RepeatType = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceRepeatType.None; + UmpteenthDayOfTheMonth = 0; + Day = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.DaysOfTheWeek.None; + UmpteenthOccurrenceOfWeekDayOfTheMonth = 0; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceRepeatType RepeatType + { + get; + set; + } + + public int UmpteenthDayOfTheMonth + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.DaysOfTheWeek Day + { + get; + set; + } + + public int UmpteenthOccurrenceOfWeekDayOfTheMonth + { + get; + set; + } + } + + public class RecurrenceEnding + { + public RecurrenceEnding() + { + EndingType = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.EndingType.CertainAmountOfRepeats; + EndingDateTime = default(System.DateTime); + AmountOfRepeats = 0; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.EndingType EndingType + { + get; + set; + } + + public System.DateTime EndingDateTime + { + get; + set; + } + + public int AmountOfRepeats + { + get; + set; + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class RecurringSequenceInfo + { + public RecurringSequenceInfo() + { + Name = default(string); + Recurrence = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.Recurrence(); + } + + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.RecurrenceAction RecurrenceAction + { + get; + set; + } + + /// + /// The name of the recurring order sequence. + /// + public string Name + { + get; + set; + } + + /// + /// The ID of the recurring order sequence in the order manager. + /// + public System.Guid Id => TemplateId; + /// + /// The recurrence info for the recurring order sequence. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence.Recurrence Recurrence + { + get; + set; + } + + /// + /// The key of the template for the recurring order in the contract manager. + /// + public System.Guid TemplateId + { + get; + set; + } + + public bool TemplateIsUpdated + { + get; + set; + } + + public System.Guid EventId + { + get; + set; + } + + public override string ToString() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.None); + } + } + } + } + + namespace Profile + { + /// + /// This class represents a group of unique Audio Channel Pairs. + /// + public class AudioChannelConfiguration + { + private readonly System.Collections.Generic.HashSet audioChannelPairs = new System.Collections.Generic.HashSet(); + private int lastDisplayedPair = -1; + private int maxDisplayedPair = -1; + /// + /// Initializes a new instance of the class + /// + /// Collection containing the audio channel profile parameters. This can list can also contain other profile parameters. Only the audio channel profile parameters are used. + public AudioChannelConfiguration(System.Collections.Generic.IEnumerable profileParameters) + { + System.Collections.Generic.IEnumerable audioProfileParameters = System.Linq.Enumerable.Where(profileParameters, p => p != null && System.Linq.Enumerable.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.AllAudioChannelConfigurationGuids, p.Id)); + Initialize(audioProfileParameters); + } + + /// + /// A boolean indicating if this Audio Channel Configuration is a copy from the source, taking into account some special copy rules. + /// + public bool IsCopyFromSource + { + get; + set; + } + + /// + /// The parameter indicating if dolby-e decoding is required. + /// Only applicable in case dolby-e is selected in the source. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter AudioDolbyDecodingRequiredProfileParameter + { + get; + set; + } + + /// + /// The parameter indicating if embedding is required. + /// Not applicable in the source. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter AudioEmbeddingRequiredProfileParameter + { + get; + set; + } + + /// + /// The parameter indicating if deembedding is required. + /// Not applicable in the source. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter AudioDeembeddingRequiredProfileParameter + { + get; + set; + } + + /// + /// The parameter indicating if shuffling is required. + /// Not applicable in the source. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter AudioShufflingRequiredProfileParameter + { + get; + set; + } + + /// + /// Gets the list of Audio Channel Pairs managed by this AudioChannelConfiguration. + /// + public System.Collections.Generic.IEnumerable AudioChannelPairs + { + get + { + return audioChannelPairs; + } + } + + /// + /// Indicates if an additional Audio Channel Pair can be displayed in the UI. + /// + public bool CanAddAudioPair + { + get + { + return lastDisplayedPair < maxDisplayedPair; + } + } + + /// + /// Indicates if an Audio Channel Pair can be removed in the UI. + /// + public bool CanRemoveAudioPair + { + get + { + return lastDisplayedPair > 0; + } + } + + /// + /// Gets a value matching the Channel of the last Audio Channel Pair that is displayed in the UI. + /// Returns -1 if no Audio Channel Pairs are displayed. + /// + public int LastDisplayedAudioPairchannel + { + get + { + return lastDisplayedPair; + } + } + + /// + /// Initialize the properties linked to audio profile parameters. + /// + /// The list of audio profile parameters. + private void Initialize(System.Collections.Generic.IEnumerable audioProfileParameters) + { + AudioDolbyDecodingRequiredProfileParameter = System.Linq.Enumerable.FirstOrDefault(audioProfileParameters, a => a.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.AudioDolbyDecodingRequired); + AudioEmbeddingRequiredProfileParameter = System.Linq.Enumerable.FirstOrDefault(audioProfileParameters, a => a.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.AudioEmbeddingRequired); + AudioDeembeddingRequiredProfileParameter = System.Linq.Enumerable.FirstOrDefault(audioProfileParameters, a => a.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.AudioDeembeddingRequired); + AudioShufflingRequiredProfileParameter = System.Linq.Enumerable.FirstOrDefault(audioProfileParameters, a => a.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.AudioShufflingRequired); + foreach (var audioProfileParameter in audioProfileParameters) + { + // there is only 1 parameter used to indicate if audio dolby decoding is required + if (AudioDolbyDecodingRequiredProfileParameter != null && AudioDolbyDecodingRequiredProfileParameter.Id == audioProfileParameter.Id) + continue; + // check that this audio channel profile parameter is not yet processed + // every Audio Channel Pair uses a number of profile parameters + if (System.Linq.Enumerable.Any(AudioChannelPairs, p => p.Contains(audioProfileParameter))) + continue; + int channel; + if (!System.Int32.TryParse(System.Linq.Enumerable.Last(audioProfileParameter.Name.Split(' ')), out channel) || channel % 2 == 0) + { + // an Audio Channel Pair contains the configuration of 2 audio channels + // we can skip this in case the channel is not uneven as it will be automatically added to the correct audio channel pair already + continue; + } + + var firstChannel = audioProfileParameter; + var firstChannelDescription = System.Linq.Enumerable.FirstOrDefault(audioProfileParameters, p => p.Name == System.String.Format("{0} Description", firstChannel.Name)); + var secondChannel = System.Linq.Enumerable.FirstOrDefault(audioProfileParameters, p => p.Name == firstChannel.Name.Replace(channel.ToString(), (channel + 1).ToString())); + var secondChannelDescription = System.Linq.Enumerable.FirstOrDefault(audioProfileParameters, p => p.Name == System.String.Format("{0} Description", secondChannel.Name)); + var audioChannel = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.AudioChannelPair(firstChannel, firstChannelDescription, secondChannel, secondChannelDescription, AudioDolbyDecodingRequiredProfileParameter); + audioChannelPairs.Add(audioChannel); + if (audioChannel.ShouldDisplay) + lastDisplayedPair = audioChannel.Channel; + if (audioChannel.Channel > maxDisplayedPair) + maxDisplayedPair = audioChannel.Channel; + } + } + + public override string ToString() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.AppendLine($"Is copy from source: {IsCopyFromSource} | "); + if (AudioDeembeddingRequiredProfileParameter != null) + sb.AppendLine($"Audio deembedding required: {AudioDeembeddingRequiredProfileParameter.StringValue} | "); + if (AudioEmbeddingRequiredProfileParameter != null) + sb.AppendLine($"Audio embedding required: {AudioEmbeddingRequiredProfileParameter.StringValue} | "); + if (AudioShufflingRequiredProfileParameter != null) + sb.AppendLine($"Audio shuffling required: {AudioShufflingRequiredProfileParameter.StringValue} | "); + foreach (var audioChannelPair in AudioChannelPairs) + { + sb.AppendLine($"{audioChannelPair.ToString()} | "); + } + + return sb.ToString(); + } + } + + /// + /// This class represents an Audio Channel Pair. + /// + public class AudioChannelPair + { + private System.Collections.Generic.List allAudioChannelOptions; + private bool isStereo; + /// + /// Initializes a new instance of the class + /// + /// ProfileParameter of the first audio channel in this pair. + /// ProfileParameter of the description for the first audio channel in this pair. + /// ProfileParameter of the second audio channel in this pair. + /// ProfileParameter of the description for the second audio channel in this pair. + /// ProfileParameter of the Dolby Decoding parameter. + /// + public AudioChannelPair(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter firstChannel, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter firstChannelDescription, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter secondChannel, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter secondChannelDescription, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter dolbyDecoding) + { + FirstChannelProfileParameter = firstChannel ?? throw new System.ArgumentNullException(nameof(firstChannel)); + FirstChannelDescriptionProfileParameter = firstChannelDescription ?? throw new System.ArgumentNullException(nameof(firstChannelDescription)); + SecondChannelProfileParameter = secondChannel ?? throw new System.ArgumentNullException(nameof(secondChannel)); + SecondChannelDescriptionProfileParameter = secondChannelDescription ?? throw new System.ArgumentNullException(nameof(secondChannelDescription)); + AllAudioChannelOptions = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Concat(new[]{Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.Constants.None}, System.Linq.Enumerable.Select(FirstChannelProfileParameter.Discreets, d => d.DisplayValue))); + AllAudioChannelOptionsWithoutDolbyDecoding = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where(AllAudioChannelOptions, o => !(o.StartsWith("Dolby") && o.Contains("&")))); + Channel = System.Convert.ToInt32(System.Linq.Enumerable.Last(firstChannel.Name.Split(' '))); + Description = $"Audio Channel {Channel}&{Channel + 1}"; + if (FirstChannelProfileParameter.StringValue == "Other" && SecondChannelProfileParameter.StringValue == "Other") + { + IsStereo = FirstChannelDescriptionProfileParameter.StringValue == SecondChannelDescriptionProfileParameter.StringValue; + } + else + { + IsStereo = FirstChannelProfileParameter.StringValue == SecondChannelProfileParameter.StringValue; + } + + if (dolbyDecoding != null) + { + DolbyDecodingProfileParameter = dolbyDecoding; + } + } + + /// + /// Indicates if this audio channel pair contains the provided profile parameter. + /// + /// The profile parameter. + /// True in case the profile parameter is part of this audio channel configuration. + public bool Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter parameter) + { + return FirstChannelProfileParameter.Equals(parameter) || FirstChannelDescriptionProfileParameter.Equals(parameter) || SecondChannelProfileParameter.Equals(parameter) || SecondChannelDescriptionProfileParameter.Equals(parameter); + } + + /// + /// Gets all possible options for the Audio Channel profile parameters. + /// + public System.Collections.Generic.List AllAudioChannelOptions + { + get => allAudioChannelOptions; + set + { + if (AllAudioChannelOptions != value) + { + allAudioChannelOptions = value; + AudioChannelOptionsChanged?.Invoke(this, new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.AudioChannelPair.AudioChannelOptionsChangedEventArgs(Channel, allAudioChannelOptions)); + } + } + } + + public event System.EventHandler AudioChannelOptionsChanged; + /// + /// Gets all options without the Dolby Decoded channels for the Audio Channel profile parameters. + /// + public System.Collections.Generic.List AllAudioChannelOptionsWithoutDolbyDecoding + { + get; + private set; + } + + /// + /// The profile parameter for the first channel. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter FirstChannelProfileParameter + { + get; + private set; + } + + /// + /// The profile parameter for the description of the first channel. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter FirstChannelDescriptionProfileParameter + { + get; + private set; + } + + /// + /// The profile parameter for the second channel. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter SecondChannelProfileParameter + { + get; + private set; + } + + /// + /// The profile parameter for the description of the second channel. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter SecondChannelDescriptionProfileParameter + { + get; + private set; + } + + /// + /// The Dolby decoding profile parameter. + /// + /// Possible values: "Yes", "No". + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter DolbyDecodingProfileParameter + { + get; + private set; + } + + /// + /// The channel of this audio channel pair. + /// This matches the Audio Channel ID of the first Audio Channel in this Pair. + /// + public int Channel + { + get; + private set; + } + + /// + /// The description of this audio channel pair. + /// + public string Description + { + get; + private set; + } + + /// + /// Indicates if this audio channel pair is stereo or mono. + /// + public bool IsStereo + { + get => isStereo; + set + { + if (isStereo != value) + { + isStereo = value; + IsStereoChanged?.Invoke(this, isStereo); + } + } + } + + /// + /// This event is called when the value of the IsStereo configuration parameter is updated. + /// + public event System.EventHandler IsStereoChanged; + /// + /// Used in AudioChannelPairSection. + /// Indicates whether this pair should be visible in the UI. + /// An Audio Channel Pair should only be displayed when it's values are not none. + /// + public bool ShouldDisplay => FirstChannelProfileParameter.StringValue != "None" && FirstChannelProfileParameter.Value != null || SecondChannelProfileParameter.StringValue != "None" && SecondChannelProfileParameter.Value != null; + /// + /// Generates a HashCode for this object. + /// + /// HashCode for this object. + public override int GetHashCode() + { + return FirstChannelProfileParameter.GetHashCode() ^ FirstChannelDescriptionProfileParameter.GetHashCode() ^ SecondChannelProfileParameter.GetHashCode() ^ SecondChannelDescriptionProfileParameter.GetHashCode(); + } + + /// + /// Checks if this object matches another one. + /// + /// Object to check. + /// True if object matches else false. + public override bool Equals(object obj) + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.AudioChannelPair other = obj as Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.AudioChannelPair; + if (other == null) + return false; + return FirstChannelProfileParameter.Equals(other.FirstChannelProfileParameter) && FirstChannelDescriptionProfileParameter.Equals(other.FirstChannelDescriptionProfileParameter) && SecondChannelProfileParameter.Equals(other.SecondChannelProfileParameter) && SecondChannelDescriptionProfileParameter.Equals(other.SecondChannelDescriptionProfileParameter); + } + + public override string ToString() + { + return $"Channel {Channel} Profile Parameter = {FirstChannelProfileParameter.StringValue}. | Channel {Channel + 1} Profile Parameter = {SecondChannelProfileParameter.StringValue} | IsStereo = {IsStereo} | Dolby Decoding = {(DolbyDecodingProfileParameter != null ? DolbyDecodingProfileParameter.StringValue : "N/A")}."; + } + + public class AudioChannelOptionsChangedEventArgs : System.EventArgs + { + internal AudioChannelOptionsChangedEventArgs(int channel, System.Collections.Generic.IEnumerable audioChannelOptions) + { + Channel = channel; + AudioChannelOptions = audioChannelOptions; + } + + public int Channel + { + get; + private set; + } + + public System.Collections.Generic.IEnumerable AudioChannelOptions + { + get; + private set; + } + } + } + + public class Discreet + { + private readonly string discreet; + public Discreet(string discreet) + { + this.discreet = discreet; + IsAvailable = true; + InitializeLinkedParameterValues(); + } + + private void InitializeLinkedParameterValues() + { + if (discreet == null) + return; + if (discreet.Contains("[") && discreet.Contains(":") && discreet.Contains("]")) + { + System.Text.RegularExpressions.Match discreetNameMatch = System.Text.RegularExpressions.Regex.Match(discreet, @".*\["); + System.Text.RegularExpressions.Match parameterNameMatch = System.Text.RegularExpressions.Regex.Match(discreet, @"\[.*:"); + System.Text.RegularExpressions.Match parameterValueMatch = System.Text.RegularExpressions.Regex.Match(discreet, @":.*\]"); + DisplayValue = discreetNameMatch.Value.Trim(' ', '['); + LinkedParentName = parameterNameMatch.Value.Trim('[', ':'); + LinkedParentValue = parameterValueMatch.Value.Trim(':', ']').ToUpper(); + } + else + { + DisplayValue = discreet; + } + } + + public bool IsAvailable + { + get; + set; + } + + /// + /// The value of the discreet as it should be displayed in the UI. + /// In case of linked parameters this will be the first piece of the discreet. + /// In case of a non-linked parameter this will be the same as the internal value of the discreet. + /// + public string DisplayValue + { + get; + private set; + } + + /// + /// Value of the Discreet as used internally. For linked discreets, this will be "DisplayValue[Linked Parent Name:Linked Parent Value]" + /// + public string InternalValue + { + get + { + return discreet; + } + } + + public string LinkedParentName + { + get; + private set; + } + + /// + /// The selected value of the linked parent discreet to which this discreet applies. + /// This value is in uppercase. + /// + public string LinkedParentValue + { + get; + private set; + } + + public override string ToString() + { + return discreet; + } + + public override bool Equals(object obj) + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.Discreet other = obj as Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.Discreet; + if (other == null) + return false; + return discreet.Equals(other.discreet); + } + + public override int GetHashCode() + { + return discreet.GetHashCode(); + } + } + + public interface IProfileManager + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileDefinition GetProfileDefinition(System.Guid id); + System.Collections.Generic.Dictionary GetInterfaceProfileDefinitions(Skyline.DataMiner.Net.Messages.FunctionDefinition functionDefinition); + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter GetProfileParameter(System.Guid guid); + } + + public class ProfileDefinition + { + public ProfileDefinition(Skyline.DataMiner.Net.Profiles.ProfileDefinition srmProfileDefinition) + { + if (srmProfileDefinition == null) + throw new System.ArgumentNullException(nameof(srmProfileDefinition)); + Id = srmProfileDefinition.ID; + Name = srmProfileDefinition.Name; + ProfileParameters = GetProfileParameters(srmProfileDefinition); + } + + public System.Guid Id + { + get; + set; + } + + public string Name + { + get; + set; + } + + public System.Collections.Generic.IEnumerable ProfileParameters + { + get; + set; + } + + private System.Collections.Generic.IEnumerable GetProfileParameters(Skyline.DataMiner.Net.Profiles.ProfileDefinition srmProfileDefinition) + { + var profileParameters = new System.Collections.Generic.HashSet(); + if (srmProfileDefinition == null) + return profileParameters; + foreach (var profileParameter in srmProfileDefinition.Parameters) + { + var existingProfileParameter = System.Linq.Enumerable.FirstOrDefault(profileParameters, p => p.Equals(profileParameter)); + if (existingProfileParameter == null) + { + profileParameters.Add(new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter(profileParameter)); + } + } + + return profileParameters; + } + } + + public class ProfileManager : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.IProfileManager + { + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers; + private System.Collections.Generic.List allSrmProfileDefinitions; + private System.Collections.Generic.List allSrmProfileParameters; + public ProfileManager(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers) + { + this.helpers = helpers ?? throw new System.ArgumentNullException(nameof(helpers)); + } + + private System.Collections.Generic.List AllSrmProfileDefinitions => allSrmProfileDefinitions ?? (allSrmProfileDefinitions = GetAllSrmProfileDefinitions()); + private System.Collections.Generic.List AllSrmProfileParameters => allSrmProfileParameters ?? (allSrmProfileParameters = GetAllSrmProfileParameters()); + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter GetProfileParameter(System.Guid guid) + { + var parameter = System.Linq.Enumerable.SingleOrDefault(AllSrmProfileParameters, pp => pp.ID == guid) ?? throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ProfileParameterNotFoundException(guid); + return new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter(parameter); + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileDefinition GetProfileDefinition(System.Guid id) + { + var srmProfileDefinition = System.Linq.Enumerable.SingleOrDefault(AllSrmProfileDefinitions, pd => pd.ID == id) ?? throw new Skyline.DataMiner.Library.Exceptions.ProfileDefinitionNotFoundException(id); + return new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileDefinition(srmProfileDefinition); + } + + public System.Collections.Generic.Dictionary GetInterfaceProfileDefinitions(Skyline.DataMiner.Net.Messages.FunctionDefinition functionDefinition) + { + if (functionDefinition == null) + throw new System.ArgumentNullException(nameof(functionDefinition)); + var interfaceProfileDefinitions = new System.Collections.Generic.Dictionary(); + var functionInterfaces = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Concat(System.Linq.Enumerable.Concat(functionDefinition.InputInterfaces, functionDefinition.OutputInterfaces), functionDefinition.InputOutputInterfaces)); + foreach (var functionInterface in functionInterfaces) + { + if (interfaceProfileDefinitions.ContainsKey(functionInterface.ProfileDefinition)) + continue; + var systemProfileDefinition = System.Linq.Enumerable.SingleOrDefault(AllSrmProfileDefinitions, pd => pd.ID == functionInterface.ProfileDefinition); + var profileDefinition = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileDefinition(systemProfileDefinition); + interfaceProfileDefinitions[profileDefinition.Id] = profileDefinition; + } + + return interfaceProfileDefinitions; + } + + private System.Collections.Generic.List GetAllSrmProfileDefinitions() + { + LogMethodStart(nameof(GetAllSrmProfileDefinitions), out var stopwatch); + var retrievedSrmProfileDefinitions = Skyline.DataMiner.Net.ManagerStore.CrudHelperComponentExtension.ReadAll(helpers.ProfileHelper.ProfileDefinitions); + Log(nameof(GetAllSrmProfileDefinitions), $"Retrieved {retrievedSrmProfileDefinitions.Count} profile definitions"); + LogMethodCompleted(nameof(GetAllSrmProfileDefinitions), stopwatch); + return retrievedSrmProfileDefinitions; + } + + private System.Collections.Generic.List GetAllSrmProfileParameters() + { + LogMethodStart(nameof(GetAllSrmProfileParameters), out var stopwatch); + var retrievedProfileParameters = Skyline.DataMiner.Net.ManagerStore.CrudHelperComponentExtension.ReadAll(helpers.ProfileHelper.ProfileParameters); + Log(nameof(GetAllSrmProfileParameters), $"Retrieved {retrievedProfileParameters.Count} profile parameters"); + LogMethodCompleted(nameof(GetAllSrmProfileParameters), stopwatch); + return retrievedProfileParameters; + } + + private void Log(string nameOfMethod, string message, string nameOfObject = null) + { + helpers.ProgressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileManager), nameOfMethod, message, nameOfObject); + } + + private void LogMethodStart(string nameOfMethod, out System.Diagnostics.Stopwatch stopwatch) + { + Log(nameOfMethod, "Start"); + stopwatch = System.Diagnostics.Stopwatch.StartNew(); + } + + private void LogMethodCompleted(string nameOfMethod, System.Diagnostics.Stopwatch stopwatch = null) + { + stopwatch?.Stop(); + Log(nameOfMethod, $"Completed [{stopwatch?.Elapsed}]"); + } + } + + /// + /// This class represents an SRM ProfileParameter. + /// + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + public class ProfileParameter : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.IYleChangeTracking + { + private object value; + private object initialValue; + private System.Collections.Generic.List discreets = new System.Collections.Generic.List(); + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.ValidationInfo valueValidation; + public ProfileParameter() + { + } + + public ProfileParameter(Skyline.DataMiner.Net.Profiles.Parameter netParameter, Skyline.DataMiner.Library.Solutions.SRM.Model.Parameter srmParameter = null) + { + if (netParameter == null) + throw new System.ArgumentNullException(nameof(netParameter)); + Name = netParameter.Name; + Id = netParameter.ID; + Category = netParameter.Categories; + Type = (Skyline.DataMiner.Library.Solutions.SRM.Model.ParameterType)netParameter.Type; + Discreets = netParameter.Type == Skyline.DataMiner.Net.Profiles.Parameter.ParameterType.Discrete ? System.Linq.Enumerable.ToList(System.Linq.Enumerable.Select(netParameter.Discretes, x => new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.Discreet(x))) : new System.Collections.Generic.List(); + DefaultValue = netParameter.DefaultValue; + Stepsize = netParameter.Stepsize; + Decimals = netParameter.Decimals; + RangeMax = netParameter.RangeMax; + RangeMin = netParameter.RangeMin; + Unit = netParameter.Units; + if (srmParameter != null) + Value = srmParameter.Value; + initialValue = Value; + } + + /// + /// The id of the profile parameter + /// Only required when action is "NEW" or "EDIT" + /// + public System.Guid Id + { + get; + set; + } + + /// + /// Gets or sets the name of the ProfileParameter. + /// + public string Name + { + get; + set; + } + + /// + /// Property set by controller and used by UI for validation. + /// + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.ValidationInfo ValueValidation + { + get + { + if (valueValidation == null) + valueValidation = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.ValidationInfo(); + return valueValidation; + } + + set + { + valueValidation = value; + } + } + + /// + /// The value of the profile parameter + /// Only required when action is "NEW" or "EDIT" + /// + public object Value + { + get + { + return value; + } + + set + { + if (this.value != value) + { + this.value = value; + ValueChanged?.Invoke(this, this.value); + } + } + } + + /// + /// Gets the string representation of the value contained in this ProfileParameter. + /// + [Newtonsoft.Json.JsonIgnore] + public string StringValue + { + get => System.Convert.ToString(value); + } + + /// + /// This event is called when the value of this ProfileParameter is updated. + /// + public event System.EventHandler ValueChanged; + /// + /// The categories of the Profile Parameter. + /// + public Skyline.DataMiner.Net.Profiles.ProfileParameterCategory Category + { + get; + set; + } + + /// + /// Indicates if the Profile Parameter is a Capability. + /// + public bool IsCapability + { + get => (Category & Skyline.DataMiner.Net.Profiles.ProfileParameterCategory.Capability) == Skyline.DataMiner.Net.Profiles.ProfileParameterCategory.Capability; + } + + /// + /// Gets a boolean indicating if Change Tracking has been enabled for this object. + /// + /// + [Newtonsoft.Json.JsonIgnore] + public bool ChangeTrackingEnabled + { + get; + private set; + } + + /// + /// Gets a boolean indicating if this object has been changed since object construction or since last call. + /// + /// + [Newtonsoft.Json.JsonIgnore] + public bool IsChanged => ChangeInfo.IsChanged; + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo ChangeInfo => GetChanges(); + public bool IsNonInterfaceDtrParameter => Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids._Matrix || Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids._OrbitalPosition; + public System.Collections.Generic.List Discreets + { + get + { + return discreets; + } + + set + { + if (value == null) + { + discreets = new System.Collections.Generic.List(); + } + else + { + discreets = value; + } + } + } + + public Skyline.DataMiner.Library.Solutions.SRM.Model.ParameterType Type + { + get; + set; + } + + public Skyline.DataMiner.Net.Profiles.ParameterValue DefaultValue + { + get; + set; + } + + public double RangeMin + { + get; + set; + } + + public double RangeMax + { + get; + set; + } + + public double Stepsize + { + get; + set; + } + + public int Decimals + { + get; + set; + } + + public string Unit + { + get; + set; + } + + public override bool Equals(object obj) + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter other = obj as Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter; + if (other == null) + return false; + return Id.Equals(other.Id); + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } + + /// + /// Resets Change Tracking. + /// + /// + public void AcceptChanges() + { + initialValue = Value; + } + + public override string ToString() + { + return $"{Name} = {StringValue}"; + } + + /// + /// Gets the changes made to this object since object construction or since last call. + /// + /// A flags enum containing the types of changes. + /// + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo GetChanges() + { + var changeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo(); + if (Value != initialValue) + { + if (System.Linq.Enumerable.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.AllAudioProcessingRequiredGuids, Id)) + changeInfo.ProfileParameterChangeInfo.MarkAudioProcessingProfileParametersChanged(); + else if (Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.VideoFormat) + changeInfo.ProfileParameterChangeInfo.MarkVideoProcessingProfileParametersChanged(); + else if (Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.RemoteGraphics) + changeInfo.ProfileParameterChangeInfo.MarkGraphicsProcessingProfileParametersChanged(); + else if (IsNonInterfaceDtrParameter) + changeInfo.ProfileParameterChangeInfo.MarkDtrProfileParametersChanged(); + else + changeInfo.ProfileParameterChangeInfo.MarkOtherProfileParametersChanged(); + } + + return changeInfo; + } + } + } + + namespace Resources + { + public interface IResourceManager + { + } + + /// + /// Wrapper class around the ResourceManagerHelper. + /// This was introduced to allow mocking of this class through the IResourceManager interface. + /// + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Skyline.DataMiner.Storage.Types.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLNetTypes.dll")] + public class ResourceManager : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Resources.IResourceManager + { + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers; + public ResourceManager(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers) + { + this.helpers = helpers ?? throw new System.ArgumentNullException(nameof(helpers)); + } + } + } + + namespace Service + { + public enum Status + { + /// + /// Service which is under preliminary order. + /// + [System.ComponentModel.Description("Preliminary")] + Preliminary = 0, + /// + /// Service which is waiting for device configuration. + /// User tasks are generated for specific service related manual tasks. + /// + [System.ComponentModel.Description("Configuration Pending")] + ConfigurationPending = 1, + /// + /// Service where all related user tasks are completed. + /// + [System.ComponentModel.Description("Configuration Completed")] + ConfigurationCompleted = 2, + /// + /// Service where some component is overbooked. + /// This is actually not possible in SRM and will more likely be like "Quaranteened" eg "Resource Missing" + /// + [System.ComponentModel.Description("Resource Overbooked")] + ResourceOverbooked = 3, + /// + /// Service which is withing 30min of start time. + /// + [System.ComponentModel.Description("Service Cueing")] + ServiceCueing = 4, + /// + /// Service where start time is reached and is not yet finished. + /// + [System.ComponentModel.Description("Service Running")] + ServiceRunning = 5, + /// + /// Service in post roll. + /// + [System.ComponentModel.Description("Post Roll")] + PostRoll = 6, + /// + /// Service where end time is reached but was only partially delivered or not delivered at all. + /// + [System.ComponentModel.Description("Service Completed With Errors")] + ServiceCompletedWithErrors = 7, + /// + /// Service where end time is reached. + /// + [System.ComponentModel.Description("Service Completed")] + ServiceCompleted = 8, + /// + /// Service which was cancelled. + /// + [System.ComponentModel.Description("Cancelled")] + Cancelled = 9, + /// + /// Service which has incompleted file processing user tasks. + /// + [System.ComponentModel.Description("File Processing")] + FileProcessing = 10 + } + + public enum Type + { + Source, + Destination, + Recording, + Transmission, + VideoProcessing, + AudioProcessing, + GraphicsProcessing, + Routing + } + + public enum FileDestination + { + [System.ComponentModel.Description("ARCHIVE (METRO)")] + ArchiveMetro, + [System.ComponentModel.Description("IPLAY HKI")] + IplayHki, + [System.ComponentModel.Description("IPLAY VSA")] + IplayVsa, + [System.ComponentModel.Description("IPLAY TRE")] + IplayTre, + [System.ComponentModel.Description("UA IPLAY")] + UaIplay, + [System.ComponentModel.Description("ISILON")] + Isilon + } + + public enum VideoResolution + { + [System.ComponentModel.Description("576i50")] + Resolution576i50, + [System.ComponentModel.Description("1080i50")] + Resolution1080i50, + [System.ComponentModel.Description("1080p50")] + Resolution1080p50 + } + + public enum VideoCodec + { + [System.ComponentModel.Description("AVCi100")] + AvcI100, + [System.ComponentModel.Description("XDcamHD50")] + XdCamHd50 + } + + public enum TimeCodec + { + [System.ComponentModel.Description("Real")] + Real, + [System.ComponentModel.Description("Non-Real")] + NonReal + } + + public enum ProxyFormat + { + [System.ComponentModel.Description("Both")] + Both, + [System.ComponentModel.Description("MPEG-1")] + Mpeg1, + [System.ComponentModel.Description("MPEG-4")] + Mpeg4 + } + + public interface IServiceManager + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service GetService(System.Guid serviceId); + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + /// + /// The recording configuration containing additional details for a recording that are not stored in profile parameters. + /// + public class RecordingConfiguration : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.IYleChangeTracking + { + private bool initialSubrecordingsNeeded; + private string initialNameOfServiceToRecord; + private string initialRecordingName; + private string initialPlasmaIdForArchive; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.FileDestination initialRecordingFileDestination; + private string initialRecordingFileDestinationPath; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.VideoResolution initialRecordingFileVideoResolution; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.TimeCodec initialRecordingFileTimeCodec; + private bool initialSubtitleProxy; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ProxyFormat initialProxyFormat; + private bool initialFastRerunCopy; + private bool initialAreenaCopy; + private bool initialBroadcastReady; + private System.DateTime initialDeadlineForArchiving; + public RecordingConfiguration() + { + RecordingFileDestination = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.FileDestination.ArchiveMetro; + RecordingFileVideoResolution = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.VideoResolution.Resolution1080i50; + RecordingFileVideoCodec = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.VideoCodec.AvcI100; + RecordingFileTimeCodec = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.TimeCodec.Real; + SubtitleProxy = false; + ProxyFormat = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ProxyFormat.Mpeg1; + FastRerunCopy = false; + FastAreenaCopy = false; + BroadcastReady = false; + IsPlasmaLiveNews = false; + SubRecordingsNeeded = false; + SubRecordings = new System.Collections.Generic.List(); + } + + /// + /// The service name of the service that needs to be recorded. + /// Only needs to be set in case the operator in the UI selected to record a specific service. + /// + public string NameOfServiceToRecord + { + get; + set; + } + + /// + /// Name of the recording. + /// + public string RecordingName + { + get; + set; + } + + /// + /// Plasma ID for archiving. + /// Only applicable on Live recordings. + /// + public string PlasmaIdForArchive + { + get; + set; + } + + /// + /// Destination of the recording file. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.FileDestination RecordingFileDestination + { + get; + set; + } + + /// + /// The video resolution of the recording file. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.VideoResolution RecordingFileVideoResolution + { + get; + set; + } + + /// + /// The video codec of the recording file. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.VideoCodec RecordingFileVideoCodec + { + get; + set; + } + + /// + /// The time codec for the recording file. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.TimeCodec RecordingFileTimeCodec + { + get; + set; + } + + /// + /// Indicates if subtitle proxy is required. + /// + public bool SubtitleProxy + { + get; + set; + } + + /// + /// The proxy format. + /// Only in case Subtitle Proxy is required. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ProxyFormat ProxyFormat + { + get; + set; + } + + /// + /// Indicates if a fast rerun copy is required. + /// + public bool FastRerunCopy + { + get; + set; + } + + /// + /// Indicates if a fast areena copy is required. + /// + public bool FastAreenaCopy + { + get; + set; + } + + /// + /// Indicates if this recording is broadcast ready. + /// + public bool BroadcastReady + { + get; + set; + } + + /// + /// The destination path for this recording. + /// + public string RecordingFileDestinationPath + { + get; + set; + } + + /// + /// Indicates if sub recordings are needed. + /// + public bool SubRecordingsNeeded + { + get; + set; + } + + /// + /// Indicates if the recording configuration is part of a Plasma Live News order. + /// + public bool IsPlasmaLiveNews + { + get; + set; + } + + /// + /// The deadline for archiving. + /// + public System.DateTime DeadLineForArchiving + { + get; + set; + } + + /// + /// TV Channel name from the Transmission table in the MediaGenix WhatsOn element. + /// Used for the short description on service level. + /// Only applicable for plasma services. + /// + public string PlasmaTvChannelName + { + get; + set; + } + + /// + /// Program name from the Programs table in the MediaGenix WhatsOn element. + /// Used for the short description on service level. + /// Only applicable for plasma services. + /// + public string PlasmaProgramName + { + get; + set; + } + + /// + /// The list of sub recordings. + /// + public System.Collections.Generic.List SubRecordings + { + get; + set; + } + + /// + /// Gets a boolean indicating if this object has been changed since object construction or since last call. + /// + /// + public bool IsChanged => ChangeInfo.IsChanged; + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo ChangeInfo => GetChanges(); + /// + /// Gets a boolean indicating if Change Tracking is enabled. + /// + public bool ChangeTrackingEnabled + { + get; + private set; + } + + /// + /// Gets the type of changes that have happened since object creation or since last call. + /// + /// A flags enum containing the types of changes. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo GetChanges() + { + var changeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo(); + bool propertiesHaveChanged = false; + propertiesHaveChanged |= initialNameOfServiceToRecord != NameOfServiceToRecord; + propertiesHaveChanged |= initialRecordingName != RecordingName; + propertiesHaveChanged |= initialRecordingFileDestination != RecordingFileDestination; + propertiesHaveChanged |= initialRecordingFileDestinationPath != RecordingFileDestinationPath; + propertiesHaveChanged |= initialPlasmaIdForArchive != PlasmaIdForArchive; + propertiesHaveChanged |= initialRecordingFileVideoResolution != RecordingFileVideoResolution; + propertiesHaveChanged |= initialRecordingFileTimeCodec != RecordingFileTimeCodec; + propertiesHaveChanged |= initialFastRerunCopy != FastRerunCopy; + propertiesHaveChanged |= initialAreenaCopy != FastAreenaCopy; + propertiesHaveChanged |= initialSubtitleProxy != SubtitleProxy; + propertiesHaveChanged |= initialProxyFormat != ProxyFormat; + propertiesHaveChanged |= initialBroadcastReady != BroadcastReady; + propertiesHaveChanged |= initialDeadlineForArchiving != DeadLineForArchiving; + propertiesHaveChanged |= initialSubrecordingsNeeded != SubRecordingsNeeded; + if (propertiesHaveChanged) + changeInfo.MarkCustomPropertiesChanged(); + foreach (var subrecording in SubRecordings) + changeInfo.CombineWith(subrecording.ChangeInfo); + return changeInfo; + } + + /// + /// Resets Change Tracking. + /// + /// + public void AcceptChanges() + { + initialNameOfServiceToRecord = NameOfServiceToRecord; + initialRecordingName = RecordingName; + initialPlasmaIdForArchive = PlasmaIdForArchive; + initialRecordingFileDestination = RecordingFileDestination; + initialRecordingFileDestinationPath = RecordingFileDestinationPath; + initialRecordingFileVideoResolution = RecordingFileVideoResolution; + initialRecordingFileTimeCodec = RecordingFileTimeCodec; + initialSubtitleProxy = SubtitleProxy; + initialProxyFormat = ProxyFormat; + initialFastRerunCopy = FastRerunCopy; + initialAreenaCopy = FastAreenaCopy; + initialBroadcastReady = BroadcastReady; + initialSubrecordingsNeeded = SubRecordingsNeeded; + initialDeadlineForArchiving = DeadLineForArchiving; + foreach (var subrecording in SubRecordings) + subrecording.AcceptChanges(); + } + + /// + /// Deserialize a json string into a RecordingConfiguration object. + /// + /// The recording configuration json string. + /// A RecordingConfiguration object. + public static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.RecordingConfiguration Deserialize(string recordingConfiguration) + { + try + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(recordingConfiguration); + } + catch (System.Exception) + { + return null; + } + } + + public override string ToString() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.AppendLine($"Subtitle proxy: " + SubtitleProxy + " | "); + sb.AppendLine($"Fast rerun copy: " + FastRerunCopy + " | "); + sb.AppendLine($"Broadcast ready: " + BroadcastReady + " | "); + sb.AppendLine($"Sub recording needed: " + SubRecordingsNeeded + " | "); + foreach (var subRecording in SubRecordings) + { + sb.AppendLine($"{subRecording.ToString()} | "); + } + + return sb.ToString(); + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Skyline.DataMiner.Storage.Types.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLNetTypes.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class Service : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.IYleChangeTracking + { + private const string None = "None"; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.ValidationInfo startValidation; + private string name; + private bool isCancelled; + // Fields for change tracking + private System.DateTime initialStart; + //private DateTime initialStartWithPreRoll; + private System.DateTime initialEnd; + //private DateTime initialEndWithPostRoll; + private bool initialIntegrationIsMaster; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.RecordingConfiguration initialRecordingConfiguration; + private string initialContactInfoName; + private string initialContactInfoPhone; + private string initialLiveUDeviceName; + private string initialAudioReturnInfo; + private string initialVidigoStreamSourceLink; + private string initialComments; + private System.Collections.Generic.HashSet initialSecurityViewIds; + private System.Collections.Generic.List initialFunctions; + private string comments; + private System.DateTime start; + private System.DateTime end; + private System.TimeSpan preRoll; + private System.TimeSpan postRoll; + private bool hasCustomPreRoll = false; + private bool hasCustomPostRoll = false; + private System.Collections.Generic.Dictionary selectableSecurityViewIds; + private bool isEventLevelReception; + private bool isGlobalEventLevelReception; + //private DateTime startWithPreRoll; + //private DateTime endWithPostRoll; + public Service() + { + Id = System.Guid.NewGuid(); + IsBooked = false; + Functions = new System.Collections.Generic.List(); + Children = new System.Collections.Generic.List(); + OrderReferences = new System.Collections.Generic.HashSet(); + Interfaces = new System.Collections.Generic.List(); + SecurityViewIds = new System.Collections.Generic.HashSet(); + UserTasks = new System.Collections.Generic.List(); + } + + public Service(string name): this() + { + this.name = name; + } + + public Service(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service) + { + // Deep copy using reflection + System.Reflection.PropertyInfo[] propertyInfo = typeof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service).GetProperties(); + foreach (System.Reflection.PropertyInfo property in propertyInfo) + { + if (property.CanWrite) + { + property.SetValue(this, property.GetValue(service)); + } + } + + Id = service.Id; + } + + /// + /// Creates a new Service instance based on a ServiceConfiguration. + /// + /// + /// ServiceConfiguration object defining the Service. + /// + /// + public Service(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, int nodeId, string nodeLabel, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Configuration.ServiceConfiguration configuration) + { + helpers.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), out var stopwatch, Name); + Name = configuration.Name; + Id = configuration.Id; + PreRoll = configuration.PreRoll; + Start = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.Truncate(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.Truncate(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.FromServiceConfiguration(configuration.Start), System.TimeSpan.FromSeconds(1)), System.TimeSpan.FromMilliseconds(1)); + End = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.Truncate(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.Truncate(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.FromServiceConfiguration(configuration.End), System.TimeSpan.FromSeconds(1)), System.TimeSpan.FromMilliseconds(1)); + BackupType = configuration.ServiceLevel.HasValue ? configuration.ServiceLevel.Value : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.BackupType.None; + LinkedServiceId = configuration.LinkedServiceId; + LinkedEventIds = configuration.LinkedEventIds ?? new System.Collections.Generic.HashSet(); + IsEurovisionService = configuration.IsEurovisionService; + IsEurovisionMultiFeedService = configuration.IsEurovisionMultiFeedService; + EurovisionWorkOrderId = configuration.EurovisionWorkOrderId; + EurovisionTransmissionNumber = configuration.EurovisionTransmissionNumber; + EurovisionBookingDetails = configuration.EurovisionBookingDetails; + EurovisionServiceConfigurations = configuration.EurovisionServiceConfigurations; + EurovisionDestinationId = configuration.EurovisionDestinationId; + EurovisionTechnicalSystemId = configuration.EurovisionTechnicalSystemId; + IntegrationType = configuration.IntegrationType; + IntegrationIsMaster = configuration.IntegrationIsMaster; + Comments = configuration.Comments; + ContactInformationName = configuration.ContactInformationName; + ContactInformationTelephoneNumber = configuration.ContactInformationTelephoneNumber; + LiveUDeviceName = configuration.LiveUDeviceName; + AudioReturnInfo = configuration.AudioReturnInfo; + VidigoStreamSourceLink = configuration.VidigoStreamSourceLink; + AdditionalDescriptionUnknownSource = configuration.AdditionalDescriptionUnknownSource; + IsUnknownSourceService = configuration.IsUnknownSourceService; + IsAudioConfigurationCopiedFromSource = configuration.IsAudioConfigurationCopiedFromSource; + RequiresRouting = configuration.RequiresRouting; + RoutingConfigurationUpdateRequired = configuration.RoutingConfigurationUpdateRequired; + RecordingConfiguration = configuration.RecordingConfiguration; + IsBooked = false; + IsPreliminary = true; + NodeId = nodeId; + NodeLabel = nodeLabel; + Children = new System.Collections.Generic.List(); + Functions = new System.Collections.Generic.List(); + OrderReferences = configuration.OrderReferences ?? new System.Collections.Generic.HashSet(); + UserTasks = new System.Collections.Generic.List(); + IsEventLevelReception = configuration.IsEventLevelReception; + IsGlobalEventLevelReception = configuration.IsGlobalEventLevelReception; + HasResourcesAssigned = false; + HasAnIssueBeenreportedManually = configuration.HasAnIssueBeenreportedManually; + SecurityViewIds = configuration.SecurityViewIds; + NameOfServiceToTransmit = configuration.NameOfServiceToTransmit; + ChangedByUpdateServiceScript = configuration.ChangedByUpdateServiceScript; + InitServiceDefinition(helpers, this, configuration.ServiceDefinitionId, string.Empty, configuration.Functions, nodeId, nodeLabel); + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), $"Summary of properties on service object taken from service configuration: ID={Id} IsELR={IsEventLevelReception}, IsGlobalELR={IsGlobalEventLevelReception}, SecurityViewIds={string.Join(",", SecurityViewIds)}, RequiresRouting={RequiresRouting}, RoutingConfigurationUpdateRequired={RoutingConfigurationUpdateRequired}, HasIssueBeenReportedManually={HasAnIssueBeenreportedManually}, NameOfServiceToRecordOrTransmit={NameOfServiceToTransmitOrRecord}, IntegrationIsMaster={IntegrationIsMaster}, Timing={TimingInfoToString(this)}, ChangedByUpdateServiceScript={ChangedByUpdateServiceScript}", Name); + helpers.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), null, stopwatch); + } + + private static void InitServiceDefinition(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, System.Guid serviceDefinitionId, string serviceDefinitionName, System.Collections.Generic.Dictionary configuredFunctions, int nodeId, string nodeLabel) + { + helpers.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(InitServiceDefinition), out var stopwatch); + if (serviceDefinitionId != System.Guid.Empty) + { + service.Definition = helpers.ServiceDefinitionManager.GetServiceDefinition(serviceDefinitionId); + if (service.Definition != null) + { + // Set Pre- and PostRoll + //PreRoll = ServiceManager.GetPreRollDuration(Definition, IntegrationType); + service.PostRoll = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager.GetPostRollDuration(service.Definition, service.IntegrationType); + } + + if (service.Definition?.FunctionDefinitions != null && configuredFunctions != null) + { + foreach (var functionDefinition in service.Definition.FunctionDefinitions) + { + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), "Handling Function Definition " + functionDefinition.Name, service.Name); + var functionNode = System.Linq.Enumerable.FirstOrDefault(service.Definition.Diagram.Nodes, n => n.Label == functionDefinition.Label); + if (functionNode == null) + continue; + var function = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function{Id = functionDefinition.Id, Name = functionDefinition.Name, NodeId = functionNode.ID, ConfigurationOrder = functionDefinition.ConfigurationOrder, Parameters = new System.Collections.Generic.List(), InterfaceParameters = new System.Collections.Generic.List(), Definition = functionDefinition, IsOptional = functionDefinition.Options != null && functionDefinition.Options.Contains("Optional")}; + UpdateFunctionFromServiceConfiguration(helpers, configuredFunctions, function, functionDefinition); + service.Functions.Add(function); + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), $"Function summary: {function.Configuration.ToString()}", service.Name); + } + + service.AudioChannelConfiguration = GetAudioChannelConfiguration(service.Functions); + } + } + else if (service.IsEurovisionService) + { + bool hasServiceName = !string.IsNullOrEmpty(service.Name); + bool hasServiceDefinitionName = !string.IsNullOrEmpty(serviceDefinitionName); + bool serviceNameContainsReception = hasServiceName && service.Name.Contains("Reception"); + bool serviceNameContainsTransmission = hasServiceName && service.Name.Contains("Transmission"); + bool serviceDefinitionNameContainsReception = hasServiceDefinitionName && serviceDefinitionName.Contains("Reception"); + bool serviceDefinitionNameContainsTransmission = hasServiceDefinitionName && serviceDefinitionName.Contains("Transmission"); + // Eurovision service that was booked from the CustomerUI + if (serviceNameContainsReception || serviceDefinitionNameContainsReception) + { + service.Definition = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition.GenerateEurovisionReceptionServiceDefinition(); + } + else if (serviceNameContainsTransmission || serviceDefinitionNameContainsTransmission) + { + service.Definition = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition.GenerateEurovisionTransmissionServiceDefinition(); + } + else + { + throw new System.InvalidOperationException("Unable to determine the service definition for the following Eurovision Service: " + service.Name); + } + } + else if (service.IsUnknownSourceService) + { + service.Definition = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition.GenerateDummyUnknownReceptionServiceDefinition(); + service.NodeId = nodeId; + service.NodeLabel = nodeLabel; + } + else + { + // dummy source + service.Definition = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition.GenerateDummyReceptionServiceDefinition(); + service.NodeId = nodeId; // node ID of a main source service should always be 1 + service.NodeLabel = nodeLabel; + } + + helpers.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(InitServiceDefinition), null, stopwatch); + } + + private static void UpdateFunctionFromServiceConfiguration(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, System.Collections.Generic.Dictionary configuredFunctions, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function function, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.FunctionDefinition functionDefinition) + { + if (!configuredFunctions.TryGetValue(functionDefinition.Id, out var functionConfiguration)) + return; + function.RequiresResource = functionConfiguration.RequiresResource; + try + { + function.McrHasOverruledFixedTieLineLogic = functionConfiguration.McrHasOverruledFixedTieLineLogic; + } + catch + { + function.McrHasOverruledFixedTieLineLogic = false; + } + + if (functionConfiguration.ResourceId != System.Guid.Empty) + { + try + { + function.Resource = helpers.ResourceManagerHelper.GetResource(functionConfiguration.ResourceId) as Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource; + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(UpdateFunctionFromServiceConfiguration), $"Set function {function?.Name} resource to '{function?.Resource?.Name}' based on service configuration"); + } + catch (System.Exception e) + { + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(UpdateFunctionFromServiceConfiguration), $"Exception retrieving function {function?.Name} resource '{functionConfiguration.ResourceId}': {e}"); + } + } + + if (functionDefinition.ProfileDefinition != null) + { + var parametersToAdd = GetProfileParametersFromConfiguration(helpers, functionConfiguration, function, functionDefinition.ProfileDefinition); + function.Parameters.AddRange(parametersToAdd); + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(UpdateFunctionFromServiceConfiguration), $"Added following profile parameters from configuration to function {function.Name}: '{string.Join(", ", System.Linq.Enumerable.Select(parametersToAdd, p => $"{p.Name}={p.Value}"))}'"); + } + + if (functionDefinition.InterfaceProfileDefinitions != null && System.Linq.Enumerable.Any(functionDefinition.InterfaceProfileDefinitions)) + { + foreach (var interfaceProfileDefinition in functionDefinition.InterfaceProfileDefinitions.Values) + { + var parametersToAdd = GetProfileParametersFromConfiguration(helpers, functionConfiguration, function, interfaceProfileDefinition); + function.InterfaceParameters.AddRange(parametersToAdd); + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(UpdateFunctionFromServiceConfiguration), $"Added following interface profile parameters from configuration to function {function.Name}: '{string.Join(", ", System.Linq.Enumerable.Select(parametersToAdd, p => $"{p.Name}={p.Value}"))}'"); + } + } + + helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(UpdateFunctionFromServiceConfiguration), $"Note: function object should contain all of its profile parameters now."); + } + + private static System.Collections.Generic.List GetProfileParametersFromConfiguration(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Configuration.FunctionConfiguration configuration, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function function, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileDefinition profileDefinition) + { + var parameters = new System.Collections.Generic.List(); + foreach (var profileDefinitionParameter in profileDefinition.ProfileParameters) + { + bool parameterIsAlreadyAdded = System.Linq.Enumerable.Any(System.Linq.Enumerable.Concat(function.Parameters, function.InterfaceParameters), p => p.Id == profileDefinitionParameter.Id); + if (parameterIsAlreadyAdded) + continue; + var functionProfileParameter = helpers.ProfileManager.GetProfileParameter(profileDefinitionParameter.Id); + if (configuration.ProfileParameters != null) + { + var serviceConfigurationProfileParameter = System.Linq.Enumerable.FirstOrDefault(configuration.ProfileParameters, p => p.Key == functionProfileParameter.Id); + functionProfileParameter.Value = serviceConfigurationProfileParameter.Value; + } + + parameters.Add(functionProfileParameter); + } + + return parameters; + } + + /// + /// Reservation instance of the service. + /// + public System.Guid Id + { + get; + set; + } + + /// + /// Name of the order that uses this service. + /// Currently used for recording services + /// + public string OrderName + { + get; + set; + } + + /// + /// The name of the service. + /// + public string Name + { + get + { + if (name == null && Definition != null) + { + // the id used here is not the id of the reservation itself + // this id is generated when the service object itself is created initially + // the name of a contributed service cannot be changed afterwards and is only known after booking the reservation + // this id is included in the name because the name needs to be unique + name = $"{Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceType)} [{Id}]"; + } + + return name; + } + + internal set + { + name = value; + } + } + + /// + /// Start date and time of the service. + /// + public System.DateTime Start + { + get + { + return start; + } + + set + { + if (start != value) + { + if (start == default(System.DateTime)) + initialStart = value; + start = value; + StartChanged?.Invoke(this, start); + StartWithPreRollChanged?.Invoke(this, StartWithPreRoll); + } + } + } + + /// + /// Property set by controller and used by UI for validation. + /// + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.ValidationInfo StartValidation + { + get => startValidation ?? (startValidation = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.ValidationInfo()); + set => startValidation = value; + } + + internal event System.EventHandler StartChanged; + public System.DateTime StartWithPreRoll => Start.Subtract(PreRoll); + internal event System.EventHandler StartWithPreRollChanged; + /// + /// End date and time of the service. + /// + public System.DateTime End + { + get => end; + set + { + if (end != value) + { + if (end == default(System.DateTime)) + initialEnd = value; + end = value; + EndChanged?.Invoke(this, end); + EndWithPostRollChanged?.Invoke(this, EndWithPostRoll); + } + } + } + + internal event System.EventHandler EndChanged; + public System.DateTime EndWithPostRoll => End.Add(PostRoll); + internal event System.EventHandler EndWithPostRollChanged; + public System.TimeSpan PreRoll + { + get => hasCustomPreRoll ? preRoll : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager.GetPreRollDuration(Definition, IntegrationType); + internal set + { + hasCustomPreRoll = true; + preRoll = value; + } + } + + public System.TimeSpan PostRoll + { + get => hasCustomPostRoll ? postRoll : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager.GetPostRollDuration(Definition, IntegrationType); + internal set + { + hasCustomPostRoll = true; + postRoll = value; + } + } + + /// + /// The status of this service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status Status => GenerateStatus(); + /// + /// Indicates if this Service is saved or not. Used to determine the correct Service Status. + /// + public bool IsPreliminary + { + get; + set; + } + + /// + /// The list of orders ids this service is used in. + /// For now this doesn't contain the order itself to avoid having to retrieve all orders each time we retrieve a service. + /// Could be improved in the future. + /// + public System.Collections.Generic.HashSet OrderReferences + { + get; + set; + } + + /// + /// The service definition for the service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition Definition + { + get; + set; + } + + /// + /// The reservation which is retrieved during FromReservationInstance() is stored in this property. + /// + public Skyline.DataMiner.Net.ResourceManager.Objects.ServiceReservationInstance ReservationInstance + { + get; + private set; + } + + /// + /// The service level (backup) for the service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.BackupType BackupType + { + get; + set; + } + + /// + /// The list of functions in this service. + /// + public System.Collections.Generic.List Functions + { + get; + set; + } + + /// + /// Gets the configuration of the Audio Channel Profile Parameters. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.AudioChannelConfiguration AudioChannelConfiguration + { + get; + private set; + } + + /// + /// Is set to true when a destination or recording contains an audio configuration that is copied from source. + /// + public bool IsAudioConfigurationCopiedFromSource + { + get; + set; + } + + /// + /// The comments for the service. + /// + public string Comments + { + get => comments; + set + { + comments = value; + CommentsChanged?.Invoke(this, comments); + } + } + + internal event System.EventHandler CommentsChanged; + /// + /// The list of child services for the service. + /// + [Newtonsoft.Json.JsonIgnore] + public System.Collections.Generic.List Children + { + get; + set; + } + + /// + /// Indicates which integration created this Service. + /// If not specified this will be set to None. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType IntegrationType + { + get; + set; + } + + /// + /// Gets a boolean indicating if the related integration is master or if DataMiner is the master. + /// Used to determine which updates from which sources are allowed. + /// Always false for manually created services. + /// + public bool IntegrationIsMaster + { + get; + set; + } + + = false; + /// + /// The resource linked to this service. + /// This is an internal property. + /// + public Skyline.DataMiner.Net.Messages.Resource ContributingResource + { + get; + set; + } + + /// + /// The resource pool for the resource linked to the service (can be found in Contributing Config property of Service Definition). + /// This is an internal property. + /// + public Skyline.DataMiner.Net.Messages.ResourcePool ResourcePool + { + get; + set; + } + + /// + /// The node id for this service in the order service definition. + /// This is an internal property. + /// + public int NodeId + { + get; + set; + } + + /// + /// The node label for this service in the order service definition. + /// + public string NodeLabel + { + get; + set; + } + + /// + /// The available interfaces for this service in the order service definitions. + /// This is an internal property. + /// + public System.Collections.Generic.IEnumerable Interfaces + { + get; + set; + } + + /// + /// The id of the event in which this service can be used as an Event Level Reception. + /// This is an internal property. + /// + public System.Collections.Generic.HashSet LinkedEventIds + { + get; + set; + } + + /// + /// Indicates if this service can be used as an Event Level Reception. + /// This is an internal property. + /// + public bool IsEventLevelReception + { + get => isEventLevelReception; + set + { + if (value == IsEventLevelReception) + return; + isEventLevelReception = value; + IsEventLevelReceptionChanged?.Invoke(this, IsEventLevelReception); + } + } + + public event System.EventHandler IsEventLevelReceptionChanged; + /// + /// Indicates if this service can be used as an global Event Level Reception. + /// This is an internal property. + /// + public bool IsGlobalEventLevelReception + { + get => isGlobalEventLevelReception; + set + { + if (value == IsGlobalEventLevelReception) + return; + isGlobalEventLevelReception = value; + IsGlobalEventLevelReceptionChanged?.Invoke(this, IsGlobalEventLevelReception); + } + } + + public event System.EventHandler IsGlobalEventLevelReceptionChanged; + /// + /// Gets a boolean indicating if this service is already booked as ELR. + /// + public bool IsAlreadyBookedAsEventLevelReception => IsBooked && IsEventLevelReception && System.Linq.Enumerable.Any(LinkedEventIds); + /// + /// Gets a boolean indicating if this service is already booked as a global ELR. + /// + public bool IsAlreadyBookedAsGlobalEventLevelReception => IsBooked && IsGlobalEventLevelReception && System.Linq.Enumerable.Any(LinkedEventIds); + /// + /// Indicates if this service has any Resources assigned to it. + /// + public bool HasResourcesAssigned + { + get; + set; + } + + /// + /// It only applies to Child Services (Destination/Recording) of a backup source when the Service Level of the Backup is Active. + /// This is the Id of the Service to which this service is linked. + /// + public System.Guid LinkedServiceId + { + get; + set; + } + + /// + /// Should be passed from the UI to the Library when a new Order is created where the Backup source is configured as Active backup. + /// This property links the Source child service to it backup counterpart and vice versa. + /// + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service LinkedService + { + get; + set; + } + + /// + /// Should be passed from the UI to the Library when an order is created. + /// This property contains the type of the order this service is part of. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderType OrderType + { + get; + set; + } + + /// + /// A list of User Tasks linked to this service. + /// + [Newtonsoft.Json.JsonIgnore] + public System.Collections.Generic.List UserTasks + { + get; + set; + } + + /// + /// Indicates if this is an Eurovision service. + /// + public bool IsEurovisionService + { + get; + set; + } + + /// + /// This is set to true from the HandleIntegrationUpdate script if the synopsis contains a value for the ioMuxName field. + /// The ioMuxName field is used to define multiple multiplexed feeds in the signal. + /// If this boolean is true, you will be able to edit the Service Selection profile parameter of the Satellite Reception in the LiveOrderForm. + /// + public bool IsEurovisionMultiFeedService + { + get; + set; + } + + /// + /// The id of the Eurovision work order that was requested through the Live Order Form. + /// + public string EurovisionWorkOrderId + { + get; + set; + } + + /// + /// The transmission number of the Eurovision booking in case of a Eurovision service. + /// This can be used to map the incoming Eurovision synopsis to this service. + /// This is only applicable if this is a Eurovision service and if it was automatically created by the Eurovision integration. + /// + public string EurovisionTransmissionNumber + { + get; + set; + } + + /// + /// Only used in the CustomerUI script. + /// This value is not stored or retrieved from the SRM configuration. + /// Used to determine if the Resource assigned to this Service should be included when updating the available Resources in the script. + /// + public bool IsDuplicate + { + get; + set; + } + + = false; + /// + /// Serialized data of the Eurovision booking details as configured in the Customer UI. + /// This is only applicable in case of an Eurovision service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.EurovisionBookingDetails EurovisionBookingDetails + { + get; + set; + } + + /// + /// This property is only used when the Service is a Dummy Service that was generated from the EBU integration. + /// In that case this property will contain the possible Receptions or Transmissions. + /// + public System.Collections.Generic.List EurovisionServiceConfigurations + { + get; + set; + } + + /// + /// This property is only used when the Service is a Reception Service that was generated by the EBU integration. + /// In that case this property will contain the id of the destination in the synopsis on which this service is based. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string EurovisionDestinationId + { + get; + set; + } + + /// + /// This property is only used when the Service is a Reception or Transmission Service that was generated by the EBU integration. + /// In that case this property will contain the id of the technical system in the synopsis on which this service is based. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string EurovisionTechnicalSystemId + { + get; + set; + } + + /// + /// Whenever an order contains an unknown source the user is able to specify additional information + /// So that a user in a later stage can select the desired source whenever they want to book the order definitively. + /// + public string AdditionalDescriptionUnknownSource + { + get; + set; + } + + /// + /// Indicates if this service is unknown. + /// + public bool IsUnknownSourceService + { + get; + set; + } + + /// + /// Contact Information Name. + /// Only applicable for LiveU receptions. + /// Will be saved in a custom property for LiveU receptions; + /// + public string ContactInformationName + { + get; + set; + } + + /// + /// Contact Information Telephone Number. + /// Only applicable for LiveU receptions. + /// Will be saved in a custom property for LiveU receptions; + /// + public string ContactInformationTelephoneNumber + { + get; + set; + } + + /// + /// Additional information reception/transmission LiveU device name. + /// Only applicable for LiveU receptions or transmissions. + /// Will be saved in a custom property for LiveU receptions or transmissions; + /// + public string LiveUDeviceName + { + get; + set; + } + + /// + /// Normal users will fill in this field when LiveU is selected + /// News users will be able to fill in this field for every reception service. + /// + public string AudioReturnInfo + { + get; + set; + } + + /// + /// Additional info for IP RX Vidigo services. + /// Will be saved in custom property on IP receptions. + /// + public string VidigoStreamSourceLink + { + get; + set; + } + + /// + /// Contains additional recording configurations that are not stored as profile parameters. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.RecordingConfiguration RecordingConfiguration + { + get; + set; + } + + public string NameOfServiceToTransmit + { + get; + set; + } + + public string NameOfServiceToTransmitOrRecord + { + get + { + if (Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording) + return RecordingConfiguration?.NameOfServiceToRecord; + else if (Definition?.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Transmission) + return NameOfServiceToTransmit; + else + return string.Empty; + } + + set + { + if (Definition?.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && RecordingConfiguration != null) + RecordingConfiguration.NameOfServiceToRecord = value; + else if (Definition?.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Transmission) + NameOfServiceToTransmit = value; + } + } + + /// + /// Indicates if routing is required for this service. + /// + public bool RequiresRouting + { + get; + set; + } + + = true; + /// + /// Indicates if routing config should be updated whenever applicable. + /// + public bool RoutingConfigurationUpdateRequired + { + get; + set; + } + + = true; + /// + /// Indicates if this Service is a Dummy Service. + /// + public bool IsDummy => Definition == null || Definition.IsDummy; + /// + /// Indicates if the Service is a Dummy reception service that was generated by EBU Integration. + /// + public bool IsEbuDummyReception + { + get + { + if (Definition == null) + return false; + return IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Eurovision && Definition.IsDummy && Definition.ContributingConfig != null && Definition.ContributingConfig.ParentSystemFunction == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager.SourceServiceSystemFunctionId; + } + } + + /// + /// Indicates if the Service is a Dummy transmission service that was generated by EBU Integration. + /// + public bool IsEbuDummyTransmission + { + get + { + if (Definition == null) + return false; + return IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Eurovision && Definition.IsDummy && Definition.ContributingConfig != null && Definition.ContributingConfig.ParentSystemFunction == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager.TransmissionServiceSystemFunctionId; + } + } + + public bool IsBooked + { + get; + set; + } + + /// + /// Gets a collection of DataMiner Cube view IDs of views where this service is visible. If empty, this service should be visible for everyone. + /// + public System.Collections.Generic.HashSet SecurityViewIds + { + get; + set; + } + + = new System.Collections.Generic.HashSet(); + /// + /// Gets a collection of DataMiner Cube view IDs of views that are selected in the event of which this service is part of. Used by UI. + /// + public System.Collections.Generic.Dictionary SelectableSecurityViewIds + { + get => selectableSecurityViewIds; + set + { + selectableSecurityViewIds = value; + SelectableSecurityViewIdsChanged?.Invoke(this, SelectableSecurityViewIds); + } + } + + public event System.EventHandler> SelectableSecurityViewIdsChanged; + public string DisplayName + { + get; + set; + } + + /// + /// A boolean used to skip certain logic because the user input from the UpdateService script should overwrite it + /// + public bool ChangedByUpdateServiceScript + { + get; + set; + } + + = false; + /// + /// Gets a boolean indicating if this object has been changed since object construction or since last call. + /// + /// + [Newtonsoft.Json.JsonIgnore] + public bool IsChanged => ChangeInfo.IsChanged; + /// + /// Gets a boolean indicating if Change Tracking is enabled. + /// + /// + [Newtonsoft.Json.JsonIgnore] + public bool ChangeTrackingEnabled + { + get; + private set; + } + + /// + /// Gets an object containing all changes made since object construction or since last call. + /// + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo ChangeInfo => GetChanges(); + /// + /// Gets a boolean indicating if service is backup. + /// Used by UI. + /// + public bool UI_IsBackupService + { + get => BackupType != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.BackupType.None; + } + + /// + /// Gets a boolean indicating if service has commentary audio. + /// Used by UI. + /// + public bool UI_HasCommentaryAudio + { + get => false; + } // TODO implement when audio commentary is supported. + + /// + /// If an issue has been reported manually via the UpdateService script and when the order is finished. + /// The service will have the status Completed With Errors at the end. + /// + public bool HasAnIssueBeenreportedManually + { + get; + set; + } + + /// + /// Indicates whether the Service should stop immediately. + /// + public bool StopNow + { + get; + set; + } + + = false; + /// + /// Indicates if the service was automatically generated. + /// This is determined by checking the Virtual Platform of the Service Definition. + /// + public bool IsAutogenerated + { + get + { + if (Definition == null) + return false; + if (Definition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Routing) + return true; + if (Definition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.AudioProcessing) + return true; + if (Definition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.GraphicsProcessing) + return true; + if (Definition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.FileProcessing) + return true; + if (Definition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.VideoProcessing) + return true; + return false; + } + } + + /// + /// Gets the types of changes that this service underwent since construction or since last call. + /// + /// A flags enum containing the types of changes that this service underwent. + /// + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo GetChanges(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + progressReporter?.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GetChanges), Name); + var changeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo(); + bool startIsChanged = Start != initialStart; + //bool startWithPreRollIsChanged = StartWithPreRoll != initialStartWithPreRoll; + //if (startIsChanged || startWithPreRollIsChanged) changeInfo.TimingChangeInfo.MarkStartTimingChanged(); + if (startIsChanged) + changeInfo.TimingChangeInfo.MarkStartTimingChanged(); + bool endIsChanged = End != initialEnd; + //bool endWithPostRollIsChanged = EndWithPostRoll != initialEndWithPostRoll; + //if (endIsChanged || endWithPostRollIsChanged) changeInfo.TimingChangeInfo.MarkEndTimingChanged(); + if (endIsChanged) + changeInfo.TimingChangeInfo.MarkEndTimingChanged(); + bool timingHasChanged = startIsChanged || endIsChanged; + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GetChanges), $"Timing has{(timingHasChanged ? string.Empty : " not")} changed from {TimingInfoToString(initialStart, initialEnd)}{(timingHasChanged ? $" to {TimingInfoToString(this)}" : string.Empty)}", Name); + if (RecordingConfiguration?.ChangeInfo != null) + changeInfo.CombineWith(RecordingConfiguration.ChangeInfo); + bool integrationIsMasterChanged = IntegrationIsMaster != initialIntegrationIsMaster; + bool contactInfoIsChanged = ContactInformationName != initialContactInfoName; + bool contactInfoPhoneIsChanged = ContactInformationTelephoneNumber != initialContactInfoPhone; + bool liveUDeviceNameIsChanged = LiveUDeviceName != initialLiveUDeviceName; + bool audioReturnInfoIsChanged = AudioReturnInfo != initialAudioReturnInfo; + bool vidigoStreamSourceLinkIsChanged = VidigoStreamSourceLink != initialVidigoStreamSourceLink; + if (integrationIsMasterChanged || contactInfoIsChanged || contactInfoPhoneIsChanged || liveUDeviceNameIsChanged || vidigoStreamSourceLinkIsChanged) + changeInfo.MarkCustomPropertiesChanged(); + bool commentsChanged = Comments != initialComments; + if (commentsChanged) + changeInfo.MarkCustomPropertiesChanged(); + bool securityViewIdsAdded = initialSecurityViewIds == null && SecurityViewIds != null; + bool securityViewIdsRemoved = initialSecurityViewIds != null && SecurityViewIds == null; + bool securityViewIdsValuesChanged = initialSecurityViewIds != null && SecurityViewIds != null && !System.Linq.Enumerable.SequenceEqual(System.Linq.Enumerable.OrderBy(initialSecurityViewIds, x => x), System.Linq.Enumerable.OrderBy(SecurityViewIds, x => x)); + bool securityViewIdsChanged = securityViewIdsAdded || securityViewIdsRemoved || securityViewIdsValuesChanged; + if (securityViewIdsChanged) + { + changeInfo.SecurityViewIdsChanged = true; + } + + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GetChanges), $"Security View IDs have{(securityViewIdsChanged ? string.Empty : " not")} changed from {(initialSecurityViewIds == null ? "empty" : string.Join(";", initialSecurityViewIds))}{(securityViewIdsChanged ? $" to {string.Join(";", SecurityViewIds)}" : string.Empty)}", Name); + // TODO add eurovision booking details change check + if (Functions == null) + return changeInfo; + if (initialFunctions != null && Functions.Count != initialFunctions.Count) + changeInfo.MarkServiceDefinitionChanged(); + foreach (var function in Functions) + { + if (initialFunctions != null) + { + var initialFunction = System.Linq.Enumerable.FirstOrDefault(initialFunctions, f => f.Id == function.Id); + if (initialFunction == null) + { + changeInfo.MarkServiceDefinitionChanged(); + continue; + } + } + + var functionChangeInfo = function.ChangeInfo; + changeInfo.CombineWith(functionChangeInfo); + bool functionResourceHasChanged = functionChangeInfo.ResourceChangeInfo.ResourcesChanged; + if (!functionResourceHasChanged) + continue; + int functionPositionInServiceDefinition = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.GraphExtensions.GetFunctionPosition(Definition.Diagram, function); + bool functionIsAtBeginningOfServiceDefinition = functionPositionInServiceDefinition == 0; + bool functionIsAtEndOfServiceDefinition = functionPositionInServiceDefinition == Definition.Diagram.Nodes.Count - 1; + if (functionIsAtBeginningOfServiceDefinition) + changeInfo.ResourceChangeInfo.MarkResourceAtBeginningOfServiceDefinitionAddedOrSwapped(); + if (functionIsAtEndOfServiceDefinition) + changeInfo.ResourceChangeInfo.MarkResourceAtEndOfServiceDefinitionAddedOrSwapped(); + } + + progressReporter?.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GetChanges), Name); + return changeInfo; + } + + /// + /// Resets Change Tracking. + /// + /// + public void AcceptChanges() + { + initialStart = Start; + initialEnd = End; + //initialStartWithPreRoll = StartWithPreRoll; + //initialEndWithPostRoll = EndWithPostRoll; + initialRecordingConfiguration = RecordingConfiguration; + RecordingConfiguration?.AcceptChanges(); + initialIntegrationIsMaster = IntegrationIsMaster; + initialContactInfoName = ContactInformationName; + initialContactInfoPhone = ContactInformationTelephoneNumber; + initialVidigoStreamSourceLink = VidigoStreamSourceLink; + initialLiveUDeviceName = LiveUDeviceName; + initialAudioReturnInfo = AudioReturnInfo; + initialSecurityViewIds = new System.Collections.Generic.HashSet(SecurityViewIds); + initialComments = Comments; + foreach (var function in Functions) + function.AcceptChanges(); + initialFunctions = Functions; + } + + public override bool Equals(object obj) + { + if (!(obj is Service other)) + return false; + return Id.Equals(other.Id); + // TODO saved services have no ID and their names can change when editing/merging an Order, so this Equals method does not work in that case + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } + + /// + /// Get the service for a give reservation instance. + /// + /// + /// The reservation instance. + /// The service object. + public static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service FromReservationInstance(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservationInstance) + { + if (helpers == null) + throw new System.ArgumentNullException(nameof(helpers)); + if (reservationInstance == null) + throw new System.ArgumentNullException(nameof(reservationInstance)); + helpers.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(FromReservationInstance), out var stopwatch, reservationInstance.Name); + var booking = Skyline.DataMiner.Library.Solutions.SRM.ReservationInstanceExtensions.GetBookingData(reservationInstance); + var service = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service(booking.Description) + {Children = new System.Collections.Generic.List(), Functions = new System.Collections.Generic.List(), UserTasks = new System.Collections.Generic.List(), Id = reservationInstance.ID, PreRoll = Skyline.DataMiner.Library.Solutions.SRM.ReservationInstanceExtensions.GetPreRoll(reservationInstance), PostRoll = Skyline.DataMiner.Library.Solutions.SRM.ReservationInstanceExtensions.GetPostRoll(reservationInstance)}; + var convertedStartTime = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.Truncate(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.FromReservation(reservationInstance.Start), System.TimeSpan.FromMinutes(1)); + var convertedEndTime = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.Truncate(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.DateTimeExtensions.FromReservation(reservationInstance.End), System.TimeSpan.FromMinutes(1)); + service.Start = convertedStartTime.Add(service.PreRoll); + service.End = convertedEndTime.Subtract(service.PostRoll); + service.IsBooked = true; + service.BackupType = GetServiceLevel(reservationInstance); + service.LinkedEventIds = GetLinkedEventIds(reservationInstance) ?? new System.Collections.Generic.HashSet(); + service.IntegrationType = GetIntegrationType(reservationInstance); + service.IntegrationIsMaster = GetBooleanProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.IntegrationIsMasterPropertyName); + service.IsEventLevelReception = GetBooleanProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.IsEventLevelReceptionPropertyName); + service.IsGlobalEventLevelReception = GetBooleanProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.IsGlobalEventLevelReceptionPropertyName); + if (service.IsEventLevelReception || service.IsGlobalEventLevelReception) + service.VerifyContributingResourceCreation(); + service.HasResourcesAssigned = System.Linq.Enumerable.Any(reservationInstance.ResourcesInReservationInstance); + service.OrderReferences = GetOrderReferences(reservationInstance); + service.SecurityViewIds = new System.Collections.Generic.HashSet(reservationInstance.SecurityViewIDs); + var serviceResourceReservationInstance = reservationInstance as Skyline.DataMiner.Net.ResourceManager.Objects.ServiceReservationInstance; + if (serviceResourceReservationInstance == null) + throw new System.ArgumentException($"Unable to cast to {nameof(Skyline.DataMiner.Net.ResourceManager.Objects.ServiceReservationInstance)}", nameof(reservationInstance)); + var serviceDefinition = helpers.ServiceDefinitionManager.GetServiceDefinition(serviceResourceReservationInstance.ServiceDefinitionID); + service.Definition = serviceDefinition; + service.Functions = helpers.ServiceManager.GetFunctions(serviceResourceReservationInstance, serviceDefinition); + service.LinkedServiceId = GetLinkedServiceId(serviceResourceReservationInstance); + service.AudioChannelConfiguration = GetAudioChannelConfiguration(service.Functions); + service.EurovisionWorkOrderId = GetStringProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.EurovisionIdPropertyName); + service.EurovisionTransmissionNumber = GetStringProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.EurovisionTransmissionNumberPropertyName); + service.EurovisionBookingDetails = GetEurovisionBookingDetails(reservationInstance); + if (!string.IsNullOrEmpty(service.EurovisionWorkOrderId) || service.EurovisionBookingDetails != null) + service.IsEurovisionService = true; + service.ContactInformationName = GetStringProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.ContactInformationNamePropertyName); + service.ContactInformationTelephoneNumber = GetStringProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.ContactInformationTelephoneNumberPropertyName); + service.VidigoStreamSourceLink = GetStringProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.VidigoStreamSourceLinkPropertyName); + service.HasAnIssueBeenreportedManually = GetBooleanProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.ReportedIssuePropertyName); + if (serviceDefinition.VirtualPlatformServiceName == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformName.LiveU) + { + service.LiveUDeviceName = GetStringProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.LiveUDeviceNamePropertyName); + } + + service.AudioReturnInfo = GetStringProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.AudioReturnInfoPropertyName); + service.RecordingConfiguration = GetRecordingConfiguration(reservationInstance); + service.NameOfServiceToTransmit = GetStringProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.NameOfServiceToTransmitPropertyName); + service.UserTasks = System.Linq.Enumerable.ToList(helpers.UserTaskManager.GetUserTasks(service)); + service.isCancelled = GetStatus(serviceResourceReservationInstance) == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.Cancelled; + service.Comments = GetStringProperty(reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.CommentsPropertyName); + service.ReservationInstance = serviceResourceReservationInstance; + helpers.ProgressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(FromReservationInstance), $"Summary of properties on service object taken from reservation instance: ID={service.Id} IsELR={service.IsEventLevelReception} IsGlobalELR={service.IsGlobalEventLevelReception}, SecurityViewIds={string.Join(",", service.SecurityViewIds)}, RequiresRouting={service.RequiresRouting}, RoutingConfigurationUpdateRequired={service.RoutingConfigurationUpdateRequired}, HasIssueBeenReportedManually={service.HasAnIssueBeenreportedManually}, NameOfServiceToTransmitOrRecord={service.NameOfServiceToTransmitOrRecord}, IntegrationIsMaster={service.IntegrationIsMaster}, Timing={TimingInfoToString(service)}", service.Name); + helpers.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(FromReservationInstance), reservationInstance.Name, stopwatch); + return service; + } + + private static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.BackupType GetServiceLevel(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservationInstance) + { + if (!reservationInstance.Properties.Dictionary.TryGetValue(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.ServiceLevelPropertyName, out var serviceLevel)) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ServiceReservationPropertyNotFoundException(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.ServiceLevelPropertyName, reservationInstance.Name); + } + + return (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.BackupType)System.Convert.ToInt32(serviceLevel); + } + + private static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType GetIntegrationType(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservationInstance) + { + object integrationType; + if (!reservationInstance.Properties.Dictionary.TryGetValue(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.IntegrationTypePropertyName, out integrationType)) + { + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.None; + } + + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumValueFromDescription(System.Convert.ToString(integrationType)); + } + + public static bool GetBooleanProperty(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservation, string propertyName) + { + string propertyValue = GetStringProperty(reservation, propertyName); + return !string.IsNullOrWhiteSpace(propertyValue) && System.Convert.ToBoolean(propertyValue); + } + + public static string GetStringProperty(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservation, string propertyName) + { + if (reservation == null) + throw new System.ArgumentNullException(nameof(reservation)); + if (string.IsNullOrWhiteSpace(propertyName)) + throw new System.ArgumentNullException(nameof(propertyName)); + return reservation.Properties.Dictionary.TryGetValue(propertyName, out object propertyValue) ? System.Convert.ToString(propertyValue) : null; + } + + private static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.RecordingConfiguration GetRecordingConfiguration(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservationInstance) + { + object recordingConfigurationPropertyValue; + if (!reservationInstance.Properties.Dictionary.TryGetValue(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.RecordingConfigurationPropertyName, out recordingConfigurationPropertyValue)) + { + return null; + } + + try + { + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.RecordingConfiguration.Deserialize(System.Convert.ToString(recordingConfigurationPropertyValue)); + } + catch (System.Exception) + { + return null; + } + } + + private static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status GetStatus(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservationInstance) + { + object status; + if (!reservationInstance.Properties.Dictionary.TryGetValue(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.StatusPropertyName, out status)) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ServiceReservationPropertyNotFoundException(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.StatusPropertyName, reservationInstance.Name); + } + + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumValueFromDescription(System.Convert.ToString(status)); + } + + private static System.Guid GetLinkedServiceId(Skyline.DataMiner.Net.ResourceManager.Objects.ServiceReservationInstance reservationInstance) + { + var linkedServiceIdProperty = System.Linq.Enumerable.FirstOrDefault(reservationInstance.Properties, p => string.Equals(p.Key, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.LinkedServiceIdPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + if (linkedServiceIdProperty.Equals(default(System.Collections.Generic.KeyValuePair)) || linkedServiceIdProperty.Value == null) + return System.Guid.Empty; + System.Guid linkedServiceId; + if (!System.Guid.TryParse(System.Convert.ToString(linkedServiceIdProperty.Value), out linkedServiceId)) + return System.Guid.Empty; + return linkedServiceId; + } + + public static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.AudioChannelConfiguration GetAudioChannelConfiguration(System.Collections.Generic.IEnumerable functions) + { + System.Collections.Generic.HashSet audioChannelProfileParameters = new System.Collections.Generic.HashSet(); + foreach (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function function in functions) + { + foreach (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileParameter parameter in function.Parameters) + { + if (parameter == null) + continue; + if (System.Linq.Enumerable.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.AllAudioChannelConfigurationGuids, parameter.Id)) + { + audioChannelProfileParameters.Add(parameter); + } + } + } + + return new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.AudioChannelConfiguration(audioChannelProfileParameters); + } + + private static System.Collections.Generic.HashSet GetOrderReferences(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservation) + { + var orders = new System.Collections.Generic.HashSet(); + var orderIdsProperty = System.Linq.Enumerable.FirstOrDefault(reservation.Properties, p => string.Equals(p.Key, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.OrderReferencesPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + if (orderIdsProperty.Equals(default(System.Collections.Generic.KeyValuePair)) || System.Convert.ToString(orderIdsProperty.Value) == string.Empty) + { + return orders; + } + + try + { + var orderIds = System.Linq.Enumerable.Select(System.Convert.ToString(orderIdsProperty.Value).Split(';'), id => System.Guid.Parse(id)); + foreach (var orderId in orderIds) + { + if (orderId == System.Guid.Empty) + continue; + orders.Add(orderId); + } + } + catch (System.Exception) + { + return orders; + } + + return orders; + } + + internal static System.Collections.Generic.HashSet GetLinkedEventIds(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservation) + { + var eventIds = new System.Collections.Generic.HashSet(); + var linkedEventIdsProperty = System.Linq.Enumerable.FirstOrDefault(reservation.Properties, p => string.Equals(p.Key, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.LinkedEventIdPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + if (linkedEventIdsProperty.Equals(default(System.Collections.Generic.KeyValuePair)) || System.Convert.ToString(linkedEventIdsProperty.Value) == string.Empty) + { + return eventIds; + } + + try + { + var linkedEventIds = System.Convert.ToString(linkedEventIdsProperty.Value).Split(';'); + foreach (var eventId in linkedEventIds) + { + if (eventId == string.Empty) + continue; + eventIds.Add(eventId); + } + } + catch (System.Exception) + { + return eventIds; + } + + return eventIds; + } + + private static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.EurovisionBookingDetails GetEurovisionBookingDetails(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance reservationInstance) + { + object eurovisionBookingDetailsPropertyValue; + if (!reservationInstance.Properties.Dictionary.TryGetValue(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ServicePropertyNames.EurovisionBookingDetailsPropertyName, out eurovisionBookingDetailsPropertyValue)) + { + return null; + } + + var eurovisionBookingDetails = System.Convert.ToString(eurovisionBookingDetailsPropertyValue); + if (string.IsNullOrEmpty(eurovisionBookingDetails)) + { + return null; + } + + try + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(eurovisionBookingDetails); + } + catch (System.Exception) + { + return null; + } + } + + /// + /// Checks if resources are assigned to the Functions that should have resources assigned. + /// + /// + /// Due to the way the standard SRM solution works, all Functions in the Service Definitions have been marked optional. + /// Therefore this method is used to see if all Functions that require a resource have a resource assigned. + /// + /// A boolean indicating if all resources are correctly assigned. + private bool VerifyFunctionResources(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + if (Definition == null) + return false; + if (Definition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.AudioProcessing) + { + return VerifyAudioProcessingFunctionResources(); + } + + foreach (var function in Functions) + { + // matrix functions in a non-routing service always need to have a resource assigned + if (function != null && function.Name.Contains("Matrix") && Definition.VirtualPlatform != Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Routing) + { + if (function.Name.Contains("Input") && !VerifyMatrixFunctionResources(function)) + { + return false; + } + else + { + // output will automatically be checked when verifying the input + } + } + else if (function != null && function.Resource == null) + { + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(VerifyFunctionResources), $"Function {function.Definition.Label} requires a resource but has no resource assigned", Name); + return false; + } + } + + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(VerifyFunctionResources), $"All necessary functions have resources assigned", Name); + return true; + } + + /// + /// Verify that the matrix function resources are correctly assigned. + /// + /// The matrix input function. + /// Returns true if the matrix input and connected output are correctly assigned. + private bool VerifyMatrixFunctionResources(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function matrixInputFunction, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + // if the function is a matrix and has no resource assigned, check if the resources before and after the matrix are the same device + // if they aren't the same device, a matrix is required as routing between those different devices + // the lack of a resource for the Matrix function then leads to a ResourceOverbooked state on the Service + // if they are the same device, no routing is required between those functions + var edgeToMatrixInput = System.Linq.Enumerable.FirstOrDefault(Definition.Diagram.Edges, e => e.ToNodeID == matrixInputFunction.NodeId); + if (edgeToMatrixInput == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.EdgeNotFoundException($"Edge to node id {matrixInputFunction.NodeId} not found in service definition {Definition.Id}"); + } + + var functionToMatrixInput = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.NodeId == edgeToMatrixInput.FromNodeID); + if (functionToMatrixInput == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.FunctionNotFoundException($"Function not found with node id {edgeToMatrixInput.FromNodeID}"); + } + + var edgeToMatrixOutput = System.Linq.Enumerable.FirstOrDefault(Definition.Diagram.Edges, e => e.FromNodeID == matrixInputFunction.NodeId); + if (edgeToMatrixOutput == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.EdgeNotFoundException($"Edge from node id {matrixInputFunction.NodeId} not found in service definition {Definition.Id}"); + } + + var matrixOutputFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.NodeId == edgeToMatrixOutput.ToNodeID); + if (matrixOutputFunction == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.FunctionNotFoundException($"Function not found with node id {edgeToMatrixInput.ToNodeID}"); + } + + var edgeFromMatrixOutput = System.Linq.Enumerable.FirstOrDefault(Definition.Diagram.Edges, e => e.FromNodeID == edgeToMatrixOutput.ToNodeID); + if (edgeFromMatrixOutput == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.EdgeNotFoundException($"Edge from node id {edgeToMatrixOutput.ToNodeID} not found in service definition {Definition.Id}"); + } + + var functionFromMatrixOutput = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.NodeId == edgeFromMatrixOutput.ToNodeID); + if (functionFromMatrixOutput == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.FunctionNotFoundException($"Function not found with node id {edgeFromMatrixOutput.ToNodeID}"); + } + + if (functionToMatrixInput.Resource != null && functionFromMatrixOutput.Resource != null && functionToMatrixInput.Resource.MainDVEDmaID == functionFromMatrixOutput.Resource.MainDVEDmaID && functionToMatrixInput.Resource.MainDVEElementID == functionFromMatrixOutput.Resource.MainDVEElementID) + { + // in case the resources connected to the input and the output matrix are from the same device + // then no matrix resources are needed + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(VerifyMatrixFunctionResources), $"Resource {functionToMatrixInput.Resource.Name} from function {functionToMatrixInput.Definition.Label} and resource {functionFromMatrixOutput.Resource.Name} from function {functionFromMatrixOutput} are the same device, matrix functions are OK", Name); + return true; + } + + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(VerifyMatrixFunctionResources), $"Function {matrixInputFunction.Definition.Label} has resource {matrixInputFunction.Resource?.Name}, function {matrixOutputFunction.Definition.Label} has resource {matrixOutputFunction.Resource?.Name}", Name); + // if we reach this code then both the input and output matrix function should have a resource assigned + return matrixInputFunction.Resource != null && matrixOutputFunction.Resource != null; + } + + /// + /// Checks if all audio processing functions have a correct resource assigned. + /// + /// Returns true in case all resources are ok. + private bool VerifyAudioProcessingFunctionResources() + { + var audioDeembeddingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.Name == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.AudioDeembeddingFunctionDefinitionName); + var audioDeembeddingRequiredParameter = System.Linq.Enumerable.FirstOrDefault(audioDeembeddingFunction.Parameters, p => p.Name.Contains("Required")); + var audioDeembeddingRequired = System.Convert.ToString(audioDeembeddingRequiredParameter.Value) != "Yes"; + var audioDolbyDecodingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.Name == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.AudioDolbyDecodingFunctionDefinitionName); + var audioDolbyDecodingRequiredParameter = System.Linq.Enumerable.FirstOrDefault(audioDolbyDecodingFunction.Parameters, p => p.Name.Contains("Required")); + var audioDolbyDecodingRequired = System.Convert.ToString(audioDolbyDecodingRequiredParameter.Value) != "Yes"; + var audioShufflingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.Name == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.AudioShufflingFunctionDefinitionName); + var audioShufflingRequiredParameter = System.Linq.Enumerable.FirstOrDefault(audioShufflingFunction.Parameters, p => p.Name.Contains("Required")); + var audioShufflingRequired = System.Convert.ToString(audioShufflingRequiredParameter.Value) != "Yes"; + var audioEmbeddingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.Name == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.AudioEmbeddingFunctionDefinitionName); + var audioEmbeddingRequiredParameter = System.Linq.Enumerable.FirstOrDefault(audioEmbeddingFunction.Parameters, p => p.Name.Contains("Required")); + var audioEmbeddingRequired = System.Convert.ToString(audioEmbeddingRequiredParameter.Value) != "Yes"; + var matrixSdiInputAudioDeembeddingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.NodeId == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.MatrixSdiInputAudioDeembeddingFunctionNodeId); + var audioDeembeddingCheckMatrixInputResource = audioDeembeddingRequired && (audioDolbyDecodingRequired || audioShufflingRequired || audioEmbeddingRequired); + var audioDeembeddingCheckMatrixOutputResource = false; + if (!VerifyAudioProcessingFunctionResource(audioDeembeddingFunction, matrixSdiInputAudioDeembeddingFunction, null, audioDeembeddingCheckMatrixInputResource, audioDeembeddingCheckMatrixOutputResource)) + return false; + var matrixSdiInputAudioDolbyDecodingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.NodeId == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.MatrixSdiInputAudioDolbyDecodingFunctionNodeId); + var matrixSdiOutputAudioDolbyDecodingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.NodeId == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.MatrixSdiOutputAudioDolbyDecodingFunctionNodeId); + var audioDolbyDecodingCheckMatrixInputResource = audioDolbyDecodingRequired && (audioShufflingRequired || audioEmbeddingRequired); + var audioDolbyDecodingCheckMatrixOutputResource = audioDolbyDecodingRequired && audioDeembeddingRequired; + if (!VerifyAudioProcessingFunctionResource(audioDolbyDecodingFunction, matrixSdiInputAudioDolbyDecodingFunction, matrixSdiOutputAudioDolbyDecodingFunction, audioDolbyDecodingCheckMatrixInputResource, audioDolbyDecodingCheckMatrixOutputResource)) + return false; + var matrixSdiInputAudioShufflingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.NodeId == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.MatrixSdiInputAudioShufflingFunctionNodeId); + var matrixSdiOutputAudioShufflingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.NodeId == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.MatrixSdiOutputAudioShufflingFunctionNodeId); + var audioShufflingCheckMatrixInputResource = audioShufflingRequired && audioEmbeddingRequired; + var audioShufflingCheckMatrixOutputResource = audioShufflingRequired && (audioDeembeddingRequired || audioDolbyDecodingRequired); + if (!VerifyAudioProcessingFunctionResource(audioShufflingFunction, matrixSdiInputAudioShufflingFunction, matrixSdiOutputAudioShufflingFunction, audioShufflingCheckMatrixInputResource, audioShufflingCheckMatrixOutputResource)) + return false; + var matrixSdiOutputAudioEmbeddingFunction = System.Linq.Enumerable.FirstOrDefault(Functions, f => f.NodeId == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService.MatrixSdiOutputAudioEmbeddingFunctionNodeId); + var audioEmbeddingCheckMatrixInputResource = false; + var audioEmbeddingCheckMatrixOutputResource = audioEmbeddingRequired && (audioDeembeddingRequired || audioDolbyDecodingRequired || audioShufflingRequired); + if (!VerifyAudioProcessingFunctionResource(audioEmbeddingFunction, null, matrixSdiOutputAudioEmbeddingFunction, audioEmbeddingCheckMatrixInputResource, audioEmbeddingCheckMatrixOutputResource)) + return false; + return true; + } + + private bool VerifyAudioProcessingFunctionResource(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function audioProcessingFunction, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function matrixInputFunction, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function matrixOutputFunction, bool checkInput = true, bool checkOutput = true) + { + if (audioProcessingFunction == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.FunctionNotFoundException("Audio processing function could not be found"); + } + + var requiredParameter = System.Linq.Enumerable.FirstOrDefault(audioProcessingFunction.Parameters, p => p.Name.Contains("Required")); + if (requiredParameter == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.FunctionParameterNotFoundException("Audio processing Required"); + } + + // if this function is not required then we don't need to check the actual resource(s) + if (System.Convert.ToString(requiredParameter.Value) != "Yes") + return true; + if (audioProcessingFunction.Resource == null) + return false; + if (checkInput) + { + if (matrixInputFunction == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.FunctionNotFoundException("Matrix SDI Input audio processing function could not be found"); + } + + if (matrixInputFunction.Resource == null) + return false; + } + + if (checkOutput) + { + if (matrixOutputFunction == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.FunctionNotFoundException("Matrix SDI Output audio processing function could not be found"); + } + + if (matrixOutputFunction.Resource == null) + return false; + } + + return true; + } + + private void VerifyContributingResourceCreation() + { + // check if the contributing resource was correctly created + // the resource should have the same id as the service + var contributingFunctionResource = Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ResourceManager.GetResource(Id); + if (contributingFunctionResource == null) + { + // Catching faulty event level reception resources + ContributingResource = null; + ResourcePool = null; + return; + } + + // the contributing resource will only be added to 1 resource pool + var resourcePoolId = System.Linq.Enumerable.FirstOrDefault(contributingFunctionResource.PoolGUIDs); + var resourcePool = Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ResourceManager.GetResourcePool(resourcePoolId) ?? throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ResourcePoolNotFoundException($"Resource pool not found {resourcePoolId}"); + ContributingResource = contributingFunctionResource; + ResourcePool = resourcePool; + } + + public override string ToString() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.AppendLine($"Short Description: {GetShortDescription()}"); + sb.AppendLine($"\tStatus: {Status}"); + sb.AppendLine($"\tBackup Type: {BackupType}"); + sb.AppendLine($"\tID: {Id}"); + sb.AppendLine($"\tNode ID: {NodeId}"); + sb.AppendLine($"\tStart: {Start}"); + sb.AppendLine($"\tEnd: {End}"); + sb.AppendLine($"\tStart With Pre Roll: {StartWithPreRoll}"); + sb.AppendLine($"\tEnd With Post Roll: {EndWithPostRoll}"); + sb.AppendLine($"\tIntegration Type: {IntegrationType}"); + sb.AppendLine($"\tEurovision ID: {EurovisionWorkOrderId}"); + sb.AppendLine($"\tEurovision Transmission Number: {EurovisionTransmissionNumber}"); + sb.AppendLine($"\tSD Virtual Platform: {Definition.VirtualPlatform}"); + sb.AppendLine($"\tSD ID: {Definition.Id}"); + sb.AppendLine($"\tSD Name: {Definition.Name}"); + sb.AppendLine($"\tIs Eurovision Service: {IsEurovisionService}"); + return sb.ToString(); + } + + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status GenerateStatus(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + var now = System.DateTime.Now; + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GenerateStatus), $"Evaluating status at: {now.ToString("dd/MM/yyyy HH:mm:ss")}", Name); + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GenerateStatus), $"Service timing: {TimingInfoToString(this)}", Name); + if (isCancelled) + { + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GenerateStatus), "Service is cancelled", Name); + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.Cancelled; + } + + if (IsPreliminary || !IsBooked) + { + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GenerateStatus), "Service is preliminary", Name); + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.Preliminary; + } + + // check if resources are overbooked + bool isResourceOverbooked = !VerifyFunctionResources(); + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GenerateStatus), $"{(isResourceOverbooked ? "Not all" : "All")} expected resources are assigned", Name); + // check user tasks + var hasIncompleteConfigurationUserTasks = false; + var hasIncompleteFileProcessingUserTasks = false; + if (UserTasks != null) + { + foreach (var userTask in UserTasks) + { + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GenerateStatus), $"User Task {userTask.Name} is {userTask.Status}", Name); + if (userTask.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Complete) + continue; + if (userTask.Description.IndexOf("File Processing", System.StringComparison.OrdinalIgnoreCase) != -1) + hasIncompleteFileProcessingUserTasks = true; + else + hasIncompleteConfigurationUserTasks = true; + } + } + + if (hasIncompleteConfigurationUserTasks) + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GenerateStatus), "Service has incomplete configuration user tasks", Name); + if (hasIncompleteFileProcessingUserTasks) + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service), nameof(GenerateStatus), "Service has incomplete file processing user tasks", Name); + // return correct status based on timing, resources and user tasks + if (EndWithPostRoll <= now) + { + if (HasAnIssueBeenreportedManually || isResourceOverbooked || hasIncompleteConfigurationUserTasks) + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ServiceCompletedWithErrors; + if (hasIncompleteFileProcessingUserTasks) + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.FileProcessing; + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ServiceCompleted; + } + + if (isResourceOverbooked) + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ResourceOverbooked; + if (hasIncompleteConfigurationUserTasks) + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ConfigurationPending; + if (StartWithPreRoll <= now && now < Start) + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ServiceCueing; + if (Start <= now && now < End) + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ServiceRunning; + if (End <= now && now < EndWithPostRoll) + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.PostRoll; + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Status.ConfigurationCompleted; + } + + /// + /// Gets the short description for this service. + /// + /// The order that contains this service. Can be null in case of non-recording services. Cannot be null in case of recording services. + /// Thrown in case this service is a recording and is null. + public string GetShortDescription(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order = null, Skyline.DataMiner.Automation.IEngine engine = null) + { + switch (Definition.VirtualPlatform) + { + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionSatellite: + return GetSatelliteReceptionDescription(); + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionSatellite: + return GetSatelliteTransmissionDescription(); + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionFiber: + return GetFiberTranmissionDescription(); + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionLiveU: + return GetLiveUReceptionDescription(); + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionFiber: + return GetFiberReceptionDescription(); + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording: + if (order == null) + throw new System.ArgumentNullException(nameof(order), "Order cannot be null for a recording service."); + return GetRecordingDescription(order); + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Routing: + return GetRoutingDescription(); + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.AudioProcessing: + return GetAudioProcessingDescription(); + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionFixedService: + return GetFixedServiceDescription(); + default: + return GetStandardShortDescription(); + } + } + + private string GetStandardShortDescription() + { + var result = new System.Text.StringBuilder(); + bool isServiceDestination = Definition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Destination; + if (!isServiceDestination) + { + string virtualPlatformName = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceName); + result.Append(virtualPlatformName); + } + + if (Functions.Count == 1) + { + var function = System.Linq.Enumerable.Single(Functions); + var resource = function.Resource; + string resourceName = resource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(resource, function.Id) : None; + string resourceDescription = !isServiceDestination ? " - " + resourceName : resourceName; + result.Append(resourceDescription); + } + + return result.ToString(); + } + + private string GetFiberReceptionDescription() + { + var description = new System.Text.StringBuilder(); + bool isFullCapacity = Definition.Description.Contains("Full Capacity"); + description.Append(isFullCapacity ? GetFiberReceptionFullCapacityDescription() : GetFiberReceptionLimitedCapacityDescription()); + return description.ToString(); + } + + private string GetFiberReceptionFullCapacityDescription() + { + var description = new System.Text.StringBuilder(); + string virtualPlatformName = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceName); + description.Append($"{virtualPlatformName}"); + var function = System.Linq.Enumerable.Single(Functions); + string fiberResourceName = function.Resource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(function.Resource, function.Id) : None; + if (!string.IsNullOrEmpty(fiberResourceName)) + { + description.Append($" - {fiberResourceName}"); + } + + string nameValue = System.Linq.Enumerable.Single(System.Linq.Enumerable.SelectMany(Functions, f => f.Parameters), p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.FeedName).StringValue; + if (!string.IsNullOrEmpty(nameValue)) + { + description.Append($" - {nameValue}"); + } + + return description.ToString(); + } + + private string GetFiberReceptionLimitedCapacityDescription() + { + var description = new System.Text.StringBuilder(); + string virtualPlatformName = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceName); + description.Append($"{virtualPlatformName}"); + var fiberSourceFunction = System.Linq.Enumerable.SingleOrDefault(Functions, f => f != null && f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.FiberSource); + string fiberResourceName = fiberSourceFunction.Resource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(fiberSourceFunction.Resource, fiberSourceFunction.Id) : None; + if (!string.IsNullOrEmpty(fiberResourceName)) + { + description.Append($" - {fiberResourceName} --> "); + } + + var function = System.Linq.Enumerable.Single(Functions, f => f != null && f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.FiberDecoding); + fiberResourceName = function.Resource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(function.Resource, function.Id) : None; + if (!string.IsNullOrEmpty(fiberResourceName)) + { + description.Append(fiberResourceName); + } + + string nameValue = System.Linq.Enumerable.Single(System.Linq.Enumerable.SelectMany(Functions, f => f.Parameters), p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.FeedName).StringValue; + if (!string.IsNullOrEmpty(nameValue)) + { + description.Append($" - {nameValue}"); + } + + return description.ToString(); + } + + private string GetFiberTranmissionDescription() + { + var description = new System.Text.StringBuilder(); + bool isLimitedCapacity = Definition.Description.Contains("Limited Capacity"); + if (isLimitedCapacity) + { + string virtualPlatformName = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceName); + string virtualPlatformType = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceType); + description.Append($"{virtualPlatformName} {virtualPlatformType}"); + var genericEncodingfunction = System.Linq.Enumerable.SingleOrDefault(Functions, f => f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.GenericEncoding); + string fiberResourceName = genericEncodingfunction?.Resource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(genericEncodingfunction.Resource, genericEncodingfunction.Id) : None; + if (!string.IsNullOrEmpty(fiberResourceName)) + { + description.Append($" - {fiberResourceName} --> "); + } + + var fiberSourceFunction = System.Linq.Enumerable.SingleOrDefault(Functions, f => f != null && f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.FiberDestination); + fiberResourceName = fiberSourceFunction?.Resource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(fiberSourceFunction.Resource, fiberSourceFunction.Id) : None; + if (!string.IsNullOrEmpty(fiberResourceName)) + { + description.Append(fiberResourceName); + } + + string nameValue = System.Linq.Enumerable.SingleOrDefault(System.Linq.Enumerable.SelectMany(Functions, f => f.Parameters), p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.FeedName)?.StringValue; + if (!string.IsNullOrEmpty(nameValue)) + { + description.Append($" - {nameValue}"); + } + + return description.ToString(); + } + else + { + string standardDescription = GetStandardShortDescription(); + description.Append(standardDescription); + string feedNameValue = System.Linq.Enumerable.SingleOrDefault(System.Linq.Enumerable.SelectMany(Functions, f => f.Parameters), p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.FeedName)?.StringValue; + if (!string.IsNullOrEmpty(feedNameValue)) + { + description.Append($" - {feedNameValue}"); + } + + return description.ToString(); + } + } + + private string GetSatelliteReceptionDescription() + { + var result = new System.Text.StringBuilder(); + string virtualPlatformName = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceName); + result.Append($"{virtualPlatformName}"); + var allProfileParams = System.Linq.Enumerable.ToList(System.Linq.Enumerable.SelectMany(Functions, f => f.Parameters)); + var modulationStandardProfileParameter = System.Linq.Enumerable.FirstOrDefault(allProfileParams, p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.ModulationStandard) ?? throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ProfileParameterNotFoundException(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.ModulationStandard.ToString(), null, allProfileParams); + bool serviceUsesNs3OrNs4Modulation = modulationStandardProfileParameter.StringValue == "NS3" || modulationStandardProfileParameter.StringValue == "NS4"; + if (serviceUsesNs3OrNs4Modulation) + { + var demodulatingFunction = System.Linq.Enumerable.Single(Functions, f => f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.Demodulating); + var demodulatingResource = demodulatingFunction.Resource; + string demodulatingResourceName = demodulatingResource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(demodulatingResource, demodulatingFunction.Id) : string.Empty; + result.Append(" - " + demodulatingResourceName); + } + + var decodingFunction = System.Linq.Enumerable.Single(Functions, f => f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.Decoding); + var decodingResource = decodingFunction.Resource; + string decodingResourceName = decodingResource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(decodingResource, decodingFunction.Id) : string.Empty; + if (!string.IsNullOrEmpty(decodingResourceName)) + { + if (serviceUsesNs3OrNs4Modulation) + result.Append(" > "); + else + result.Append(" - "); + result.Append(decodingResourceName); + } + + string serviceSelection = System.Linq.Enumerable.FirstOrDefault(System.Linq.Enumerable.SelectMany(Functions, f => f.Parameters), p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.ServiceSelection)?.StringValue; + if (!string.IsNullOrWhiteSpace(serviceSelection)) + result.Append(" - " + serviceSelection); + return result.ToString(); + } + + private string GetSatelliteTransmissionDescription() + { + var result = new System.Text.StringBuilder(); + string virtualPlatformName = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceName); + string virtualPlatformType = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceType); + result.Append($"{virtualPlatformName} {virtualPlatformType}"); + result.Append(" - "); + var encodingFunction = System.Linq.Enumerable.Single(Functions, f => f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.GenericEncoding); + var encodingResource = encodingFunction.Resource; + string encodingResourceName = encodingResource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(encodingResource, encodingFunction.Id) : "None"; + result.Append(encodingResourceName); + result.Append(" --> "); + var modulatingFunction = System.Linq.Enumerable.Single(Functions, f => f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.GenericModulating); + var modulatingResource = modulatingFunction.Resource; + string modulatingResourceName = modulatingResource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(modulatingResource, modulatingFunction.Id) : "None"; + result.Append(modulatingResourceName); + return result.ToString(); + } + + private string GetLiveUReceptionDescription() + { + var result = new System.Text.StringBuilder(); + string virtualPlatformName = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceName); + result.Append($"{virtualPlatformName}"); + var function = System.Linq.Enumerable.Single(Functions); + var functionResource = function.Resource; + string resourceName = functionResource != null ? Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.ResourceExtensions.GetDisplayName(functionResource, function.Id) : string.Empty; + if (!string.IsNullOrEmpty(resourceName)) + result.Append(" - " + resourceName); + bool isPasila = Definition.Description.Contains("Pasila"); + bool isAudioReturn = System.Linq.Enumerable.Any(System.Linq.Enumerable.SelectMany(Functions, f => f.Parameters), p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.AudioReturnChannel && p.StringValue == "Required"); + if (isPasila && isAudioReturn) + result.Append(" - Audio Return"); + return result.ToString(); + } + + private string GetRoutingDescription() + { + string virtualPlatform = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatform); + var firstResource = System.Linq.Enumerable.First(Functions).Resource; + string firstResourceName = firstResource != null ? firstResource.Name : None; + string firstResourceDisplayName = System.Linq.Enumerable.Last(firstResourceName.Split('.')); + var lastResource = System.Linq.Enumerable.Last(Functions).Resource; + string lastResourceName = lastResource != null ? lastResource.Name : None; + string lastResourceDisplayName = System.Linq.Enumerable.Last(lastResourceName.Split('.')); + if (firstResource != null || lastResource != null) + { + string matrix = string.Empty; + bool isEduskuntaMatrix = firstResourceName.Contains("EDUSKUNTA") || lastResourceName.Contains("EDUSKUNTA"); + bool isHmxMatrix = firstResourceName.Contains("HMX") || lastResourceName.Contains("HMX"); + bool isNmxMatrix = firstResourceName.Contains("NMX") || lastResourceName.Contains("NMX"); + if (isEduskuntaMatrix) + matrix = "EDU"; + else if (isHmxMatrix) + matrix = "HMX"; + else if (isNmxMatrix) + matrix = "NEWS"; + return $"{matrix} {virtualPlatform} - {firstResourceDisplayName} --> {lastResourceDisplayName}"; + } + + if (!(string.IsNullOrEmpty(firstResourceName) && string.IsNullOrEmpty(lastResourceName))) + return $"{virtualPlatform} - {firstResourceDisplayName} --> {lastResourceDisplayName}"; + else + return virtualPlatform; + } + + private string GetRecordingDescription(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order) + { + var description = new System.Text.StringBuilder(); + switch (Definition.Description) + { + case "Messi Live": + description.Append("Live Rec."); + description.Append(GetLiveRecordingDescriptionResourcePart(order)); + break; + case "Messi Live Backup": + description.Append("Live Backup Rec."); + description.Append(GetLiveRecordingDescriptionResourcePart(order)); + break; + case "Messi News": + description.Append(GetNewsRecordingDescription()); + description.Append(GetNewsRecordingDetailsPart(order)); + break; + default: + return "Recording"; + } + + if (RecordingConfiguration != null) + { + if (IntegrationType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma) + { + if (!string.IsNullOrEmpty(RecordingConfiguration.PlasmaTvChannelName)) + description.Append(" - " + RecordingConfiguration.PlasmaTvChannelName); + if (!string.IsNullOrEmpty(RecordingConfiguration.PlasmaProgramName)) + description.Append(" - " + RecordingConfiguration.PlasmaProgramName); + } + else if (!string.IsNullOrEmpty(RecordingConfiguration.RecordingName)) + description.Append(" - " + RecordingConfiguration.RecordingName); + } + + return description.ToString(); + } + + private string GetLiveRecordingDescriptionResourcePart(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order) + { + var result = new System.Text.StringBuilder(); + var routingService = System.Linq.Enumerable.Single(order.AllServices, s => s.Children.Contains(this)); + var matrixOutputFunction = System.Linq.Enumerable.LastOrDefault(routingService.Functions); // Not all services have functions, for example the Dummy Services or Eurovision Dummy Services. + var matrixOutputResource = matrixOutputFunction?.Resource; + string matrixOutputResourceName = matrixOutputResource?.Name ?? None; + string matrixOutputResourceDisplayName = System.Linq.Enumerable.Last(matrixOutputResourceName.Split('.')); + result.Append(" - " + matrixOutputResourceDisplayName); + string functionResourceName = System.Linq.Enumerable.Single(Functions).Resource?.Name ?? None; + if (!string.IsNullOrEmpty(functionResourceName)) + result.Append(" --> " + functionResourceName); + return result.ToString(); + } + + private string GetNewsRecordingDescription() + { + var newsRecordingFunction = System.Linq.Enumerable.FirstOrDefault(Functions); + if (newsRecordingFunction == null) + return "News Rec."; + var feedTypeProfileParameter = System.Linq.Enumerable.FirstOrDefault(newsRecordingFunction.Parameters, p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids._FeedType); + if (feedTypeProfileParameter == null || string.IsNullOrEmpty(feedTypeProfileParameter.StringValue) || feedTypeProfileParameter.StringValue == "None") + return "News Rec."; + return $"News {feedTypeProfileParameter.StringValue} Rec."; + } + + private string GetNewsRecordingDetailsPart(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order) + { + var result = new System.Text.StringBuilder(); + var routingService = System.Linq.Enumerable.Single(order.AllServices, s => s != null && s.Children?.Contains(this) == true); + if (routingService.Functions != null && System.Linq.Enumerable.Any(routingService.Functions)) + { + var matrixOutputFunction = System.Linq.Enumerable.Single(routingService.Functions, f => f != null && routingService.Definition?.FunctionIsFirst(f) == true); + var matrixOutputResource = matrixOutputFunction.Resource; + string matrixOutputResourceName = matrixOutputResource != null ? matrixOutputResource.Name : None; + string matrixOutputResourceDisplayName = System.Linq.Enumerable.Last(matrixOutputResourceName.Split('.')); + if (!string.IsNullOrEmpty(matrixOutputResourceDisplayName)) + { + result.Append(matrixOutputResourceDisplayName.Contains("UMX") ? " - " + matrixOutputResourceDisplayName : string.Empty); + } + } + + string recordingFunctionResourceName = System.Linq.Enumerable.Single(Functions).Resource?.Name ?? None; + if (!string.IsNullOrEmpty(recordingFunctionResourceName)) + result.Append(" --> " + recordingFunctionResourceName); + return result.ToString(); + } + + private string GetAudioProcessingDescription() + { + string virtualPlatformName = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceName); + var nonRoutingResourceNames = System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(Functions, f => !System.Linq.Enumerable.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.AllMatrixGuids, f.Id) && f.Resource != null), f => f.Resource.Name); + var stringBuilder = new System.Text.StringBuilder(virtualPlatformName); + foreach (var resourceName in nonRoutingResourceNames) + stringBuilder.Append(" - " + resourceName); + return stringBuilder.ToString(); + } + + private string GetFixedServiceDescription() + { + var result = new System.Text.StringBuilder(); + string virtualPlatformName = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(Definition.VirtualPlatformServiceName); + result.Append(virtualPlatformName); + var function = System.Linq.Enumerable.FirstOrDefault(Functions); + if (function == null) + return result.ToString(); + var channelParameter = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p.Id.Equals(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.Channel)); + if (channelParameter != null && !string.IsNullOrEmpty(channelParameter.StringValue)) + result.Append(" - " + channelParameter.StringValue); + var linkedIrdProperty = function.Resource != null ? System.Linq.Enumerable.FirstOrDefault(function.Resource.Properties, p => p.Name.Equals("LinkedIRD", System.StringComparison.InvariantCultureIgnoreCase)) : null; + if (linkedIrdProperty != null && !string.IsNullOrEmpty(linkedIrdProperty.Value)) + result.Append(" - " + linkedIrdProperty.Value); + string serviceSelection = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.ServiceSelection)?.StringValue; + if (!string.IsNullOrWhiteSpace(serviceSelection)) + result.Append(" - " + serviceSelection); + return result.ToString(); + } + + public static string TimingInfoToString(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service) + { + return $"Start:{service.Start.ToString("dd/MM/yyyy HH:mm:ss")}, Start with preroll:{service.StartWithPreRoll.ToString("dd/MM/yyyy HH:mm:ss")}, End:{service.End.ToString("dd/MM/yyyy HH:mm:ss")}, End with postroll:{service.EndWithPostRoll.ToString("dd/MM/yyyy HH:mm:ss")}"; + } + + public static string TimingInfoToString(System.DateTime start, System.DateTime end) + { + return $"Start:{start.ToUniversalTime()}, End:{end.ToUniversalTime()}"; + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Skyline.DataMiner.Storage.Types.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLNetTypes.dll")] + public class ServiceManager : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.IServiceManager + { + public static readonly string SourceServiceSystemFunctionId = "c7e8648e-7522-4724-99a8-74e48a45f380"; + public static readonly string TransmissionServiceSystemFunctionId = "147f77f6-74d6-4802-8603-5042a6e0ad5d"; + private static readonly System.TimeSpan PlasmaServicePreRoll = System.TimeSpan.Zero; + private static readonly System.TimeSpan PlasmaServicePostRoll = System.TimeSpan.Zero; + private static readonly System.TimeSpan FeenixServicePreRoll = System.TimeSpan.FromMinutes(5); + private static readonly System.TimeSpan FeenixServicePostRoll = System.TimeSpan.FromMinutes(5); + private static readonly System.TimeSpan MessiLiveRecordingPreRoll = System.TimeSpan.FromMinutes(10); + private static readonly System.TimeSpan MessiNewsRecordingPreRoll = System.TimeSpan.Zero; + private static readonly System.TimeSpan MessiLiveRecordingPostRoll = System.TimeSpan.FromMinutes(20); + private static readonly System.TimeSpan MessiNewsRecordingPostRoll = System.TimeSpan.Zero; + private static readonly System.TimeSpan Preroll = System.TimeSpan.FromMinutes(5); + private static readonly System.TimeSpan PostRoll = System.TimeSpan.FromMinutes(5); + private static readonly System.Collections.Generic.Dictionary preRollDurations = new System.Collections.Generic.Dictionary{{Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionSatellite, new System.TimeSpan(hours: 0, minutes: 30, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionFiber, new System.TimeSpan(hours: 0, minutes: 30, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionMicrowave, new System.TimeSpan(hours: 0, minutes: 30, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionIp, new System.TimeSpan(hours: 0, minutes: 30, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionLiveU, new System.TimeSpan(hours: 0, minutes: 15, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionFixedLine, new System.TimeSpan(hours: 0, minutes: 15, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Routing, new System.TimeSpan(hours: 0, minutes: 15, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording, new System.TimeSpan(hours: 0, minutes: 30, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.VideoProcessing, new System.TimeSpan(hours: 0, minutes: 15, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.AudioProcessing, new System.TimeSpan(hours: 0, minutes: 30, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.GraphicsProcessing, new System.TimeSpan(hours: 0, minutes: 30, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionSatellite, new System.TimeSpan(hours: 0, minutes: 30, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionIp, new System.TimeSpan(hours: 0, minutes: 60, seconds: 0)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Destination, new System.TimeSpan(hours: 0, minutes: 15, seconds: 0)}}; + private static readonly System.Collections.Generic.Dictionary postRollDurations = new System.Collections.Generic.Dictionary{{Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionSatellite, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionFiber, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionMicrowave, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionIp, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionLiveU, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionFixedLine, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Routing, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.VideoProcessing, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.AudioProcessing, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.GraphicsProcessing, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionSatellite, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionIp, System.TimeSpan.FromMinutes(60)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionLiveU, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionMicrowave, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionEurovision, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionFiber, System.TimeSpan.FromMinutes(30)}, {Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Destination, System.TimeSpan.FromMinutes(30)}, }; + private readonly Skyline.DataMiner.Automation.IEngine engine; + public ServiceManager(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers) + { + Helpers = helpers ?? throw new System.ArgumentNullException(nameof(helpers)); + this.engine = helpers.Engine; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers Helpers + { + get; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service GetService(System.Guid serviceId) + { + var reservationInstance = GetReservation(serviceId); + if (reservationInstance == null) + { + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.ReservationNotFoundException(serviceId); + } + + var service = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service.FromReservationInstance(Helpers, reservationInstance); + return service; + } + + public Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance GetReservation(System.Guid id) + { + return Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ResourceManager.GetReservationInstance(id); + } + + public System.Collections.Generic.List GetFunctions(Skyline.DataMiner.Net.ResourceManager.Objects.ServiceReservationInstance reservationInstance, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition serviceDefinition) + { + if (reservationInstance == null) + throw new System.ArgumentNullException(nameof(reservationInstance)); + if (serviceDefinition == null) + throw new System.ArgumentNullException(nameof(serviceDefinition)); + LogMethodStarted(nameof(GetFunctions), out var stopwatch); + if (reservationInstance.IsQuarantined) + { + // When the service reservation instance is quarantined, no valid function data is available. + return new System.Collections.Generic.List(); + } + + var functions = new System.Collections.Generic.List(); + foreach (var node in serviceDefinition.Diagram.Nodes) + { + var function = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function(Helpers, reservationInstance, node, serviceDefinition); + functions.Add(function); + } + + LogMethodCompleted(nameof(GetFunctions), null, stopwatch); + return functions; + } + + /// + /// Gets the Pre Roll duration for the provided Service Definition. + /// + /// Service Definition for which the pre roll is requested. + /// Optional IntegrationType of the service. Affects the pre roll for Plasma Services. + /// Pre Roll of the Primary Source Service. In case the Pre Roll of the Primary Source Service itself is requested, this value is ignored. + /// TimeSpan of the Pre Roll. + public static System.TimeSpan GetPreRollDuration(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition serviceDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType integrationType = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.None, System.TimeSpan primarySourcePreRollDuration = default(System.TimeSpan)) + { + System.TimeSpan originalPreroll; + switch (integrationType) + { + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma: + originalPreroll = PlasmaServicePreRoll; + break; + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Feenix: + originalPreroll = FeenixServicePreRoll; + break; + default: + if (serviceDefinition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && serviceDefinition.Description.ToUpper().Contains("MESSI LIVE")) + { + // MESSI LIVE REC Pre Roll = 10 min + originalPreroll = MessiLiveRecordingPreRoll; + } + else if (serviceDefinition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && serviceDefinition.Description.ToUpper().Equals("MESSI NEWS")) + { + // MESSI NEWS REC Pre Roll = 5 min + originalPreroll = MessiNewsRecordingPreRoll; + } + else if (preRollDurations.ContainsKey(serviceDefinition.VirtualPlatform)) + { + originalPreroll = preRollDurations[serviceDefinition.VirtualPlatform]; + } + else + { + originalPreroll = primarySourcePreRollDuration; + } + + break; + } + + // Temporary workaround as YLE would temporarily like to see smaller prerolls + if (originalPreroll < Preroll) + return originalPreroll; + return Preroll; + } + + /// + /// Gets the Post Roll duration for the provided Service Definition. + /// + /// Service Definition for which the post roll is requested. + /// Optional IntegrationType of the service. Affects the post roll for Plasma Services. + /// Post Roll of the Primary Source Service. In case the Post Roll of the Primary Source Service itself is requested, this value is ignored. + /// TimeSpan of the Post Roll. + public static System.TimeSpan GetPostRollDuration(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition serviceDefinition, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType integrationType = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.None, System.TimeSpan primarySourcePostRollDuration = default(System.TimeSpan)) + { + System.TimeSpan originalPostRoll; + switch (integrationType) + { + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Plasma: + originalPostRoll = PlasmaServicePostRoll; + break; + case Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType.Feenix: + originalPostRoll = FeenixServicePostRoll; + break; + default: + if (serviceDefinition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && serviceDefinition.Description.ToUpper().Contains("MESSI LIVE")) + { + // MESSI LIVE REC Post Roll = 20 min + originalPostRoll = MessiLiveRecordingPostRoll; + } + else if (serviceDefinition.VirtualPlatform == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.Recording && serviceDefinition.Description.ToUpper().Equals("MESSI NEWS")) + { + // MESSI NEWS REC Post Roll = 10min + originalPostRoll = MessiNewsRecordingPostRoll; + } + else if (postRollDurations.ContainsKey(serviceDefinition.VirtualPlatform)) + { + originalPostRoll = postRollDurations[serviceDefinition.VirtualPlatform]; + } + else + { + originalPostRoll = primarySourcePostRollDuration; + } + + break; + } + + // Temporary workaround as YLE would temporarily like to see smaller postrolls + if (originalPostRoll < PostRoll) + return originalPostRoll; + return PostRoll; + } + + private void LogMethodStarted(string methodName, out System.Diagnostics.Stopwatch stopwatch, string objectName = null) + { + Helpers.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager), methodName, out stopwatch, objectName); + } + + private void LogMethodCompleted(string methodName, string objectName = null, System.Diagnostics.Stopwatch stopwatch = null) + { + Helpers.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager), methodName, objectName, stopwatch); + } + } + + /// + /// A sub recording for a specific recording. + /// + public class SubRecording : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.IYleChangeTracking + { + private string initialName; + private string initialAdditionalInfo; + private System.DateTime initialEstimatedTimeSlotStart; + private System.DateTime initialEstimatedTimeSlotEnd; + private string initialTimeSlotDescription; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.ValidationInfo nameValidation; + public SubRecording() + { + Id = System.Guid.NewGuid(); + EstimatedTimeSlotStart = System.DateTime.Now.AddDays(1); + EstimatedTimeSlotEnd = System.DateTime.Now.AddDays(1); + } + + /// + /// Used to identify the object by a controller. + /// + [Newtonsoft.Json.JsonIgnore] + public System.Guid Id + { + get; + } + + /// + /// The name of this sub recording. + /// + public string Name + { + get; + set; + } + + /// + /// Property set by controller and used by UI for validation. + /// + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.ValidationInfo NameValidation + { + get + { + if (nameValidation == null) + nameValidation = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.ValidationInfo(); + return nameValidation; + } + + set + { + nameValidation = value; + } + } + + /// + /// Additional information about this sub recording. + /// + public string AdditionalInformation + { + get; + set; + } + + /// + /// The start of the estimated time slot for this sub recording. + /// + public System.DateTime EstimatedTimeSlotStart + { + get; + set; + } + + /// + /// The end of the estimated time slot for this sub recording. + /// + public System.DateTime EstimatedTimeSlotEnd + { + get; + set; + } + + /// + /// The description for this time slot. + /// + public string TimeslotDescription + { + get; + set; + } + + [Newtonsoft.Json.JsonIgnore] + public bool IsChanged => ChangeInfo.IsChanged; + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo ChangeInfo => GetChanges(); + [Newtonsoft.Json.JsonIgnore] + public bool ChangeTrackingEnabled + { + get; + private set; + } + + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo GetChanges() + { + var changeInfo = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.ChangeInfo(); + bool nameIsChanged = Name != initialName; + bool additionalInfoIsChanged = AdditionalInformation != initialAdditionalInfo; + bool estimatedTimeSlotStartIsChanged = EstimatedTimeSlotStart != initialEstimatedTimeSlotStart; + bool estimatedTimeSlotEndIsChanged = EstimatedTimeSlotEnd != initialEstimatedTimeSlotEnd; + bool timeSlotDescriptionIsChanged = TimeslotDescription != initialTimeSlotDescription; + if (nameIsChanged || additionalInfoIsChanged || estimatedTimeSlotStartIsChanged || estimatedTimeSlotEndIsChanged || timeSlotDescriptionIsChanged) + changeInfo.MarkCustomPropertiesChanged(); + return changeInfo; + } + + public void AcceptChanges() + { + initialName = Name; + initialAdditionalInfo = AdditionalInformation; + initialEstimatedTimeSlotStart = EstimatedTimeSlotStart; + initialEstimatedTimeSlotEnd = EstimatedTimeSlotEnd; + initialTimeSlotDescription = TimeslotDescription; + } + + public override string ToString() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.AppendLine($"Sub recording name: " + Name + "|"); + sb.AppendLine($"Sub recording start: " + System.Convert.ToString(EstimatedTimeSlotStart, System.Globalization.CultureInfo.InvariantCulture) + "|"); + sb.AppendLine($"Sub recording end: " + System.Convert.ToString(EstimatedTimeSlotEnd, System.Globalization.CultureInfo.InvariantCulture) + "|"); + sb.AppendLine($"Sub recording time slot description: " + TimeslotDescription); + return sb.ToString(); + } + } + + namespace Auto_Generation + { + public class AudioProcessingService : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.LiveVideoService + { + private static readonly System.Guid InputAudioChannel1ProfileParameterId = System.Guid.Parse("b60f8740-f593-431b-8043-474ccb8f9566"); + private static readonly System.Guid InputAudioChannel2ProfileParameterId = System.Guid.Parse("1fe71070-44d5-4ad0-95db-103413935506"); + private static readonly System.Guid InputAudioChannel3ProfileParameterId = System.Guid.Parse("00d823aa-4363-4d49-9eb6-fa2a2712bf9c"); + private static readonly System.Guid InputAudioChannel4ProfileParameterId = System.Guid.Parse("bc63cd0f-1886-45ff-a675-659a2f840166"); + private static readonly System.Guid InputAudioChannel5ProfileParameterId = System.Guid.Parse("7d8a7d82-a328-4f5c-9c4d-a1f634fdefc5"); + private static readonly System.Guid InputAudioChannel6ProfileParameterId = System.Guid.Parse("81352369-5ece-4c1e-98d6-bd908589e2c4"); + private static readonly System.Guid InputAudioChannel7ProfileParameterId = System.Guid.Parse("cb840609-c68c-4636-9225-b3667685e29c"); + private static readonly System.Guid InputAudioChannel8ProfileParameterId = System.Guid.Parse("11ea232f-511e-463a-927a-d4ed4fac52b6"); + private static readonly System.Guid InputAudioChannel9ProfileParameterId = System.Guid.Parse("96837519-a1be-4415-aef9-ec7c148a8ce0"); + private static readonly System.Guid InputAudioChannel10ProfileParameterId = System.Guid.Parse("6701766b-60d4-499c-8e84-ee91f2afbc65"); + private static readonly System.Guid InputAudioChannel11ProfileParameterId = System.Guid.Parse("e39f61ce-515f-4134-b308-32fb6c3df9c0"); + private static readonly System.Guid InputAudioChannel12ProfileParameterId = System.Guid.Parse("b7e5efb5-8c48-4670-9d3b-c8315beeb0f8"); + private static readonly System.Guid InputAudioChannel13ProfileParameterId = System.Guid.Parse("4da8b4de-178c-4bbe-b48c-69f25dba46c9"); + private static readonly System.Guid InputAudioChannel14ProfileParameterId = System.Guid.Parse("c1f16b91-a429-4e09-b315-34900b6a0906"); + private static readonly System.Guid InputAudioChannel15ProfileParameterId = System.Guid.Parse("b305ea6d-9028-44e3-8b72-e394ade2ac0c"); + private static readonly System.Guid InputAudioChannel16ProfileParameterId = System.Guid.Parse("01133e53-fa18-48d8-bb3e-073326618f3c"); + private static readonly System.Guid OutputAudioChannel1ProfileParameterId = System.Guid.Parse("c18bcf3e-7985-45f4-b968-56826861b761"); + private static readonly System.Guid OutputAudioChannel2ProfileParameterId = System.Guid.Parse("3c8bc1f0-8509-4ca8-91a9-e3528cd69bc6"); + private static readonly System.Guid OutputAudioChannel3ProfileParameterId = System.Guid.Parse("edbc7e6d-0823-41b4-a0ac-89e0b0bb70a4"); + private static readonly System.Guid OutputAudioChannel4ProfileParameterId = System.Guid.Parse("9031245f-6c36-4437-a22d-b2b65fdedb17"); + private static readonly System.Guid OutputAudioChannel5ProfileParameterId = System.Guid.Parse("26f31192-01ab-45a1-b214-a56dab65072f"); + private static readonly System.Guid OutputAudioChannel6ProfileParameterId = System.Guid.Parse("f6e684f5-3627-4fb8-9406-2e6898655440"); + private static readonly System.Guid OutputAudioChannel7ProfileParameterId = System.Guid.Parse("447bb387-397d-4565-88ff-972488e1feba"); + private static readonly System.Guid OutputAudioChannel8ProfileParameterId = System.Guid.Parse("cdfb4027-3ebb-4167-bb87-b94e732f1461"); + private static readonly System.Guid OutputAudioChannel9ProfileParameterId = System.Guid.Parse("0f5ecba8-3c17-4831-b7f0-cca2a80e001f"); + private static readonly System.Guid OutputAudioChannel10ProfileParameterId = System.Guid.Parse("fee87c0a-bb43-4819-ad66-1d366f7435ed"); + private static readonly System.Guid OutputAudioChannel11ProfileParameterId = System.Guid.Parse("de03ea6a-029e-4bf2-ad57-646a14417c36"); + private static readonly System.Guid OutputAudioChannel12ProfileParameterId = System.Guid.Parse("9f964476-2a3b-4c49-8e75-deadfc91bc04"); + private static readonly System.Guid OutputAudioChannel13ProfileParameterId = System.Guid.Parse("65929b68-e642-4ed6-a669-27455690137e"); + private static readonly System.Guid OutputAudioChannel14ProfileParameterId = System.Guid.Parse("8de81be4-8daf-4e30-9a5f-2ae6fd1a22dd"); + private static readonly System.Guid OutputAudioChannel15ProfileParameterId = System.Guid.Parse("a4e3c96b-7c15-43a8-944d-61ddcc7c2905"); + private static readonly System.Guid OutputAudioChannel16ProfileParameterId = System.Guid.Parse("517be756-d2d3-4ce1-b9e7-cee150264c0c"); + public static readonly string AudioEmbeddingFunctionDefinitionName = "Audio Embedding"; + public static readonly string AudioDeembeddingFunctionDefinitionName = "Audio Deembedding"; + public static readonly string AudioShufflingFunctionDefinitionName = "Audio Shuffling"; + public static readonly string AudioDolbyDecodingFunctionDefinitionName = "Audio Dolby Decoding"; + public static readonly int MatrixSdiInputAudioDeembeddingFunctionNodeId = 3; + public static readonly int MatrixSdiOutputAudioDolbyDecodingFunctionNodeId = 2; + public static readonly int MatrixSdiInputAudioDolbyDecodingFunctionNodeId = 7; + public static readonly int MatrixSdiOutputAudioShufflingFunctionNodeId = 6; + public static readonly int MatrixSdiInputAudioShufflingFunctionNodeId = 10; + public static readonly int MatrixSdiOutputAudioEmbeddingFunctionNodeId = 9; + private Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource inputResource; + private Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource outputResource; + private string inputAudioChannel1; + private string inputAudioChannel2; + private string inputAudioChannel3; + private string inputAudioChannel4; + private string inputAudioChannel5; + private string inputAudioChannel6; + private string inputAudioChannel7; + private string inputAudioChannel8; + private string inputAudioChannel9; + private string inputAudioChannel10; + private string inputAudioChannel11; + private string inputAudioChannel12; + private string inputAudioChannel13; + private string inputAudioChannel14; + private string inputAudioChannel15; + private string inputAudioChannel16; + private string outputAudioChannel1; + private string outputAudioChannel2; + private string outputAudioChannel3; + private string outputAudioChannel4; + private string outputAudioChannel5; + private string outputAudioChannel6; + private string outputAudioChannel7; + private string outputAudioChannel8; + private string outputAudioChannel9; + private string outputAudioChannel10; + private string outputAudioChannel11; + private string outputAudioChannel12; + private string outputAudioChannel13; + private string outputAudioChannel14; + private string outputAudioChannel15; + private string outputAudioChannel16; + public AudioProcessingService(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order): base(helpers, service, order) + { + UpdateInputOutputResource(service.Functions); + foreach (var function in service.Functions) + { + foreach (var parameter in function.Parameters) + { + if (parameter.Id == InputAudioChannel1ProfileParameterId) + inputAudioChannel1 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel2ProfileParameterId) + inputAudioChannel2 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel3ProfileParameterId) + inputAudioChannel3 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel4ProfileParameterId) + inputAudioChannel4 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel5ProfileParameterId) + inputAudioChannel5 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel6ProfileParameterId) + inputAudioChannel6 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel7ProfileParameterId) + inputAudioChannel7 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel8ProfileParameterId) + inputAudioChannel8 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel9ProfileParameterId) + inputAudioChannel9 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel10ProfileParameterId) + inputAudioChannel10 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel11ProfileParameterId) + inputAudioChannel11 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel12ProfileParameterId) + inputAudioChannel12 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel13ProfileParameterId) + inputAudioChannel13 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel14ProfileParameterId) + inputAudioChannel14 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel15ProfileParameterId) + inputAudioChannel15 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == InputAudioChannel16ProfileParameterId) + inputAudioChannel16 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel1ProfileParameterId) + outputAudioChannel1 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel2ProfileParameterId) + outputAudioChannel2 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel3ProfileParameterId) + outputAudioChannel3 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel4ProfileParameterId) + outputAudioChannel4 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel5ProfileParameterId) + outputAudioChannel5 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel6ProfileParameterId) + outputAudioChannel6 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel7ProfileParameterId) + outputAudioChannel7 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel8ProfileParameterId) + outputAudioChannel8 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel9ProfileParameterId) + outputAudioChannel9 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel10ProfileParameterId) + outputAudioChannel10 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel11ProfileParameterId) + outputAudioChannel11 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel12ProfileParameterId) + outputAudioChannel12 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel13ProfileParameterId) + outputAudioChannel13 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel14ProfileParameterId) + outputAudioChannel14 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel15ProfileParameterId) + outputAudioChannel15 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == OutputAudioChannel16ProfileParameterId) + outputAudioChannel16 = System.Convert.ToString(parameter.Value); + } + } + + LiveVideoServices = new System.Collections.Generic.List(); + } + + public override Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Type Type => Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Type.AudioProcessing; + public string InputAudioChannel1 + { + get + { + return inputAudioChannel1; + } + + set + { + inputAudioChannel1 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel1ProfileParameterId, value); + } + } + + public string InputAudioChannel2 + { + get + { + return inputAudioChannel2; + } + + set + { + inputAudioChannel2 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel2ProfileParameterId, value); + } + } + + public string InputAudioChannel3 + { + get + { + return inputAudioChannel3; + } + + set + { + inputAudioChannel3 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel3ProfileParameterId, value); + } + } + + public string InputAudioChannel4 + { + get + { + return inputAudioChannel4; + } + + set + { + inputAudioChannel4 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel4ProfileParameterId, value); + } + } + + public string InputAudioChannel5 + { + get + { + return inputAudioChannel5; + } + + set + { + inputAudioChannel5 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel5ProfileParameterId, value); + } + } + + public string InputAudioChannel6 + { + get + { + return inputAudioChannel6; + } + + set + { + inputAudioChannel6 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel6ProfileParameterId, value); + } + } + + public string InputAudioChannel7 + { + get + { + return inputAudioChannel7; + } + + set + { + inputAudioChannel7 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel7ProfileParameterId, value); + } + } + + public string InputAudioChannel8 + { + get + { + return inputAudioChannel8; + } + + set + { + inputAudioChannel8 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel8ProfileParameterId, value); + } + } + + public string InputAudioChannel9 + { + get + { + return inputAudioChannel9; + } + + set + { + inputAudioChannel9 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel9ProfileParameterId, value); + } + } + + public string InputAudioChannel10 + { + get + { + return inputAudioChannel10; + } + + set + { + inputAudioChannel10 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel10ProfileParameterId, value); + } + } + + public string InputAudioChannel11 + { + get + { + return inputAudioChannel11; + } + + set + { + inputAudioChannel11 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel11ProfileParameterId, value); + } + } + + public string InputAudioChannel12 + { + get + { + return inputAudioChannel12; + } + + set + { + inputAudioChannel12 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel12ProfileParameterId, value); + } + } + + public string InputAudioChannel13 + { + get + { + return inputAudioChannel13; + } + + set + { + inputAudioChannel13 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel13ProfileParameterId, value); + } + } + + public string InputAudioChannel14 + { + get + { + return inputAudioChannel14; + } + + set + { + inputAudioChannel14 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel14ProfileParameterId, value); + } + } + + public string InputAudioChannel15 + { + get + { + return inputAudioChannel15; + } + + set + { + inputAudioChannel15 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel15ProfileParameterId, value); + } + } + + public string InputAudioChannel16 + { + get + { + return inputAudioChannel16; + } + + set + { + inputAudioChannel16 = value; + UpdateServiceAudioChannelParameter(InputAudioChannel16ProfileParameterId, value); + } + } + + public string OutputAudioChannel1 + { + get + { + return outputAudioChannel1; + } + + set + { + outputAudioChannel1 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel1ProfileParameterId, value); + } + } + + public string OutputAudioChannel2 + { + get + { + return outputAudioChannel2; + } + + set + { + outputAudioChannel2 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel2ProfileParameterId, value); + } + } + + public string OutputAudioChannel3 + { + get + { + return outputAudioChannel3; + } + + set + { + outputAudioChannel3 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel3ProfileParameterId, value); + } + } + + public string OutputAudioChannel4 + { + get + { + return outputAudioChannel4; + } + + set + { + outputAudioChannel4 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel4ProfileParameterId, value); + } + } + + public string OutputAudioChannel5 + { + get + { + return outputAudioChannel5; + } + + set + { + outputAudioChannel5 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel5ProfileParameterId, value); + } + } + + public string OutputAudioChannel6 + { + get + { + return outputAudioChannel6; + } + + set + { + outputAudioChannel6 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel6ProfileParameterId, value); + } + } + + public string OutputAudioChannel7 + { + get + { + return outputAudioChannel7; + } + + set + { + outputAudioChannel7 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel7ProfileParameterId, value); + } + } + + public string OutputAudioChannel8 + { + get + { + return outputAudioChannel8; + } + + set + { + outputAudioChannel8 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel8ProfileParameterId, value); + } + } + + public string OutputAudioChannel9 + { + get + { + return outputAudioChannel9; + } + + set + { + outputAudioChannel9 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel9ProfileParameterId, value); + } + } + + public string OutputAudioChannel10 + { + get + { + return outputAudioChannel10; + } + + set + { + outputAudioChannel10 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel10ProfileParameterId, value); + } + } + + public string OutputAudioChannel11 + { + get + { + return outputAudioChannel11; + } + + set + { + outputAudioChannel11 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel11ProfileParameterId, value); + } + } + + public string OutputAudioChannel12 + { + get + { + return outputAudioChannel12; + } + + set + { + outputAudioChannel12 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel12ProfileParameterId, value); + } + } + + public string OutputAudioChannel13 + { + get + { + return outputAudioChannel13; + } + + set + { + outputAudioChannel13 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel13ProfileParameterId, value); + } + } + + public string OutputAudioChannel14 + { + get + { + return outputAudioChannel14; + } + + set + { + outputAudioChannel14 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel14ProfileParameterId, value); + } + } + + public string OutputAudioChannel15 + { + get + { + return outputAudioChannel15; + } + + set + { + outputAudioChannel15 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel15ProfileParameterId, value); + } + } + + public string OutputAudioChannel16 + { + get + { + return outputAudioChannel16; + } + + set + { + outputAudioChannel16 = value; + UpdateServiceAudioChannelParameter(OutputAudioChannel16ProfileParameterId, value); + } + } + + /// + /// The list of live video services using this Audio Processing service. + /// + public System.Collections.Generic.List LiveVideoServices + { + get; + set; + } + + /// + /// The input resource for this Audio Processing Service. + /// This overrides the input resource set when initializing the Live Video Services as an Audio Processing service doesn't require all functions. + /// + public override Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource InputResource + { + get + { + return inputResource; + } + } + + /// + /// The output resource for this Audio Processing Service. + /// This overrides the output resource set when initializing the Live Video Services as an Audio Processing service doesn't require all functions. + /// + public override Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource OutputResource + { + get + { + return outputResource; + } + } + + /// + /// Update the input and output resource based on what functions of the Audio Processing service are required. + /// + /// The functions of the Audio Processing service. + private void UpdateInputOutputResource(System.Collections.Generic.List functions) + { + if (AudioDeembeddingRequired) + { + var audioDeembeddingFunction = System.Linq.Enumerable.FirstOrDefault(functions, f => f.Name == AudioDeembeddingFunctionDefinitionName); + if (audioDeembeddingFunction != null) + inputResource = audioDeembeddingFunction.Resource; + if (!AudioDolbyDecodingRequired && !AudioShufflingRequired && !AudioEmbeddingRequired && audioDeembeddingFunction != null) + { + outputResource = audioDeembeddingFunction.Resource; + return; + } + } + + if (AudioDolbyDecodingRequired) + { + var audioDolbyDecodingFunction = System.Linq.Enumerable.FirstOrDefault(functions, f => f.Name == AudioDolbyDecodingFunctionDefinitionName); + if (!AudioDeembeddingRequired && audioDolbyDecodingFunction != null) + inputResource = audioDolbyDecodingFunction.Resource; + if (!AudioShufflingRequired && !AudioEmbeddingRequired && audioDolbyDecodingFunction != null) + { + outputResource = audioDolbyDecodingFunction.Resource; + return; + } + } + + if (AudioShufflingRequired) + { + var audioShufflingFunction = System.Linq.Enumerable.FirstOrDefault(functions, f => f.Name == AudioShufflingFunctionDefinitionName); + if (!AudioDeembeddingRequired && !AudioDolbyDecodingRequired && audioShufflingFunction != null) + inputResource = audioShufflingFunction.Resource; + if (!AudioEmbeddingRequired && audioShufflingFunction != null) + { + outputResource = audioShufflingFunction.Resource; + return; + } + } + + if (AudioEmbeddingRequired) + { + var audioEmbeddingFunction = System.Linq.Enumerable.FirstOrDefault(functions, f => f.Name == AudioEmbeddingFunctionDefinitionName); + if (!AudioDeembeddingRequired && !AudioDolbyDecodingRequired && !AudioShufflingRequired && audioEmbeddingFunction != null) + inputResource = audioEmbeddingFunction.Resource; + if (audioEmbeddingFunction != null) + outputResource = audioEmbeddingFunction.Resource; + } + } + + private void UpdateServiceAudioChannelParameter(System.Guid parameterId, string value) + { + if (Service == null) + { + return; + } + + foreach (var function in Service.Functions) + { + if (function.Parameters == null) + { + continue; + } + + var parameter = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p.Id == parameterId); + if (parameter != null) + { + parameter.Value = value; + return; + } + } + } + } + + /// + /// Represents a service of type Graphics Processing. + /// + public class GraphicsProcessingService : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.LiveVideoService + { + public GraphicsProcessingService(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order): base(helpers, service, order) + { + VideoFormat = "1080i50"; + RemoteGraphics = System.Linq.Enumerable.FirstOrDefault(System.Linq.Enumerable.SelectMany(service.Functions, f => f.Parameters), p => p.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.RemoteGraphics)?.StringValue; + DestinationsAndTransmissions = new System.Collections.Generic.List(); + } + + public GraphicsProcessingService(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, string graphicsProcessingEngine, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order): base(helpers, service, order) + { + VideoFormat = "1080i50"; + RemoteGraphics = graphicsProcessingEngine; + DestinationsAndTransmissions = new System.Collections.Generic.List(); + } + + /// + /// Indicates the type of this service. + /// + public override Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Type Type => Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Type.GraphicsProcessing; + /// + /// The list of Destination services that use this Graphics Processing service. + /// + public System.Collections.Generic.List DestinationsAndTransmissions + { + get; + set; + } + } + + /// + /// Base class for any Live Video service. + /// + public abstract class LiveVideoService : System.IEquatable + { + public readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order Order; + protected static readonly System.Guid VideoFormatProfileParameterId = System.Guid.Parse("8dc6df35-c574-4412-bf52-de7e3c78201c"); + protected static readonly System.Guid RecordingVideoFormatProfileParameterId = System.Guid.Parse("105baed9-4031-4d7c-a436-d26fe608af7b"); + protected static readonly System.Guid AudioEmbeddingRequiredProfileParameterId = System.Guid.Parse("a2726fd1-cc4b-4b23-b464-3684a0db4dd6"); + protected static readonly System.Guid AudioDeembeddingRequiredProfileParameterId = System.Guid.Parse("1d51086a-ca66-4e1d-b84f-6fd05a24ee68"); + protected static readonly System.Guid AudioShufflingRequiredProfileParameterId = System.Guid.Parse("01682ff9-2cc4-4cd5-8252-d5956424479a"); + protected static readonly System.Guid AudioDolbyDecodingRequiredProfileParameterId = System.Guid.Parse("35215bb4-0faa-423f-beed-58ada9b604b3"); + protected static readonly string AudioProcessingFunctionRequiredTrueProfileParameterValue = "Yes"; + protected static readonly string AudioProcessingFunctionRequiredFalseProfileParameterValue = "No"; + private readonly System.Guid AudioChannel1ProfileParameterId = System.Guid.Parse("d4f1e0fe-1a72-4ec3-9fd8-aefd4785ebdf"); + private readonly System.Guid AudioChannel2ProfileParameterId = System.Guid.Parse("bce7eff1-a884-47af-a182-559e0cfa4379"); + private readonly System.Guid AudioChannel3ProfileParameterId = System.Guid.Parse("471d52de-b90c-4d8d-9cb5-b11916a06d08"); + private readonly System.Guid AudioChannel4ProfileParameterId = System.Guid.Parse("5f014774-c3ce-492e-96c3-cd7402dbe171"); + private readonly System.Guid AudioChannel5ProfileParameterId = System.Guid.Parse("fad366e6-2f29-466b-a286-434446cf6437"); + private readonly System.Guid AudioChannel6ProfileParameterId = System.Guid.Parse("5c68fb8a-5c8f-4970-aeb4-b04b5f465724"); + private readonly System.Guid AudioChannel7ProfileParameterId = System.Guid.Parse("83b3d476-39dd-4660-854f-27bbe6436914"); + private readonly System.Guid AudioChannel8ProfileParameterId = System.Guid.Parse("e9aeb156-a027-4898-b41e-6af88169a3ff"); + private readonly System.Guid AudioChannel9ProfileParameterId = System.Guid.Parse("5eadca8d-f96a-464d-81a4-139dc6da0fba"); + private readonly System.Guid AudioChannel10ProfileParameterId = System.Guid.Parse("7178133a-d8a8-485d-99fa-b909ef73d848"); + private readonly System.Guid AudioChannel11ProfileParameterId = System.Guid.Parse("052babfe-b396-4d3f-a305-21442b3e0fd1"); + private readonly System.Guid AudioChannel12ProfileParameterId = System.Guid.Parse("acb1bef4-f80b-424b-abd1-a51a05586a6d"); + private readonly System.Guid AudioChannel13ProfileParameterId = System.Guid.Parse("fa83f575-0935-4952-b561-ce349c7e59fb"); + private readonly System.Guid AudioChannel14ProfileParameterId = System.Guid.Parse("f60e0b3e-840a-47f1-b521-9e1dbdc28562"); + private readonly System.Guid AudioChannel15ProfileParameterId = System.Guid.Parse("2712a2f9-273a-439f-b85a-5101789782cf"); + private readonly System.Guid AudioChannel16ProfileParameterId = System.Guid.Parse("cc76cdc0-925c-472f-985f-c0c5e477639c"); + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.GraphicsProcessingService graphicsProcessing; + private readonly System.Collections.Generic.List children; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.VideoProcessingService videoProcessingService; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService audioProcessingService; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.RoutingService inputRoutingService; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.RoutingService outputRoutingService; + private string audioEmbedding; + private string audioDeembedding; + private string audioShuffling; + private string audioDolbyDecoding; + protected LiveVideoService(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order) + { + Helpers = helpers ?? throw new System.ArgumentNullException(nameof(helpers)); + Order = order; + Service = service; + // firstFunction en lastFunction is used to select the first or last resource from the service definition (used to connect to matrix input or output) + int? firstFunctionPosition = null, lastFunctionPosition = null; + foreach (var function in service.Functions) + { + var functionPositionInServiceDefinition = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.GraphExtensions.GetFunctionPosition(service.Definition.Diagram, function); + if (!firstFunctionPosition.HasValue || firstFunctionPosition > functionPositionInServiceDefinition) + { + InputResource = function.Resource; + firstFunctionPosition = functionPositionInServiceDefinition; + } + + if (!lastFunctionPosition.HasValue || lastFunctionPosition < functionPositionInServiceDefinition) + { + OutputResource = function.Resource; + lastFunctionPosition = functionPositionInServiceDefinition; + } + + foreach (var parameter in function.Parameters) + { + if (parameter.Id == VideoFormatProfileParameterId || parameter.Id == RecordingVideoFormatProfileParameterId) + VideoFormat = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioEmbeddingRequiredProfileParameterId) + audioEmbedding = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioDeembeddingRequiredProfileParameterId) + audioDeembedding = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioShufflingRequiredProfileParameterId) + audioShuffling = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioDolbyDecodingRequiredProfileParameterId) + audioDolbyDecoding = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel1ProfileParameterId) + AudioChannel1 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel2ProfileParameterId) + AudioChannel2 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel3ProfileParameterId) + AudioChannel3 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel4ProfileParameterId) + AudioChannel4 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel5ProfileParameterId) + AudioChannel5 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel6ProfileParameterId) + AudioChannel6 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel7ProfileParameterId) + AudioChannel7 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel8ProfileParameterId) + AudioChannel8 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel9ProfileParameterId) + AudioChannel9 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel10ProfileParameterId) + AudioChannel10 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel11ProfileParameterId) + AudioChannel11 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel12ProfileParameterId) + AudioChannel12 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel13ProfileParameterId) + AudioChannel13 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel14ProfileParameterId) + AudioChannel14 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel15ProfileParameterId) + AudioChannel15 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == AudioChannel16ProfileParameterId) + AudioChannel16 = System.Convert.ToString(parameter.Value); + else if (parameter.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.ProfileParameterGuids.RemoteGraphics) + RemoteGraphics = parameter.StringValue; + } + } + + children = new System.Collections.Generic.List(); + Children = children.AsReadOnly(); + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers Helpers + { + get; + } + + /// + /// Indicates the type of this Live Video service. + /// + public abstract Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Type Type + { + get; + } + + /// + /// The service object of this Live Video service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service Service + { + get; + private set; + } + + /// + /// The configured video format for this Live Video service. + /// + public string VideoFormat + { + get; + protected set; + } + + /// + /// Indicates if audio embedding is required. + /// + public bool AudioEmbeddingRequired + { + get => audioEmbedding == AudioProcessingFunctionRequiredTrueProfileParameterValue; + protected set + { + audioEmbedding = value ? AudioProcessingFunctionRequiredTrueProfileParameterValue : AudioProcessingFunctionRequiredFalseProfileParameterValue; + if (Service != null) + { + foreach (var function in Service.Functions) + { + var audioEmbeddingParameter = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p.Id == AudioEmbeddingRequiredProfileParameterId); + if (audioEmbeddingParameter != null) + { + audioEmbeddingParameter.Value = audioEmbedding; + } + } + } + } + } + + /// + /// Indicates if audio deembedding is required. + /// + public bool AudioDeembeddingRequired + { + get => audioDeembedding == AudioProcessingFunctionRequiredTrueProfileParameterValue; + protected set + { + audioDeembedding = value ? AudioProcessingFunctionRequiredTrueProfileParameterValue : AudioProcessingFunctionRequiredFalseProfileParameterValue; + if (Service == null) + return; + foreach (var function in Service.Functions) + { + var audioDeembeddingParameter = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p.Id == AudioDeembeddingRequiredProfileParameterId); + if (audioDeembeddingParameter != null) + { + audioDeembeddingParameter.Value = audioDeembedding; + } + } + } + } + + /// + /// Indicates if audio shuffling is required. + /// + public bool AudioShufflingRequired + { + get => audioShuffling == AudioProcessingFunctionRequiredTrueProfileParameterValue; + set + { + audioShuffling = value ? AudioProcessingFunctionRequiredTrueProfileParameterValue : AudioProcessingFunctionRequiredFalseProfileParameterValue; + if (Service == null) + return; + foreach (var function in Service.Functions) + { + var audioShufflingParameter = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p.Id == AudioShufflingRequiredProfileParameterId); + if (audioShufflingParameter != null) + { + audioShufflingParameter.Value = audioShuffling; + } + } + } + } + + /// + /// Indicates if audio dolby decoding is required. + /// + public bool AudioDolbyDecodingRequired + { + get => audioDolbyDecoding == AudioProcessingFunctionRequiredTrueProfileParameterValue; + protected set + { + audioDolbyDecoding = value ? AudioProcessingFunctionRequiredTrueProfileParameterValue : AudioProcessingFunctionRequiredFalseProfileParameterValue; + if (Service == null) + return; + foreach (var function in Service.Functions) + { + var audioDolbyDecodingParameter = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p.Id == AudioDolbyDecodingRequiredProfileParameterId); + if (audioDolbyDecodingParameter != null) + { + audioDolbyDecodingParameter.Value = audioDolbyDecoding; + } + } + } + } + + /// + /// Indicates the configuration for Audio Channel 1. + /// + public string AudioChannel1 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 2. + /// + public string AudioChannel2 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 3. + /// + public string AudioChannel3 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 4. + /// + public string AudioChannel4 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 5. + /// + public string AudioChannel5 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 6. + /// + public string AudioChannel6 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 7. + /// + public string AudioChannel7 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 8. + /// + public string AudioChannel8 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 9. + /// + public string AudioChannel9 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 10. + /// + public string AudioChannel10 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 11. + /// + public string AudioChannel11 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 12. + /// + public string AudioChannel12 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 13. + /// + public string AudioChannel13 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 14. + /// + public string AudioChannel14 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 15. + /// + public string AudioChannel15 + { + get; + private set; + } + + /// + /// Indicates the configuration for Audio Channel 16. + /// + public string AudioChannel16 + { + get; + private set; + } + + /// + /// Indicates the parent of this Live Video service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.LiveVideoService Parent + { + get; + private set; + } + + /// + /// The list of children of this Live Video service. + /// + public System.Collections.ObjectModel.ReadOnlyCollection Children + { + get; + private set; + } + + /// + /// Indicates what remote graphics are required. + /// + public string RemoteGraphics + { + get; + protected set; + } + + /// + /// Reference to the Graphics Processing service used for this Destination. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.GraphicsProcessingService GraphicsProcessing + { + get => graphicsProcessing; + set + { + if (value == null && graphicsProcessing == null) + return; + if (value != null && graphicsProcessing != null && graphicsProcessing.Equals(value)) + return; + if (value == null) + { + graphicsProcessing.DestinationsAndTransmissions.Remove(this); + } + else + { + value.DestinationsAndTransmissions.Add(this); + } + + graphicsProcessing = value; + } + } + + /// + /// Indicates if the current Graphics Processing configuration is valid. + /// + public bool HasValidGraphicsProcessingConfiguration + { + get + { + if (IsGraphicsProcessingRequired) + { + if (GraphicsProcessing == null) + return false; + return HasValidGraphicsProcessingService; + } + else + { + return GraphicsProcessing == null; + } + } + } + + /// + /// Indicates if Graphics Processing is required. + /// + private bool IsGraphicsProcessingRequired => RemoteGraphics != null && RemoteGraphics != "None"; + /// + /// Indicates if the current Graphics Processing service is valid. + /// + private bool HasValidGraphicsProcessingService => GraphicsProcessing.RemoteGraphics == RemoteGraphics && GraphicsProcessing.Service.Start.ToUniversalTime() <= Service.Start.ToUniversalTime() && GraphicsProcessing.Service.End.ToUniversalTime() >= Service.End.ToUniversalTime(); + /// + /// The Video Processing service used by this Live Video service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.VideoProcessingService VideoProcessingService + { + get => videoProcessingService; + set + { + if (value == null && videoProcessingService == null) + return; + if (value != null && videoProcessingService != null && videoProcessingService.Equals(value)) + return; + if (value == null) + { + videoProcessingService.LiveVideoServices.Remove(this); + } + else + { + value.LiveVideoServices.Add(this); + } + + videoProcessingService = value; + } + } + + /// + /// The Audio Processing service used by this Live Video service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.AudioProcessingService AudioProcessingService + { + get => audioProcessingService; + set + { + if (value == null && audioProcessingService == null) + return; + if (value != null && audioProcessingService != null && audioProcessingService.Equals(value)) + return; + if (value == null) + { + audioProcessingService.LiveVideoServices.Remove(this); + } + else + { + value.LiveVideoServices.Add(this); + } + + audioProcessingService = value; + } + } + + /// + /// The Input Routing service for this Live Video service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.RoutingService InputRoutingService + { + get => inputRoutingService; + set + { + if (value == null && inputRoutingService == null) + return; + if (value != null && inputRoutingService != null && inputRoutingService.Equals(value)) + return; + inputRoutingService = value; + } + } + + /// + /// The Output Routing service for this Live Video service. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.RoutingService OutputRoutingService + { + get => outputRoutingService; + set + { + if (value == null && outputRoutingService == null) + return; + if (value != null && outputRoutingService != null && outputRoutingService.Equals(value)) + return; + outputRoutingService = value; + } + } + + /// + /// The input resource for this Live Video service. + /// + public virtual Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource InputResource + { + get; + } + + /// + /// The output resource for this Live Video service. + /// + public virtual Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource OutputResource + { + get; + } + + /// + /// Check if the provided object is the same as this service. + /// + /// The object to check. + /// True if both objects are the same. + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.LiveVideoService other = obj as Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.LiveVideoService; + if (other == null) + { + return false; + } + + return Equals(other); + } + + /// + /// Check if the provided Live Video service object is the same as this service. + /// + /// The Live Video service to check. + /// True if both services are the same. + public bool Equals(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.LiveVideoService other) + { + return other != null && other.Service.Equals(Service); + } + + /// + /// Get the hash code for this Live Video service. + /// + /// The hash code. + public override int GetHashCode() + { + return Service.GetHashCode(); + } + + protected void Log(string nameOfMethod, string message) + { + Helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.LiveVideoService), nameOfMethod, message, Service.Name); + } + } + + public class RoutingService : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.LiveVideoService + { + private Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource matrixInputSdi; + private Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource matrixOutputSdi; + public RoutingService(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order): base(helpers, service, order) + { + foreach (var function in service.Functions) + { + if (function.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.MatrixInputSdi) + { + matrixInputSdi = function.Resource; + function.ResourceChanged += (o, e) => matrixInputSdi = function.Resource; + } + else if (function.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.MatrixOutputSdi) + { + matrixOutputSdi = function.Resource; + function.ResourceChanged += (o, e) => matrixOutputSdi = function.Resource; + } + } + } + + public override Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Type Type => Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Type.Routing; + public Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource MatrixInputSdi + { + get => matrixInputSdi; + set + { + if (matrixInputSdi == null && value == null) + return; + if (matrixInputSdi != null && matrixInputSdi.Equals(value)) + return; + if (MatrixInputSdiIsValid) + { + Log($"{MatrixInputSdi}.Set", $"Matrix Input SDI resource is already set to '{MatrixInputSdi?.Name}' and should not be changed anymore."); + throw new System.InvalidOperationException($"Service {Service?.Name} matrix input SDI resource is already set to '{MatrixInputSdi?.Name}' and should not be changed anymore to '{value?.Name}'"); + } + + matrixInputSdi = value; + if (Service == null) + return; + var function = System.Linq.Enumerable.FirstOrDefault(Service.Functions, f => f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.MatrixInputSdi); + if (function != null) + { + function.Resource = value; + MatrixInputSdiIsValid = true; + Log($"{MatrixInputSdi}.Set", $"Set service {Service.Name} function {function.Name} resource to '{function.ResourceName}'."); + } + } + } + + public bool MatrixInputSdiIsValid + { + get; + set; + } + + = false; + public Skyline.DataMiner.Net.ResourceManager.Objects.FunctionResource MatrixOutputSdi + { + get => matrixOutputSdi; + set + { + if (matrixOutputSdi == null && value == null) + return; + if (matrixOutputSdi != null && matrixOutputSdi.Equals(value)) + return; + if (MatrixOutputSdiIsValid) + { + Log($"{MatrixOutputSdi}.Set", $"Matrix Output SDI resource is already set to '{MatrixOutputSdi?.Name}' and should not be changed anymore."); + throw new System.InvalidOperationException($"Service {Service?.Name} matrix output SDI resource is already set to '{MatrixOutputSdi?.Name}' and should not be changed anymore to '{value?.Name}'"); + } + + matrixOutputSdi = value; + if (Service == null) + return; + var function = System.Linq.Enumerable.FirstOrDefault(Service.Functions, f => f.Id == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.MatrixOutputSdi); + if (function != null) + { + function.Resource = value; + MatrixOutputSdiIsValid = true; + Log($"{MatrixOutputSdi}.Set", $"Set service {Service.Name} function {function.Name} resource to '{function.ResourceName}'."); + } + } + } + + public bool MatrixOutputSdiIsValid + { + get; + set; + } + + = false; + public override string ToString() + { + return $"{Service.Name} ({MatrixInputSdi?.Name},{MatrixOutputSdi?.Name})"; + } + } + + /// + /// Represents a service of type Video Processing. + /// + public class VideoProcessingService : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Auto_Generation.LiveVideoService + { + private static readonly System.Guid InputVideoFormatProfileParameterId = System.Guid.Parse("79a7d1f5-d750-400f-b5b9-b5e6d198ad25"); + private static readonly System.Guid OutputVideoFormatProfileParameterId = System.Guid.Parse("209d06c7-3b7a-49ae-a11f-b6d9f5920fca"); + public VideoProcessingService(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order): base(helpers, service, order) + { + foreach (var function in service.Functions) + { + var inputVideoFormatParameter = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p.Id == InputVideoFormatProfileParameterId); + if (inputVideoFormatParameter != null) + { + InputVideoFormat = System.Convert.ToString(inputVideoFormatParameter.Value); + } + + var outputVideoFormatParameter = System.Linq.Enumerable.FirstOrDefault(function.Parameters, p => p.Id == OutputVideoFormatProfileParameterId); + if (outputVideoFormatParameter != null) + { + OutputVideoFormat = System.Convert.ToString(outputVideoFormatParameter.Value); + } + + if (InputVideoFormat != null && OutputVideoFormat != null) + { + break; + } + } + + LiveVideoServices = new System.Collections.Generic.List(); + } + + public VideoProcessingService(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, string inputVideoFormat, string outputVideoFormat, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Order order): base(helpers, service, order) + { + InputVideoFormat = inputVideoFormat; + OutputVideoFormat = outputVideoFormat; + LiveVideoServices = new System.Collections.Generic.List(); + } + + /// + /// Indicates the type of this service. + /// + public override Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Type Type => Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Type.VideoProcessing; + /// + /// The input video format of this Video Processing service. + /// + public string InputVideoFormat + { + get; + private set; + } + + /// + /// The output video format of this Video Processing service. + /// + public string OutputVideoFormat + { + get; + private set; + } + + /// + /// The list of live video services using this Video Processing service. + /// + public System.Collections.Generic.List LiveVideoServices + { + get; + set; + } + } + } + + namespace Configuration + { + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class FunctionConfiguration + { + /// + /// The ID of the function. + /// + public System.Guid Id + { + get; + set; + } + + public string Name + { + get; + set; + } + + /// + /// The profile parameters configured for this function. + /// The key is the id of the profile parameter and the value is the actual value that was configured. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.Generic.Dictionary ProfileParameters + { + get; + set; + } + + /// + /// The resource assigned to this function + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Guid ResourceId + { + get; + set; + } + + /// + /// The resource name assigned to this function + /// + public string ResourceName + { + get; + set; + } + + public bool RequiresResource + { + get; + set; + } + + public bool McrHasOverruledFixedTieLineLogic + { + get; + set; + } + + = false; + public override string ToString() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.None); + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + public class ServiceConfiguration + { + /// + /// The ID of the service. + /// + public System.Guid Id + { + get; + set; + } + + /// + /// The name of the service. + /// + public string Name + { + get; + set; + } + + /// + /// Start time configured for this service. + /// + public System.DateTime Start + { + get; + set; + } + + /// + /// The preroll of the Service. + /// This was added in case it doesn't match the predefined prerolls when booked very fast. + /// + public System.TimeSpan PreRoll + { + get; + set; + } + + /// + /// End time configured for this service. + /// + public System.DateTime End + { + get; + set; + } + + /// + /// The service level (backup) for the service. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.BackupType? ServiceLevel + { + get; + set; + } + + /// + /// Linked service Id, only applicable when active backup applies on the order this service belongs. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Guid LinkedServiceId + { + get; + set; + } + + /// + /// Linked event Ids, only applicable for every type of event level reception service. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.Generic.HashSet LinkedEventIds + { + get; + set; + } + + /// + /// The function configurations for each function in this service. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.Generic.Dictionary Functions + { + get; + set; + } + + /// + /// The id of the service definition that is used for this service. + /// + public System.Guid ServiceDefinitionId + { + get; + set; + } + + /// + /// Indicates which integration created this Service. + /// If not specified this will be set to None. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.IntegrationType IntegrationType + { + get; + set; + } + + public bool IntegrationIsMaster + { + get; + set; + } + + /// + /// Indicates if this is an Eurovision service. + /// + public bool IsEurovisionService + { + get; + set; + } + + /// + /// This is set to true from the HandleIntegrationUpdate script if the synopsis contains a value for the ioMuxName field. + /// The ioMuxName field is used to define multiple multiplexed feeds in the signal. + /// If this boolean is true, you will be able to edit the Service Selection profile parameter of the Satellite Reception in the LiveOrderForm. + /// + public bool IsEurovisionMultiFeedService + { + get; + set; + } + + /// + /// Indicates if this service is an Event Level Reception or not. + /// + public bool IsEventLevelReception + { + get; + set; + } + + /// + /// Indicates if this service is an global Event Level Reception or not. + /// + public bool IsGlobalEventLevelReception + { + get; + set; + } + + /// + /// The id of the work order that has been requested from EBU. + /// This can be used to map the incoming Eurovision synopsis to this service correctly. + /// This is only applicable for EBU services that were requested through the LiveOrderForm. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string EurovisionWorkOrderId + { + get; + set; + } + + /// + /// The transmission number of the Eurovision synopsis in case of a Eurovision service. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string EurovisionTransmissionNumber + { + get; + set; + } + + /// + /// Serialized data of the Eurovision booking details as configured in the Customer UI. + /// This is only applicable in case of an Eurovision service. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision.EurovisionBookingDetails EurovisionBookingDetails + { + get; + set; + } + + /// + /// This property is only used when the Service was generated by the EBU integration. + /// In that case this property will contain the possible Receptions or Transmissions. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.Generic.List EurovisionServiceConfigurations + { + get; + set; + } + + /// + /// This property is only used when the Service is a Reception Service that was generated by the EBU integration. + /// In that case this property will contain the id of the destination in the synopsis on which this service is based. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string EurovisionDestinationId + { + get; + set; + } + + /// + /// This property is only used when the Service is a Reception or Transmission Service that was generated by the EBU integration. + /// In that case this property will contain the id of the technical system in the synopsis on which this service is based. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string EurovisionTechnicalSystemId + { + get; + set; + } + + /// + /// If an issue has been reported manually via the UpdateService script and when the order is finished. + /// The service will have the status Completed With Errors at the end. + /// + public bool HasAnIssueBeenreportedManually + { + get; + set; + } + + = false; + /// + /// Comments for this service. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Comments + { + get; + set; + } + + /// + /// + /// Contact Information Name. + /// Only applicable for LiveU receptions. + /// Will be saved in a custom property for LiveU receptions; + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string ContactInformationName + { + get; + set; + } + + /// + /// Contact Information Telephone Number. + /// Only applicable for LiveU receptions. + /// Will be saved in a custom property for LiveU receptions; + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string ContactInformationTelephoneNumber + { + get; + set; + } + + /// + /// Additional information LiveU device name. + /// Only applicable for LiveU receptions or transmissions. + /// Will be saved in a custom property for LiveU receptions or transmissions; + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string LiveUDeviceName + { + get; + set; + } + + /// + /// Normal users will fill in this field when LiveU is selected + /// News users will be able to fill in this field for every reception service. + /// + public string AudioReturnInfo + { + get; + set; + } + + /// + /// Additional information Vidigo Stream Source Link. + /// Only applicable for IP Receptions. + /// Will be saved in a custom property. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string VidigoStreamSourceLink + { + get; + set; + } + + /// + /// Additional information about the desired source that should be selected whenever they want to book an order definitively. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string AdditionalDescriptionUnknownSource + { + get; + set; + } + + /// + /// Indicates if a source service is unknown. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool IsUnknownSourceService + { + get; + set; + } + + /// + /// Indicates if the audio configuration is copied from source. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool IsAudioConfigurationCopiedFromSource + { + get; + set; + } + + /// + /// Indicates if this service requires routing. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool RequiresRouting + { + get; + set; + } + + /// + /// Indicates if routing config should be updated whenever applicable. + /// + public bool RoutingConfigurationUpdateRequired + { + get; + set; + } + + /// + /// The recording configuration with additional recording details that are not stored as profile parameters. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.RecordingConfiguration RecordingConfiguration + { + get; + set; + } + + public System.Collections.Generic.HashSet SecurityViewIds + { + get; + set; + } + + /// + /// Indicates if this service requires routing. + /// + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public System.Collections.Generic.HashSet OrderReferences + { + get; + set; + } + + [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string NameOfServiceToTransmit + { + get; + set; + } + + public bool ChangedByUpdateServiceScript + { + get; + set; + } + + = false; + } + } + } + + namespace ServiceDefinition + { + public class ContributingConfig + { + public string ParentSystemFunction + { + get; + set; + } + + public string ResourcePool + { + get; + set; + } + + /// + /// The appendix name for the contributed resources created for each service + /// Only required when action is "NEW" or "EDIT" and only for a service (not for the order itself) (can be found in Contributing Config property of SD) + /// + public string ReservationAppendixName + { + get; + set; + } + + public string LifeCycle + { + get; + set; + } + + public bool ConvertToContributing + { + get; + set; + } + } + + public enum VirtualPlatform + { + [System.ComponentModel.Description("None")] + None, + [System.ComponentModel.Description("Reception.Satellite")] + ReceptionSatellite, + [System.ComponentModel.Description("Reception.LiveU")] + ReceptionLiveU, + [System.ComponentModel.Description("Reception.Fiber")] + ReceptionFiber, + [System.ComponentModel.Description("Reception.Fixed Line")] + ReceptionFixedLine, + [System.ComponentModel.Description("Reception.Fixed Service")] + ReceptionFixedService, + [System.ComponentModel.Description("Reception.IP")] + ReceptionIp, + [System.ComponentModel.Description("Reception.Microwave")] + ReceptionMicrowave, + [System.ComponentModel.Description("Reception.Eurovision")] + ReceptionEurovision, + [System.ComponentModel.Description("Reception.Unknown")] + ReceptionUnknown, + [System.ComponentModel.Description("Reception.Commentary Audio")] + ReceptionCommentaryAudio, + [System.ComponentModel.Description("Recording")] + Recording, + [System.ComponentModel.Description("Routing")] + Routing, + [System.ComponentModel.Description("Destination")] + Destination, + [System.ComponentModel.Description("Audio Processing")] + AudioProcessing, + [System.ComponentModel.Description("Video Processing")] + VideoProcessing, + [System.ComponentModel.Description("Graphics Processing")] + GraphicsProcessing, + [System.ComponentModel.Description("Transmission.Satellite")] + TransmissionSatellite, + [System.ComponentModel.Description("Transmission.LiveU")] + TransmissionLiveU, + [System.ComponentModel.Description("Transmission.Fiber")] + TransmissionFiber, + [System.ComponentModel.Description("Transmission.IP")] + TransmissionIp, + [System.ComponentModel.Description("Transmission.Microwave")] + TransmissionMicrowave, + [System.ComponentModel.Description("Transmission.Eurovision")] + TransmissionEurovision, + // TODO: is this still being used? + [System.ComponentModel.Description("File Playout")] + FilePlayout, + [System.ComponentModel.Description("File Processing")] + FileProcessing + } + + public enum VirtualPlatformType + { + [System.ComponentModel.Description("None")] + None, + [System.ComponentModel.Description("Reception")] + Reception, + [System.ComponentModel.Description("Recording")] + Recording, + [System.ComponentModel.Description("Destination")] + Destination, + [System.ComponentModel.Description("Routing")] + Routing, + [System.ComponentModel.Description("Transmission")] + Transmission, + [System.ComponentModel.Description("Audio Processing")] + AudioProcessing, + [System.ComponentModel.Description("Video Processing")] + VideoProcessing, + [System.ComponentModel.Description("Graphics Processing")] + GraphicsProcessing + } + + public enum VirtualPlatformName + { + [System.ComponentModel.Description("None")] + None, + [System.ComponentModel.Description("Satellite")] + Satellite, + [System.ComponentModel.Description("LiveU")] + LiveU, + [System.ComponentModel.Description("Fiber")] + Fiber, + [System.ComponentModel.Description("Fixed Line")] + FixedLine, + [System.ComponentModel.Description("Fixed Service")] + FixedService, + [System.ComponentModel.Description("IP")] + IP, + [System.ComponentModel.Description("Microwave")] + Microwave, + [System.ComponentModel.Description("Eurovision")] + Eurovision, + [System.ComponentModel.Description("Unknown")] + Unknown, + [System.ComponentModel.Description("Recording")] + Recording, + [System.ComponentModel.Description("Destination")] + Destination, + [System.ComponentModel.Description("Routing")] + Routing, + [System.ComponentModel.Description("Audio Processing")] + AudioProcessing, + [System.ComponentModel.Description("Video Processing")] + VideoProcessing, + [System.ComponentModel.Description("Graphics Processing")] + GraphicsProcessing, + [System.ComponentModel.Description("Commentary Audio")] + CommentaryAudio + } + + public static class GraphExtensions + { + /// + /// Gets the 0-based position of the function in the (straight-line) service definition. + /// + /// The NodeId of a function does not always correspond to the position of the function in the service definition, hence this method. + public static int GetFunctionPosition(this Skyline.DataMiner.Net.ServiceManager.Objects.Graph graph, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function function) + { + bool nodeExistsWithMoreThanTwoEdges = System.Linq.Enumerable.Any(graph.Nodes, n => System.Linq.Enumerable.Count(graph.Edges, e => e.ToNode.Equals(n) || e.FromNode.Equals(n)) > 2); + if (nodeExistsWithMoreThanTwoEdges) + throw new System.ArgumentException("Graph is not a straight line", nameof(graph)); + Skyline.DataMiner.Net.ServiceManager.Objects.Node nodeOfFunction = System.Linq.Enumerable.FirstOrDefault(graph.Nodes, n => n.Configuration.FunctionID == function.Id); + if (nodeOfFunction == null) + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.NodeNotFoundException(function.Id); + int position = 0; + Skyline.DataMiner.Net.ServiceManager.Objects.Node node = nodeOfFunction; + while (System.Linq.Enumerable.Any(graph.Edges, e => e.ToNode == node)) + { + Skyline.DataMiner.Net.ServiceManager.Objects.Edge edge = System.Linq.Enumerable.FirstOrDefault(graph.Edges, e => e.ToNode == node); + if (node == null) + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.EdgeNotFoundException(); + if (edge.FromNode != null) + { + node = edge.FromNode; + } + else + { + break; + } + + position++; + } + + return position; + } + } + + public interface IServiceDefinitionManager + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition RoutingServiceDefinition + { + get; + } + + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition AudioProcessingServiceDefinition + { + get; + } + + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition GraphicsProcessingServiceDefinition + { + get; + } + + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition VideoProcessingServiceDefinition + { + get; + } + + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition GetServiceDefinition(System.Guid serviceDefinitionGuid); + Skyline.DataMiner.Automation.Element GetBookingManager(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform virtualPlatform); + } + + public class ServiceDefinition + { + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform virtualPlatform; + public ServiceDefinition() + { + } + + public ServiceDefinition(string virtualPlatform) + { + if (!System.Linq.Enumerable.Contains(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumDescriptions(), virtualPlatform)) + throw new System.ArgumentException(System.String.Format("Unknown Virtual Platform {0}", virtualPlatform), "virtualPlatform"); + this.virtualPlatform = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumValueFromDescription(virtualPlatform); + } + + public ServiceDefinition(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform virtualPlatform) + { + this.virtualPlatform = virtualPlatform; + } + + /// + /// The id (GUID) of the service definition + /// Only required when action is "NEW" or "EDIT" + /// + public System.Guid Id + { + get; + set; + } + + public string Name + { + get; + set; + } + + public string Description + { + get; + set; + } + + public bool IsDefault + { + get; + set; + } + + /// + /// Indicates if an order with a service using this service definition only allows a source (no destinations can be added). + /// + public bool IsSourceOnly + { + get; + set; + } + + /// + /// Indicates if this service definition can only be selected by MCR users. + /// + public bool IsMcrOnly + { + get; + set; + } + + /// + /// Indicates if this service definition can only be used by integration orders. + /// + public bool IsIntegrationOnly + { + get; + set; + } + + /// + /// The booking manager element name that will be used for the order bookings + /// Always required + /// + public string BookingManagerElementName + { + get; + set; + } + + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ContributingConfig ContributingConfig + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform VirtualPlatform + { + get + { + return virtualPlatform; + } + } + + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType VirtualPlatformServiceType + { + get + { + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumValueFromDescription(System.Linq.Enumerable.First(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(virtualPlatform).Split('.'))); + } + } + + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformName VirtualPlatformServiceName + { + get + { + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumValueFromDescription(System.Linq.Enumerable.Last(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(virtualPlatform).Split('.'))); + } + } + + [Newtonsoft.Json.JsonIgnore] + public System.Collections.Generic.IEnumerable FunctionDefinitions + { + get; + set; + } + + [Newtonsoft.Json.JsonIgnore] + public Skyline.DataMiner.Net.ServiceManager.Objects.Graph Diagram + { + get; + set; + } + + [Newtonsoft.Json.JsonIgnore] + public bool IsDummy + { + get + { + return VirtualPlatformServiceName == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformName.None; + } + } + + public static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition GenerateDummyReceptionServiceDefinition() + { + return new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.None) + {Name = "Dummy Reception", Id = System.Guid.Empty, ContributingConfig = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ContributingConfig{ParentSystemFunction = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager.SourceServiceSystemFunctionId, ResourcePool = "Reception"}, FunctionDefinitions = new System.Collections.Generic.List(), IsDefault = true, IsSourceOnly = false, IsMcrOnly = false, IsIntegrationOnly = false}; + } + + public static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition GenerateDummyUnknownReceptionServiceDefinition() + { + return new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionUnknown) + {Name = "Unknown Reception", Id = System.Guid.Empty, ContributingConfig = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ContributingConfig{ParentSystemFunction = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager.SourceServiceSystemFunctionId, ResourcePool = "Reception"}, FunctionDefinitions = new System.Collections.Generic.List(), IsDefault = true, IsSourceOnly = false, IsMcrOnly = false, IsIntegrationOnly = false}; + } + + public static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition GenerateEurovisionReceptionServiceDefinition() + { + return new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.ReceptionEurovision) + {Name = "Eurovision Reception", Id = System.Guid.Empty, ContributingConfig = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ContributingConfig{ParentSystemFunction = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager.SourceServiceSystemFunctionId, ResourcePool = "Reception"}, FunctionDefinitions = new System.Collections.Generic.List(), IsDefault = true, IsSourceOnly = false, IsMcrOnly = false, IsIntegrationOnly = false}; + } + + public static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition GenerateEurovisionTransmissionServiceDefinition() + { + return new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform.TransmissionEurovision) + {Name = "Eurovision Transmission", Id = System.Guid.Empty, ContributingConfig = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ContributingConfig{ParentSystemFunction = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager.TransmissionServiceSystemFunctionId, ResourcePool = "Transmission"}, FunctionDefinitions = new System.Collections.Generic.List(), IsDefault = true, IsSourceOnly = false, IsMcrOnly = false, IsIntegrationOnly = false}; + } + + public override string ToString() + { + if (Diagram == null) + return "Diagram is null"; + var sb = new System.Text.StringBuilder(); + foreach (var node in Diagram.Nodes) + { + var parentEdge = System.Linq.Enumerable.SingleOrDefault(Diagram.Edges, e => e.ToNode.ID == node.ID); + var parentNode = parentEdge != null ? parentEdge.FromNode.ToString() : string.Empty; + var childEdges = System.Linq.Enumerable.Where(Diagram.Edges, e => e.FromNode.ID == node.ID); + var childNodes = string.Join(",", System.Linq.Enumerable.Select(childEdges, e => e.ToNode.ID)); + var nodeInfo = $"Node {node.ID} (parent ={parentNode}, children={childNodes})"; + sb.Append($"{nodeInfo} ; "); + } + + return sb.ToString(); + } + + public override bool Equals(object obj) + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition other = obj as Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition; + if (other == null) + return false; + return Id.Equals(other.Id); + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } + + public bool FunctionIsFirst(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.Function function) + { + return Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.GraphExtensions.GetFunctionPosition(Diagram, function) == 0; + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Newtonsoft.Json.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Skyline.DataMiner.Storage.Types.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLNetTypes.dll")] + public class ServiceDefinitionManager : Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.IServiceDefinitionManager + { + private const string IsDefaultPropertyName = "IsDefault"; + private const string IsSourceOnlyPropertyName = "IsSourceOnly"; + private const string IsMcrOnlyPropertyName = "IsMcrOnly"; + private const string IsIntegrationOnlyPropertyName = "IsIntegrationOnly"; + private const string VirtualPlatformPropertyName = "Virtual Platform"; + private const string ContributiongConfigPropertyName = "Contributing Config"; + private const string BookingManagerProtocolName = "Skyline Booking Manager"; + private const int BookingManagerProtocolVirtualPlatformParameterId = 123; + // cached to improve performance (don't use these fields, use the properties) + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition routingServiceDefinition; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition graphicsProcessingServiceDefinition; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition videoProcessingServiceDefinition; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition audioProcessingServiceDefinition; + private System.Collections.Generic.List allNonOrderSrmServiceDefinitions; + private System.Collections.Generic.IEnumerable allProtocolFunctionDefinitions; // initialized by some methods to improve performance + public ServiceDefinitionManager(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers helpers) + { + Helpers = helpers ?? throw new System.ArgumentNullException(nameof(helpers)); + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers Helpers + { + get; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition RoutingServiceDefinition => routingServiceDefinition ?? (routingServiceDefinition = GetServiceDefinition("Routing")); + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition GraphicsProcessingServiceDefinition => graphicsProcessingServiceDefinition ?? (graphicsProcessingServiceDefinition = GetServiceDefinition("Graphics Processing")); + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition VideoProcessingServiceDefinition => videoProcessingServiceDefinition ?? (videoProcessingServiceDefinition = GetServiceDefinition("Video Processing")); + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition AudioProcessingServiceDefinition => audioProcessingServiceDefinition ?? (audioProcessingServiceDefinition = GetServiceDefinition("Audio Processing")); + private System.Collections.Generic.List AllNonOrderSrmServiceDefinitions => allNonOrderSrmServiceDefinitions ?? (allNonOrderSrmServiceDefinitions = GetAllNonOrderSrmServiceDefinitions()); + private System.Collections.Generic.IEnumerable AllProtocolFunctionDefinitions => allProtocolFunctionDefinitions ?? (allProtocolFunctionDefinitions = GetAllProtocolFunctionDefinitions()); + /// ONLY TO BE USED FOR NON-ORDER SERVICE DEFINITIONS + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition GetServiceDefinition(System.Guid serviceDefinitionGuid) + { + try + { + LogMethodStart(nameof(GetServiceDefinition), out var stopwatch); + var srmServiceDefinition = System.Linq.Enumerable.SingleOrDefault(AllNonOrderSrmServiceDefinitions, sd => sd.ID == serviceDefinitionGuid); + if (srmServiceDefinition == null) + throw new Skyline.DataMiner.Library.Exceptions.ServiceDefinitionNotFoundException(serviceDefinitionGuid); + var virtualPlatformProperty = System.Linq.Enumerable.FirstOrDefault(srmServiceDefinition.Properties, p => System.String.Equals(p.Name, VirtualPlatformPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + string virtualPlatformName = virtualPlatformProperty.Value; + var contributingConfig = GetContributingConfig(srmServiceDefinition); + if (contributingConfig == null) + { + // Service Definition should always contain a Contributing Config + return null; + } + + var serviceDefinition = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition(virtualPlatformName) + {Id = srmServiceDefinition.ID, Name = srmServiceDefinition.Name, Description = srmServiceDefinition.Description ?? string.Empty, BookingManagerElementName = GetBookingManagerElementName(srmServiceDefinition), ContributingConfig = contributingConfig, FunctionDefinitions = GetFunctionDefinitions(srmServiceDefinition), Diagram = srmServiceDefinition.Diagram, IsDefault = IsDefault(srmServiceDefinition), IsSourceOnly = IsSourceOnly(srmServiceDefinition), IsMcrOnly = IsMcrOnly(srmServiceDefinition), IsIntegrationOnly = IsIntegrationOnly(srmServiceDefinition)}; + LogMethodCompleted(nameof(GetServiceDefinition), stopwatch); + return serviceDefinition; + } + catch (System.Exception e) + { + Log(nameof(GetServiceDefinition), $"Something went wrong while getting service definition {serviceDefinitionGuid}: {e}"); + return null; + } + } + + public Skyline.DataMiner.Automation.Element GetBookingManager(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatform virtualPlatform) + { + var bookingManagers = Helpers.Engine.FindElementsByProtocol(BookingManagerProtocolName); + var bookingManager = System.Linq.Enumerable.FirstOrDefault(bookingManagers, b => b != null && b.IsActive && System.Convert.ToString(b.GetParameter(BookingManagerProtocolVirtualPlatformParameterId)).Equals(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(virtualPlatform))); + return bookingManager; + } + + private bool IsDefault(Skyline.DataMiner.Net.ServiceManager.Objects.ServiceDefinition srmServiceDefinition) + { + var isDefaultProperty = System.Linq.Enumerable.FirstOrDefault(srmServiceDefinition.Properties, p => System.String.Equals(p.Name, IsDefaultPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + return isDefaultProperty != null && System.Convert.ToBoolean(isDefaultProperty.Value); + } + + private bool IsSourceOnly(Skyline.DataMiner.Net.ServiceManager.Objects.ServiceDefinition srmServiceDefinition) + { + var isSourceOnlyProperty = System.Linq.Enumerable.FirstOrDefault(srmServiceDefinition.Properties, p => System.String.Equals(p.Name, IsSourceOnlyPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + return isSourceOnlyProperty != null && System.Convert.ToBoolean(isSourceOnlyProperty.Value); + } + + private bool IsMcrOnly(Skyline.DataMiner.Net.ServiceManager.Objects.ServiceDefinition srmServiceDefinition) + { + var isMcrOnlyProperty = System.Linq.Enumerable.FirstOrDefault(srmServiceDefinition.Properties, p => System.String.Equals(p.Name, IsMcrOnlyPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + return isMcrOnlyProperty != null && System.Convert.ToBoolean(isMcrOnlyProperty.Value); + } + + private bool IsIntegrationOnly(Skyline.DataMiner.Net.ServiceManager.Objects.ServiceDefinition srmServiceDefinition) + { + var isIntegrationOnlyProperty = System.Linq.Enumerable.FirstOrDefault(srmServiceDefinition.Properties, p => System.String.Equals(p.Name, IsIntegrationOnlyPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + return isIntegrationOnlyProperty != null && System.Convert.ToBoolean(isIntegrationOnlyProperty.Value); + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition GetServiceDefinition(string nameFilter) + { + foreach (var srmServiceDefinition in AllNonOrderSrmServiceDefinitions) + { + if (!srmServiceDefinition.Name.Contains(nameFilter) || srmServiceDefinition.Properties == null) + continue; + var virtualPlatformProperty = System.Linq.Enumerable.FirstOrDefault(srmServiceDefinition.Properties, p => System.String.Equals(p.Name, VirtualPlatformPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + if (virtualPlatformProperty == null || System.String.IsNullOrWhiteSpace(virtualPlatformProperty.Value)) + continue; + string virtualPlatformName = virtualPlatformProperty.Value; + var contributingConfig = GetContributingConfig(srmServiceDefinition); + if (contributingConfig == null) + continue; + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition serviceDefinition = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinition(virtualPlatformName) + {Id = srmServiceDefinition.ID, Name = srmServiceDefinition.Name, Description = srmServiceDefinition.Description, BookingManagerElementName = GetBookingManagerElementName(srmServiceDefinition), ContributingConfig = contributingConfig, FunctionDefinitions = GetFunctionDefinitions(srmServiceDefinition), Diagram = srmServiceDefinition.Diagram, IsDefault = IsDefault(srmServiceDefinition), IsSourceOnly = IsSourceOnly(srmServiceDefinition), IsMcrOnly = IsMcrOnly(srmServiceDefinition), IsIntegrationOnly = IsIntegrationOnly(srmServiceDefinition)}; + return serviceDefinition; + } + + return null; + } + + /// + /// Retrieve the function definitions for a given service definition. + /// + /// The service definition. + /// Returns the function definitions for each function in the service definition in the order as they should be configured. + private System.Collections.Generic.IEnumerable GetFunctionDefinitions(Skyline.DataMiner.Net.ServiceManager.Objects.ServiceDefinition serviceDefinition) + { + var functionDefinitions = new System.Collections.Generic.List(); + var nodes = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where(serviceDefinition.Diagram.Nodes, x => !System.Linq.Enumerable.Any(serviceDefinition.Diagram.Edges, y => y.ToNodeID == x.ID))); + while (System.Linq.Enumerable.Any(nodes)) + { + var childNodes = new System.Collections.Generic.List(); + foreach (var node in nodes) + { + int order = -1; + string options = System.String.Empty; + string resourcePool = System.String.Empty; + bool isManualResourceSelectionAllowed = false; + bool isHidden = false; + foreach (var property in node.Properties) + { + switch (property.Name) + { + case "ConfigurationOrder": + if (System.Int32.TryParse(property.Value, out var configurationOrder)) + order = configurationOrder; + break; + case "Options": + options = property.Value; + break; + case "Resource Pool": + resourcePool = property.Value; + break; + case "IsManualResourceSelectionAllowed": + isManualResourceSelectionAllowed = !System.String.IsNullOrEmpty(property.Value) && System.Convert.ToBoolean(property.Value); + break; + case "IsHidden": + isHidden = !System.String.IsNullOrEmpty(property.Value) && System.Convert.ToBoolean(property.Value); + break; + default: + break; + } + } + + functionDefinitions.Add(GetFunctionDefinition(node.Configuration.FunctionID, node.Label, order, options, resourcePool, isManualResourceSelectionAllowed, isHidden)); + childNodes.AddRange(System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(serviceDefinition.Diagram.Edges, x => x.FromNodeID == node.ID), x => x.ToNode)); + } + + // this is used to make sure the function definitions are ordered the same as the nodes in the SD + nodes.Clear(); + nodes.AddRange(childNodes); + } + + return functionDefinitions; + } + + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.FunctionDefinition GetFunctionDefinition(System.Guid functionId, string label, int order, string options, string resourcePool, bool isManualResourceSelectionAllowed, bool isHidden) + { + var srmFunctionDefinition = System.Linq.Enumerable.SingleOrDefault(AllProtocolFunctionDefinitions, fd => fd.GUID == functionId); + if (srmFunctionDefinition == null) + throw new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.FunctionDefinitionNotFoundException(functionId); + var functionDefinition = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function.FunctionDefinition{Id = srmFunctionDefinition.GUID, Name = srmFunctionDefinition.Name, Label = label, ConfigurationOrder = order, Options = options, IsHidden = isHidden, ProfileDefinition = Helpers.ProfileManager.GetProfileDefinition(srmFunctionDefinition.ProfileDefinition), InterfaceProfileDefinitions = Helpers.ProfileManager.GetInterfaceProfileDefinitions(srmFunctionDefinition), ResourcePool = resourcePool, Children = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(AllProtocolFunctionDefinitions, fd => fd.ParentFunctionGUID == srmFunctionDefinition.GUID), fd => fd.GUID)), IsManualResourceSelectionAllowed = isManualResourceSelectionAllowed}; + return functionDefinition; + } + + private System.Collections.Generic.List GetAllProtocolFunctionDefinitions() + { + LogMethodStart(nameof(GetAllProtocolFunctionDefinitions), out var stopwatch); + var functionDefinitions = new System.Collections.Generic.List(); + var protocolFunctions = Helpers.ProtocolFunctionHelper.GetAllProtocolFunctions(); + foreach (var protocolFunction in protocolFunctions) + { + foreach (var protocolFunctionVersion in protocolFunction.ProtocolFunctionVersions) + { + if (!protocolFunctionVersion.Active) + continue; // only consider active function definitions + foreach (var functionDefinition in protocolFunctionVersion.FunctionDefinitions) + { + if (!System.Linq.Enumerable.Any(functionDefinitions, fd => fd.GUID.Equals(functionDefinition.GUID))) + { + functionDefinitions.Add(functionDefinition); + } + } + } + } + + Log(nameof(GetAllProtocolFunctionDefinitions), $"Retrieved {functionDefinitions.Count} protocol function definitions."); + LogMethodCompleted(nameof(GetAllProtocolFunctionDefinitions), stopwatch); + return functionDefinitions; + } + + private string GetBookingManagerElementName(Skyline.DataMiner.Net.ServiceManager.Objects.ServiceDefinition serviceDefinition) + { + var virtualPlatformProperty = System.Linq.Enumerable.FirstOrDefault(serviceDefinition.Properties, p => p.Name == "Virtual Platform"); + if (virtualPlatformProperty == null) + { + // TODO: check to use custom exceptions + throw new System.Exception(System.String.Format("ServiceDefinition with ID {0} does not contain a Virtual Platform property", serviceDefinition.ID)); + } + + var bookingManager = GetBookingManager(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumValueFromDescription(virtualPlatformProperty.Value)); + return bookingManager?.ElementName; + } + + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ContributingConfig GetContributingConfig(Skyline.DataMiner.Net.ServiceManager.Objects.ServiceDefinition serviceDefinition) + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ContributingConfig contributingConfig = null; + try + { + var contributingConfigProperty = System.Linq.Enumerable.FirstOrDefault(serviceDefinition.Properties, p => System.String.Equals(p.Name, ContributiongConfigPropertyName, System.StringComparison.InvariantCultureIgnoreCase)); + contributingConfig = Newtonsoft.Json.JsonConvert.DeserializeObject(contributingConfigProperty.Value); + } + catch (System.Exception) + { + } + + return contributingConfig; + } + + private void Log(string nameOfMethod, string message, string nameOfObject = null) + { + Helpers.Log(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinitionManager), nameOfMethod, message, nameOfObject); + } + + protected void LogMethodStart(string nameOfMethod, out System.Diagnostics.Stopwatch stopwatch) + { + Log(nameOfMethod, "Start"); + stopwatch = System.Diagnostics.Stopwatch.StartNew(); + } + + protected void LogMethodCompleted(string nameOfMethod, System.Diagnostics.Stopwatch stopwatch = null) + { + stopwatch?.Stop(); + Log(nameOfMethod, $"Completed [{stopwatch?.Elapsed}]"); + } + + private System.Collections.Generic.List GetAllNonOrderSrmServiceDefinitions() + { + LogMethodStart(nameof(GetAllNonOrderSrmServiceDefinitions), out var stopwatch); + var result = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where(Helpers.ServiceManagerHelper.GetServiceDefinitions(Skyline.DataMiner.Net.Messages.SLDataGateway.ExposerExtensions.NotEqual(Skyline.DataMiner.Net.Messages.SLDataGateway.ReflectiveExposer.DictStringField(Skyline.DataMiner.Net.ServiceManager.Objects.ServiceDefinitionExposers.Properties, "Virtual Platform"), "Order")), sd => sd.Name.StartsWith("_"))); + Log(nameof(GetAllNonOrderSrmServiceDefinitions), $"Retrieved {result.Count} Service Definitions"); + LogMethodCompleted(nameof(GetAllNonOrderSrmServiceDefinitions), stopwatch); + return result; + } + } + } + + namespace Ticketing + { + [Skyline.DataMiner.Library.Common.Attributes.DllImport("Skyline.DataMiner.Storage.Types.dll")] + public class TicketingManager + { + public const string ServiceIdTicketFieldName = "Service ID"; + public const string DeadLineTicketFieldName = "Deadline"; + private readonly Skyline.DataMiner.Automation.IEngine engine; + private readonly Skyline.DataMiner.Net.Ticketing.TicketingGatewayHelper ticketingHelper; + private readonly Skyline.DataMiner.Net.Ticketing.Helpers.TicketFieldResolver ticketFieldResolver; + public TicketingManager(Skyline.DataMiner.Automation.IEngine engine, string domain) + { + this.engine = engine; + ticketingHelper = new Skyline.DataMiner.Net.Ticketing.TicketingGatewayHelper{HandleEventsAsync = false}; + ticketingHelper.RequestResponseEvent += (sender, args) => args.responseMessage = Skyline.DataMiner.Automation.Engine.SLNet.SendSingleResponseMessage(args.requestMessage); + ticketFieldResolver = System.Linq.Enumerable.FirstOrDefault(ticketingHelper.GetTicketFieldResolvers(Skyline.DataMiner.Net.Ticketing.Helpers.TicketFieldResolver.Factory.CreateEmptyResolver(domain))); + } + + public Skyline.DataMiner.Net.Ticketing.Helpers.TicketFieldResolver TicketFieldResolver + { + get + { + return ticketFieldResolver; + } + } + + public System.Collections.Generic.IEnumerable GetTicketsForService(System.Guid serviceId) + { + // This is the preferred way of retrieving the ticket, but didn't work because of a bug in Software + // return ticketingHelper.GetTickets(new[] { TicketLink.Create(new ReservationInstanceID(serviceId)) }); + return ticketingHelper.GetTickets(filter: Skyline.DataMiner.Net.Messages.SLDataGateway.ExposerExtensions.Equal(Skyline.DataMiner.Net.Messages.SLDataGateway.ReflectiveExposer.DictStringField(Skyline.DataMiner.Net.Ticketing.TicketingExposers.CustomTicketFields, ServiceIdTicketFieldName), serviceId.ToString())); + } + } + } + + namespace UI + { + public class ValidationInfo + { + public ValidationInfo() + { + State = Skyline.DataMiner.Automation.UIValidationState.NotValidated; + Text = System.String.Empty; + } + + public Skyline.DataMiner.Automation.UIValidationState State + { + get; + set; + } + + public string Text + { + get; + set; + } + + public bool IsValid + { + get + { + return State != Skyline.DataMiner.Automation.UIValidationState.Invalid; + } + } + } + } + + namespace UserTasks + { + public static class Descriptions + { + public static class Dummy + { + public const string SelectTechnicalSystem = "Select Technical System from EBU Synopsis"; + } + + public static class FiberReception + { + public const string AllocationNeeded = "Fiber Allocation Needed"; + public const string EquipmentAllocation = "Fiber Equipment Allocation Needed + Configuration"; + } + + public static class FiberTransmission + { + public const string Configure = "Configure Ad Hoc Fiber return feed"; + } + + public static class MicrowaveReception + { + public const string EquipmentAllocation = "Microwave Equipment Allocation Needed"; + public const string EquipmentConfiguration = "Microwave Equipment Installation + Configuration Needed"; + } + + public static class MicrowaveTransmission + { + public const string Configure = "Configure Microwave Return Channel"; + } + + public static class SatelliteReception + { + public const string SelectAntenna = "Select Steerable Antenna"; + public const string SpaceNeeded = "Satellite Space Needed"; + public const string SteerAntenna = "Steer Steerable Antenna to Correct Satellite"; + public const string ConfigureNs3 = "Configure NS3 Demodulator"; + public const string ConfigureNs4 = "Configure NS4 Demodulator"; + public const string ConfigureIrd = "Configure IRD"; + public const string VerifySatellite = "Verify Satellite"; + } + } + + public enum UserTaskSource + { + LiveService, + NonLiveOrder + } + + public enum UserTaskStatus + { + Incomplete = 1, + Complete = 2 + } + + public enum UserGroup + { + [System.ComponentModel.Description("Booking Office")] + BookingOffice = 1, + [System.ComponentModel.Description("MCR Operator")] + McrOperator = 2, + [System.ComponentModel.Description("Fiber Specialist")] + FiberSpecialist = 3, + [System.ComponentModel.Description("MW Specialist")] + MwSpecialist = 4, + [System.ComponentModel.Description("Media Operator")] + MediaOperator = 5, + [System.ComponentModel.Description("Audio MCR Operator")] + AudioMcrOperator = 6, + [System.ComponentModel.Description("Messi Specific User Group")] + MessiSpecific = 7, + [System.ComponentModel.Description("Mediamylly Specific User Group")] + MediamyllySpecific = 8, + [System.ComponentModel.Description("Mediaputiikki Specific User Group")] + MediaputiikkiSpecific = 9, + [System.ComponentModel.Description("UA Specific User Group")] + UaSpecific = 10 + } + + public class UserTask + { + public const string TicketFieldDescription = "Description"; + public const string TicketFieldState = "State"; + private const string TicketFieldName = "Name"; + private const string TicketFieldUserGroup = "User Group"; + private const string TicketFieldServiceId = "Service ID"; + private const string TicketFieldIngestExportFK = "Ingest Export FK"; + private const string TicketFieldOwner = "Owner"; + private readonly Skyline.DataMiner.Automation.IEngine engine; + private readonly System.Guid ticketFieldResolverId; + private Skyline.DataMiner.Net.Ticketing.Ticket ticket; + /// + /// Constructor used to create a service-based user task from scratch. + /// + public UserTask(Skyline.DataMiner.Automation.IEngine engine, System.Guid ticketFieldResolverId, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, string description, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserGroup userGroup, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus.Incomplete) + { + this.engine = engine; + this.ticketFieldResolverId = ticketFieldResolverId; + UserTaskSource = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskSource.LiveService; + ServiceId = service.Id; + Status = status; + Description = description; + UserGroup = userGroup; + Service = service; + //Service.UserTasks = new[] { this }.Concat(Service.UserTasks.Where(x => !x.Name.Equals(this.Name))).ToList(); // replacing the existing User Task instance with this instance + ServiceStartTime = Service.Start; + Name = GenerateName(Service, description); + } + + /// + /// Constructor used to create a service-based user task from a ticket. + /// + public UserTask(Skyline.DataMiner.Automation.IEngine engine, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, Skyline.DataMiner.Net.Ticketing.Ticket ticket) + { + this.engine = engine; + this.ticket = ticket; + UserTaskSource = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskSource.LiveService; + ID = ticket.ID.ToString(); + ServiceId = System.Guid.Parse(System.Convert.ToString(ticket.CustomTicketFields[TicketFieldServiceId])); + Name = System.Convert.ToString(ticket.CustomTicketFields[TicketFieldName]); + Description = System.Convert.ToString(ticket.CustomTicketFields[TicketFieldDescription]); + UserGroup = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumValueFromDescription(System.Convert.ToString(ticket.CustomTicketFields[TicketFieldUserGroup])); + ticket.CustomTicketFields.TryGetValue(TicketFieldOwner, out var owner); + Owner = System.Convert.ToString(owner); + var statusTicketField = ticket.GetTicketField(TicketFieldState) as Skyline.DataMiner.Net.Ticketing.Validators.GenericEnumEntry; + if (statusTicketField != null) + Status = (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus)statusTicketField.Value; + Service = service; + //Service.UserTasks = new[] { this }.Concat(Service.UserTasks.Where(x => !x.Name.Equals(this.Name))).ToList(); // replacing the existing User Task instance with this instance + ServiceStartTime = service.Start; + } + + /// + /// Constructor used to make a user task from scratch for a Non-Live Transfer order. + /// + public UserTask(Skyline.DataMiner.Automation.IEngine engine, System.Guid ticketFieldResolverId, string ingestExportForeignKey, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus status, string name, string description, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserGroup userGroup) + { + this.engine = engine; + this.ticketFieldResolverId = ticketFieldResolverId; + UserTaskSource = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskSource.NonLiveOrder; + IngestExportForeignKey = ingestExportForeignKey; + Status = status; + Name = name; + Description = description; + UserGroup = userGroup; + } + + /// + /// Constructor used to make a user task from a ticket for a Non-Live Transfer order. + /// + public UserTask(Skyline.DataMiner.Automation.IEngine engine, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.Transfer.Transfer transfer, Skyline.DataMiner.Net.Ticketing.Ticket ticket) + { + this.engine = engine; + this.ticket = ticket; + UserTaskSource = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskSource.NonLiveOrder; + ID = ticket.ID.ToString(); + IngestExportForeignKey = System.Convert.ToString(ticket.CustomTicketFields[TicketFieldIngestExportFK]); + Name = System.Convert.ToString(ticket.CustomTicketFields[TicketFieldName]); + Description = System.Convert.ToString(ticket.CustomTicketFields[TicketFieldDescription]); + UserGroup = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumValueFromDescription(System.Convert.ToString(ticket.CustomTicketFields[TicketFieldUserGroup])); + ticket.CustomTicketFields.TryGetValue(TicketFieldOwner, out var owner); + Owner = System.Convert.ToString(owner); + var statusTicketField = ticket.GetTicketField(TicketFieldState) as Skyline.DataMiner.Net.Ticketing.Validators.GenericEnumEntry; + if (statusTicketField != null) + Status = (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus)statusTicketField.Value; + } + + public UserTask(Skyline.DataMiner.Automation.IEngine engine, Skyline.DataMiner.Net.Ticketing.Ticket ticket) + { + this.engine = engine; + this.ticket = ticket; + ID = ticket.ID.ToString(); + Name = System.Convert.ToString(ticket.CustomTicketFields[TicketFieldName]); + Description = System.Convert.ToString(ticket.CustomTicketFields[TicketFieldDescription]); + UserGroup = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetEnumValueFromDescription(System.Convert.ToString(ticket.CustomTicketFields[TicketFieldUserGroup])); + if (ticket.CustomTicketFields.TryGetValue(TicketFieldOwner, out var owner)) + { + Owner = System.Convert.ToString(owner); + } + + var statusTicketField = ticket.GetTicketField(TicketFieldState) as Skyline.DataMiner.Net.Ticketing.Validators.GenericEnumEntry; + if (statusTicketField != null) + Status = (Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus)statusTicketField.Value; + if (ticket.CustomTicketFields.ContainsKey(TicketFieldServiceId)) + { + UserTaskSource = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskSource.LiveService; + ServiceId = System.Guid.Parse(System.Convert.ToString(ticket.CustomTicketFields[TicketFieldServiceId])); + var serviceManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager(new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.Helpers(engine)); + Service = serviceManager.GetService(ServiceId); + Service.UserTasks = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Concat(new[]{this}, System.Linq.Enumerable.Where(Service.UserTasks, x => !x.Name.Equals(this.Name)))); // replacing the existing User Task instance with this instance + ServiceStartTime = Service.Start; + } + else if (ticket.CustomTicketFields.ContainsKey(TicketFieldIngestExportFK)) + { + UserTaskSource = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskSource.NonLiveOrder; + IngestExportForeignKey = System.Convert.ToString(ticket.CustomTicketFields[TicketFieldIngestExportFK]); + } + } + + /// + /// The ID of the ticket in the ticketing domain. + /// Format: [dataminer ID]/[ticket ID] . + /// + public string ID + { + get; + private set; + } + + /// + /// Status of the User Task. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskStatus Status + { + get; + set; + } + + /// + /// ID of the Service this user task is linked to. + /// + public System.Guid ServiceId + { + get; + private set; + } + + /// + /// ID of the ingest/export ticket this user task is linked to. + /// + public string IngestExportForeignKey + { + get; + set; + } + + public string Name + { + get; + set; + } + + public string Owner + { + get; + set; + } + + public string Description + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserGroup UserGroup + { + get; + set; + } + + public System.DateTime ServiceStartTime + { + get; + private set; + } + + /// + /// Indicates whether the user task is made based on a live service or on a non-live order. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskSource UserTaskSource + { + get; + private set; + } + + /// + /// The Service object this User Task is linked to. + /// + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service Service + { + get; + private set; + } + + /// + /// Generates the correct name for the service-based user task. + /// + private string GenerateName(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, string description) + { + if (service.Definition.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Reception || service.Definition.VirtualPlatformServiceType == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.VirtualPlatformType.Transmission) + { + return System.String.Format("{0} {1}: {2}", Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EnumExtensions.GetDescriptionFromEnumValue(service.Definition.VirtualPlatformServiceName), service.Name, description); + } + else + { + return System.String.Format("{0}: {1}", service.Name, description); + } + } + } + + public class UserTaskManager + { + public const string TicketingDomain = "User Tasks"; + private readonly Skyline.DataMiner.Automation.IEngine engine; + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter; + public UserTaskManager(Skyline.DataMiner.Automation.IEngine engine, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter = null) + { + this.engine = engine; + this.progressReporter = progressReporter; + TicketingManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Ticketing.TicketingManager(engine, TicketingDomain); + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Ticketing.TicketingManager TicketingManager + { + get; + } + + /// + /// Get user tasks that are applicable for the given live service. + /// + public System.Collections.Generic.IEnumerable GetUserTasks(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service) + { + if (service == null) + throw new System.ArgumentNullException(nameof(service)); + LogMethodStarted(nameof(GetUserTasks), out var stopwatch, service.Name); + var tickets = TicketingManager.GetTicketsForService(service.Id); + var userTasks = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Select(tickets, x => new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTask(engine, service, x))); + Log(nameof(GetUserTasks), $"Retrieved following user tasks from database: {string.Join(";", System.Linq.Enumerable.Select(userTasks, u => $"{u.Name}({u.ID})={u.Status}"))}", service.Name); + LogMethodCompleted(nameof(GetUserTasks), service.Name, stopwatch); + return userTasks; + } + + private void Log(string nameOfMethod, string message, string nameOfObject = null) + { + progressReporter?.LogProgress(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskManager), nameOfMethod, message, nameOfObject); + } + + private void LogMethodStarted(string methodName, out System.Diagnostics.Stopwatch stopwatch, string objectName = null) + { + progressReporter?.LogMethodStart(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskManager), methodName, objectName); + stopwatch = new System.Diagnostics.Stopwatch(); + stopwatch.Start(); + } + + private void LogMethodCompleted(string methodName, string objectName = null, System.Diagnostics.Stopwatch stopwatch = null) + { + progressReporter?.LogMethodCompleted(nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskManager), methodName, objectName, stopwatch); + } + } + } + + namespace Utilities + { + public static class DateTimeExtensions + { + /// + /// Used to convert a DateTime from a reservationInstance to the correct Local Time. + /// + /// DateTime as retrieved from a reservation instance. + /// Local Time from reservation instance. + public static System.DateTime FromReservation(this System.DateTime dateTime) + { + return new System.DateTime(dateTime.Ticks, System.DateTimeKind.Utc).ToLocalTime(); + } + + /// + /// Used to convert a DateTime from a service configuration to the correct Local Time. + /// + /// DateTime as retrieved from a service configuration. + /// Local Time from service configuration. + public static System.DateTime FromServiceConfiguration(this System.DateTime dateTime) + { + return new System.DateTime(dateTime.Ticks, System.DateTimeKind.Utc).ToLocalTime(); + } + + /// + /// Truncate to the nearest whole value of given + /// + public static System.DateTime Truncate(this System.DateTime dt, System.TimeSpan timeSpan) + { + if (timeSpan == System.TimeSpan.Zero) + return dt; + return dt.AddTicks(-(dt.Ticks % timeSpan.Ticks)); + } + } + + public static class EngineExtensions + { + /// + /// Logs to SLAutomation using the following template: ||| + /// + public static void Log(this Skyline.DataMiner.Automation.IEngine engine, string nameOfClass, string nameOfMethod, string message, string nameOfOrderOrService = null) + { + var sb = new System.Text.StringBuilder(); + sb.Append(nameOfClass); + sb.Append("|"); + sb.Append(nameOfMethod); + sb.Append("|"); + if (!string.IsNullOrEmpty(nameOfOrderOrService)) + { + sb.Append(nameOfOrderOrService); + sb.Append("|"); + } + + sb.Append(message); + engine.Log(sb.ToString()); + } + } + + public static class EnumExtensions + { + public static string GetDescription(this System.Enum value) + { + return GetDescriptionFromEnumValue(value); + } + + public static string GetDescriptionFromEnumValue(System.Enum value) + { + System.ComponentModel.DescriptionAttribute attribute = System.Linq.Enumerable.SingleOrDefault(value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false)) as System.ComponentModel.DescriptionAttribute; + return attribute == null ? value.ToString() : attribute.Description; + } + + public static T GetEnumValueFromDescription(string description) + { + var type = typeof(T); + if (!type.IsEnum) + throw new System.ArgumentException(); + System.Reflection.FieldInfo[] fields = type.GetFields(); + var field = System.Linq.Enumerable.SingleOrDefault(System.Linq.Enumerable.SelectMany(fields, f => f.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false), (f, a) => new + { + Field = f, Att = a + } + + ), a => ((System.ComponentModel.DescriptionAttribute)a.Att).Description == description); + return field == null ? default(T) : (T)field.Field.GetRawConstantValue(); + } + + public static System.Collections.Generic.IEnumerable GetEnumDescriptions() + { + var attributes = System.Linq.Enumerable.ToList(System.Linq.Enumerable.SelectMany(typeof(T).GetMembers(), member => System.Linq.Enumerable.Cast(member.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), true)))); + return System.Linq.Enumerable.Select(attributes, x => x.Description); + } + } + + public class FixedFileLogger : System.IDisposable + { + public const string SkylineDataFilePath = @"C:\Skyline_Data\"; + public const string TextFileExtension = ".txt"; + private readonly Skyline.DataMiner.Automation.IEngine engine; + private readonly string logfilePath; + private readonly System.Collections.Generic.List buffer = new System.Collections.Generic.List(); + public FixedFileLogger(Skyline.DataMiner.Automation.IEngine engine, string logFilePath) + { + this.engine = engine; + this.logfilePath = logFilePath ?? throw new System.ArgumentNullException(nameof(logFilePath)); + if (!logfilePath.StartsWith(SkylineDataFilePath)) + throw new System.ArgumentException($"Argument does not start with {SkylineDataFilePath}", nameof(logFilePath)); + if (!logfilePath.EndsWith(TextFileExtension)) + throw new System.ArgumentException($"Argument does not end with {TextFileExtension}", nameof(logFilePath)); + try + { + bool logFileExists = System.IO.File.Exists(logfilePath); + if (!logFileExists) + { + var newFile = System.IO.File.Create(logfilePath); + newFile.Close(); + } + } + catch (System.Exception e) + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EngineExtensions.Log(engine, nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.FixedFileLogger), nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.FixedFileLogger), $"Something went wrong: {e}"); + throw; + } + } + + public bool PrintOneLine + { + get; + set; + } + + = false; + internal void Log(string message) + { + buffer.Add(message); + } + + public static string GenerateLogFilePath(string fileName) + { + return $"{SkylineDataFilePath}{fileName}{TextFileExtension}"; + } + + public void Dispose() + { + try + { + if (PrintOneLine) + { + System.IO.File.AppendAllText(logfilePath, string.Join(",", buffer)); + } + else + { + System.IO.File.AppendAllLines(logfilePath, buffer); + } + + buffer.Clear(); + } + catch (System.Exception e) + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EngineExtensions.Log(engine, nameof(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.FixedFileLogger), nameof(Dispose), $"Something went wrong: {e}"); + throw; + } + } + } + + public class Helpers + { + private readonly Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.FixedFileLogger performanceLogger; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.EventManager eventManager; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.OrderLogger orderLogger; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.IServiceDefinitionManager serviceDefinitionManager; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager serviceManager; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManager orderManager; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Resources.ResourceManager resourceManager; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking.LockManager lockManager; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts.ContractManager contractManager; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskManager userTaskManager; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.IProfileManager profileManager; + private Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notes.INoteManager noteManager; + public Helpers(Skyline.DataMiner.Automation.IEngine engine) + { + Engine = engine ?? throw new System.ArgumentNullException(nameof(engine)); + performanceLogger = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.FixedFileLogger(Engine, @"C:\Skyline_Data\PerformanceLogging.txt") + {PrintOneLine = true}; + performanceLogger.Log($"START SCRIPT at {System.DateTime.UtcNow}(utc) by user {Engine.UserDisplayName}"); + } + + public Helpers(Skyline.DataMiner.Automation.IEngine engine, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter progressReporter): this(engine) + { + ProgressReporter = progressReporter; + } + + public Helpers(Skyline.DataMiner.Automation.IEngine engine, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.OrderLogger orderLogger): this(engine, orderLogger?.ProgressReporter) + { + OrderLogger = orderLogger; + } + + public Skyline.DataMiner.Automation.IEngine Engine + { + get; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.OrderLogger OrderLogger + { + get => orderLogger; + set + { + orderLogger = value; + ProgressReporter = OrderLogger?.ProgressReporter; + } + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter ProgressReporter + { + get; + set; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManager OrderManager + { + get => orderManager ?? (orderManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManager(this)); + set => orderManager = value; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager ServiceManager + { + get => serviceManager ?? (serviceManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.ServiceManager(this)); + set => serviceManager = value; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.IServiceDefinitionManager ServiceDefinitionManager + { + get => serviceDefinitionManager ?? (serviceDefinitionManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition.ServiceDefinitionManager(this)); + set => serviceDefinitionManager = value; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.EventManager EventManager + { + get => eventManager ?? (eventManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.EventManager(this)); + set => eventManager = value; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Resources.ResourceManager ResourceManager + { + get => resourceManager ?? (resourceManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Resources.ResourceManager(this)); + set => resourceManager = value; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.IProfileManager ProfileManager + { + get => profileManager ?? (profileManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile.ProfileManager(this)); + set => profileManager = value; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts.ContractManager ContractManager + { + get => contractManager ?? (contractManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts.ContractManager(Engine)); + set => contractManager = value; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking.LockManager LockManager + { + get => lockManager ?? (lockManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Locking.LockManager(Engine, ProgressReporter)); + set => lockManager = value; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskManager UserTaskManager + { + get => userTaskManager ?? (userTaskManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.UserTaskManager(Engine, ProgressReporter)); + set => userTaskManager = value; + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notes.INoteManager NoteManager + { + get => noteManager ?? (noteManager = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notes.NoteManager(Engine)); + set => noteManager = value; + } + + public Skyline.DataMiner.Library.Solutions.SRM.Helpers.ResourceManagerHelperExtended ResourceManagerHelper => Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ResourceManager; + public Skyline.DataMiner.Library.Solutions.SRM.Helpers.ServiceManagerHelperExtended ServiceManagerHelper => Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ServiceManager; + public Skyline.DataMiner.Net.Profiles.ProfileHelper ProfileHelper => Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ProfileHelper; + public Skyline.DataMiner.Library.Solutions.SRM.Helpers.ProtocolFunctionHelperExtended ProtocolFunctionHelper => Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ProtocolFunctionManager; + public void Log(string nameOfClass, string nameOfMethod, string message, string nameOfObject = null) + { + if (OrderLogger != null) + { + OrderLogger.Log(nameOfClass, nameOfMethod, message, nameOfObject); + } + else if (ProgressReporter != null) + { + ProgressReporter.LogProgress(nameOfClass, nameOfMethod, message, nameOfObject); + } + else + { + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.EngineExtensions.Log(Engine, nameOfClass, nameOfMethod, message, nameOfObject); + } + } + + public void LogMethodStart(string nameOfClass, string nameOfMethod, out System.Diagnostics.Stopwatch stopwatch, string nameOfObject = null) + { + Log(nameOfClass, nameOfMethod, "Start", nameOfObject); + stopwatch = System.Diagnostics.Stopwatch.StartNew(); + } + + public void LogMethodCompleted(string nameOfClass, string nameOfMethod, string nameOfObject = null, System.Diagnostics.Stopwatch stopwatch = null) + { + stopwatch?.Stop(); + performanceLogger.Log($"{nameOfClass}.{nameOfMethod}={stopwatch?.Elapsed}"); + Log(nameOfClass, nameOfMethod, $"Completed [{stopwatch?.Elapsed}]", nameOfObject); + } + } + + public static class JobExtensions + { + public static Skyline.DataMiner.Net.Sections.Section GetCustomEventSection(this Skyline.DataMiner.Net.Jobs.Job job, System.Guid customEventSectionDefinitionId) + { + if (job == null) + throw new System.ArgumentNullException(nameof(job)); + return System.Linq.Enumerable.SingleOrDefault(job.Sections, s => s.GetSectionDefinition().GetID().Id == customEventSectionDefinitionId); + } + + public static System.Collections.Generic.IEnumerable GetOrderSections(this Skyline.DataMiner.Net.Jobs.Job job) + { + var orderSections = new System.Collections.Generic.List(); + foreach (var section in job.Sections) + { + foreach (var fieldValue in section.FieldValues) + { + bool sectionContainsOrderId = fieldValue.Value.Type == typeof(System.Guid); + if (!sectionContainsOrderId) + continue; + orderSections.Add(new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.OrderSection(section)); + } + } + + return orderSections; + } + + public static Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.OrderSection GetOrderSection(this Skyline.DataMiner.Net.Jobs.Job job, System.Guid orderId) + { + return System.Linq.Enumerable.FirstOrDefault(GetOrderSections(job), s => s.OrderId == orderId); + } + + public static void AddOrUpdateOrderSection(this Skyline.DataMiner.Net.Jobs.Job job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.OrderSection orderSection) + { + var existingSection = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetOrderSection(job, orderSection.OrderId); + if (existingSection != null) + { + job.Sections.Remove(existingSection.Section); + } + + job.Sections.Add(orderSection.Section); + } + + public static System.DateTime GetStartTime(this Skyline.DataMiner.Net.Jobs.Job job) + { + var start = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameStartTime); + if (start == null) + return default(System.DateTime); + return System.DateTime.TryParse(start.ToString(), out var startTime) ? startTime : default(System.DateTime); + } + + public static System.DateTime GetEndTime(this Skyline.DataMiner.Net.Jobs.Job job) + { + var start = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.JobExtensions.GetFieldValue(job, Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Event.PropertyNameEndTime); + if (start == null) + return default(System.DateTime); + return System.DateTime.TryParse(start.ToString(), out var startTime) ? startTime : default(System.DateTime); + } + + public static object GetFieldValue(this Skyline.DataMiner.Net.Jobs.Job job, string fieldDescriptorName) + { + foreach (var section in job.Sections) + { + foreach (var fieldValue in section.FieldValues) + { + var fieldDescriptor = fieldValue.GetFieldDescriptor(); + if (fieldDescriptor == null) + continue; + if (System.String.Equals(fieldDescriptor.Name, fieldDescriptorName)) + { + return fieldValue.Value.Value; + } + } + } + + return null; + } + } + + [Skyline.DataMiner.Library.Common.Attributes.DllImport("SLSRMLibrary.dll")] + public class OrderLogger : System.IDisposable + { + private readonly Skyline.DataMiner.Automation.IEngine engine; + private readonly Skyline.DataMiner.Library.Solutions.SRM.BookingManager orderBookingManager; + private readonly string userName; + private readonly System.Collections.Generic.Dictionary srmLogHandlers = new System.Collections.Generic.Dictionary(); + private readonly System.Text.StringBuilder automationLoggerBuffer = new System.Text.StringBuilder(); + private bool orderReferenced = false; + /// + /// Initialize a new OrderLogger object. + /// This constructor should only be used in case the order has not been booked. + /// Make sure as soon as the order has been booked that AddOrderReference is executed to make sure the logging is correctly generated. + /// + /// The engine object. + /// Optional, set to false if you don't want to initialize a new SRM logger from this constructor. + /// Optional, name of the file to which the logging will be written in the C:\Skyline_Data folder if the logger is not linked to a reservations. + public OrderLogger(Skyline.DataMiner.Automation.IEngine engine, bool initializeEmptySrmLogHandler = true, string fileName = null) + { + this.engine = engine ?? throw new System.ArgumentNullException(nameof(engine)); + this.userName = engine.UserLoginName; + this.FileName = fileName; + ProgressReporter = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter(); + orderBookingManager = new Skyline.DataMiner.Library.Solutions.SRM.BookingManager((Skyline.DataMiner.Automation.Engine)engine, engine.FindElement(Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManager.OrderBookingManagerElementName)); + if (initializeEmptySrmLogHandler) + InitializeEmptySrmLogHandler(); + } + + /// + /// Initialize a new OrderLogger object. + /// + /// The engine object. + /// The ids of the orders for which the logging will need to be added to their respective log file. + public OrderLogger(Skyline.DataMiner.Automation.IEngine engine, string fileName = null, params System.Guid[] orderIds): this(engine, false, fileName) + { + if (orderIds == null || !System.Linq.Enumerable.Any(orderIds) || (orderIds.Length == 1 && System.Linq.Enumerable.Single(orderIds) == System.Guid.Empty)) + { + InitializeEmptySrmLogHandler(); + return; + } + + foreach (var orderId in orderIds) + { + var orderReservation = Skyline.DataMiner.Library.Solutions.SRM.SrmManagers.ResourceManager.GetReservationInstance(orderId); + InitializeSrmLogHandler(orderReservation); + } + } + + /// + /// Initialize a new OrderLogger object. + /// + /// The engine object. + /// The reservations of the orders for which the logging will need to be added to their respective log file. + public OrderLogger(Skyline.DataMiner.Automation.IEngine engine, string fileName = null, params Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance[] orderReservations): this(engine, false, fileName) + { + if (orderReservations == null || !System.Linq.Enumerable.Any(orderReservations)) + { + InitializeEmptySrmLogHandler(); + return; + } + + foreach (var orderReservation in orderReservations) + { + InitializeSrmLogHandler(orderReservation); + } + } + + public Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ProgressReporter ProgressReporter + { + get; + set; + } + + public string FileName + { + get; + set; + } + + public void Log(string nameOfClass, string nameOfMethod, string message, string nameOfObject = null) + { + ProgressReporter.LogProgress(nameOfClass, nameOfMethod, message, nameOfObject); + } + + public void Dispose() + { + if (orderReferenced) + { + foreach (var srmLogHandler in srmLogHandlers.Values) + srmLogHandler.Dispose(); + } + else if (!System.String.IsNullOrWhiteSpace(FileName)) + { + string path = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.FixedFileLogger.GenerateLogFilePath(FileName); + Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.FixedFileLogger fixedFileLogger = new Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities.FixedFileLogger(engine, path); + fixedFileLogger.Log(automationLoggerBuffer.ToString()); + fixedFileLogger.Dispose(); + } + else + { + engine.Log(automationLoggerBuffer.ToString()); + } + } + + private void InitializeSrmLogHandler(Skyline.DataMiner.Net.ResourceManager.Objects.ReservationInstance orderReservation) + { + if (orderReservation == null) + throw new System.ArgumentNullException(nameof(orderReservation)); + orderReferenced = true; + if (srmLogHandlers.TryGetValue(orderReservation.ID, out var orderSrmLogHandler)) + return; + try + { + orderSrmLogHandler = Skyline.DataMiner.Library.Solutions.SRM.Logging.SrmLogHandler.Create((Skyline.DataMiner.Automation.Engine)engine, orderBookingManager, orderReservation); + srmLogHandlers.Add(orderReservation.ID, orderSrmLogHandler); + ProgressReporter.ProgressLogging += (sender, e) => + { + var logging = $"[{System.DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff")}] {e.Progress}"; + Skyline.DataMiner.Library.Solutions.SRM.Logging.LoggerHelper.BufferMessage(orderSrmLogHandler, logging, Skyline.DataMiner.Library.Solutions.SRM.LogFileType.Debug); + } + + ; + } + catch (System.Exception e) + { + engine.Log($"OrderLogger|InitializeSrmLogHandler|Exception initializing SrmLogHandler for order {orderReservation.ID}: {e}"); + } + } + + private void InitializeEmptySrmLogHandler() + { + if (srmLogHandlers.TryGetValue(System.Guid.Empty, out var orderSrmLogHandler)) + return; + try + { + orderSrmLogHandler = Skyline.DataMiner.Library.Solutions.SRM.Logging.SrmLogHandler.Create((Skyline.DataMiner.Automation.Engine)engine, orderBookingManager, null); + srmLogHandlers.Add(System.Guid.Empty, orderSrmLogHandler); + ProgressReporter.ProgressLogging += (sender, e) => + { + var logging = $"[{System.DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff")}] {userName} {e.Progress}"; + automationLoggerBuffer.AppendLine(logging); + Skyline.DataMiner.Library.Solutions.SRM.Logging.LoggerHelper.BufferMessage(orderSrmLogHandler, logging, Skyline.DataMiner.Library.Solutions.SRM.LogFileType.Debug); + } + + ; + } + catch (System.Exception e) + { + engine.Log($"OrderLogger|InitializeEmptySrmLogHandler|Exception initializing empty SrmLogHandler: {e}"); + } + } + } + + public static class ResourceExtensions + { + public static string GetDisplayName(this Skyline.DataMiner.Net.Messages.Resource resource, System.Guid functionId) + { + bool functionIsMatrix = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.IsMatrixFunction(functionId); + bool functionIsSatellite = functionId == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration.FunctionGuids.Antenna; + return functionIsMatrix || functionIsSatellite ? resource.Name : System.Linq.Enumerable.First(resource.Name.Split('.')); + } + } + + public static class StringExtensions + { + public static T GetEnumValue(this string value) + { + var type = typeof(T); + if (!type.IsEnum) + throw new System.ArgumentException(); + System.Reflection.FieldInfo[] fields = type.GetFields(); + var field = System.Linq.Enumerable.SingleOrDefault(System.Linq.Enumerable.SelectMany(fields, f => f.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false), (f, a) => new + { + Field = f, Att = a + } + + ), a => ((System.ComponentModel.DescriptionAttribute)a.Att).Description == value); + return field == null ? default(T) : (T)field.Field.GetRawConstantValue(); + } + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/FinnishBroadcastingCompany_CustomerUI_Launcher_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/FinnishBroadcastingCompany_CustomerUI_Launcher_2.csproj new file mode 100644 index 0000000..42c68d3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/FinnishBroadcastingCompany_CustomerUI_Launcher_2.csproj @@ -0,0 +1,95 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {7413AADB-A31C-4B63-93F1-6E1D84585F8B} + Library + Properties + FinnishBroadcastingCompany_CustomerUI_Launcher_2 + FinnishBroadcastingCompany_CustomerUI_Launcher_2 + v4.6.2 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\FinnishBroadcastingCompany_CustomerUI_Launcher_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\FinnishBroadcastingCompany_CustomerUI_Launcher_2.xml + + + None + + + + + C:\Skyline DataMiner\Files\SLManagedAutomation.dll + + + C:\Skyline DataMiner\Files\SLNetTypes.dll + + + + + + C:\Skyline DataMiner\Files\Skyline.DataMiner.Storage.Types.dll + + + C:\Skyline DataMiner\Files\SLLoggerUtil.dll + + + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + C:\Skyline DataMiner\Files\Newtonsoft.Json.dll + + + C:\Skyline DataMiner\Files\InteractiveAutomationToolkit.dll + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e6f5110 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("FinnishBroadcastingCompany_CustomerUI_Launcher_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("FinnishBroadcastingCompany_CustomerUI_Launcher_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("532C135F-DCC0-43AB-82C6-1DEA5C393617")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/packages.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/packages.config new file mode 100644 index 0000000..e98004f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/CustomerUI_Launcher_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/CustomerUI_Launcher_2.csproj new file mode 100644 index 0000000..9a80d2d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/CustomerUI_Launcher_2.csproj @@ -0,0 +1,101 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {AE455D02-0572-43BA-B213-4D6BF8EDD37B} + Library + Properties + FinnishBroadcastingCompany_CustomerUI_Launcher_3 + FinnishBroadcastingCompany_CustomerUI_Launcher_3 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\FinnishBroadcastingCompany_CustomerUI_Launcher_3.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\FinnishBroadcastingCompany_CustomerUI_Launcher_3.xml + + + None + + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + 13.0.1 + + + 5.0.1 + + + 2.5.6 + + + 10.2.10.1 + + + 1.0.9.1-1.0.9.X.10 + + + 1.0.10325.13-1.0.0.X.13 + + + 1.0.10325.10-1.0.0.X.10 + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..287a291 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("FinnishBroadcastingCompany_CustomerUI_Launcher_3")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("FinnishBroadcastingCompany_CustomerUI_Launcher_3")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("AE5D86EA-795E-4BF4-9068-58F3F01BA06C")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/Script.cs new file mode 100644 index 0000000..b58f369 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/Script.cs @@ -0,0 +1,408 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2020 1.0.0.1 TRE, Skyline Initial version +**************************************************************************** +*/ + +// Engine.ShowUI(); + +using System; +using System.Collections.Generic; +using System.Linq; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.DeveloperCommunityLibrary.InteractiveAutomationToolkit; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; +using Skyline.DataMiner.Net.ResourceManager.Objects; + +/// +/// DataMiner Script Class. +/// +/// +/// DataMiner Script Class. +/// +public class Script : IDisposable +{ + private InteractiveController app; + + private Helpers helpers; + + private LaunchDialog dialog; + + private Engine engine; + + private string CustomerUiScriptName; + + private Element orderBookingManagerElement; + private bool disposedValue; + private static readonly string[] contributingResourcePoolNames = new[] { "Audio Processing", "Destination Service", "Graphics Processing Service", "Reception", "Recording Service", "Routing", "Transmission", "Video Processing Service" }; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + try + { + this.engine = engine; + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.SetFlag(RunTimeFlags.NoCheckingSets); + engine.Timeout = TimeSpan.FromHours(10); + RunSafe(engine); + } + catch (ScriptAbortException) + { + throw; + } + catch (Exception e) + { + engine.Log("Run|Something went wrong: " + e); + ShowExceptionDialog(engine, e); + } + } + + private void RunSafe(Engine engine) + { + // Init CustomerUiScriptName + CustomerUiScriptName = engine.GetScriptParam("CustomerUiScriptName").Value; + + // Find Order Booking Manager + orderBookingManagerElement = engine.FindElementsByName("Order Booking Manager").FirstOrDefault(); + if (orderBookingManagerElement == null) + { + engine.ExitFail("Unable to find Order Booking Manager"); + } + + // Launch Dialog + app = new InteractiveController(engine); + helpers = new Helpers(engine, "CustomerUI Launcher"); + dialog = new LaunchDialog(engine, helpers.OrderManager.GetAllFutureAndOngoingVideoReservations(), helpers.EventManager.GetAllEvents()); + + dialog.ViewButton.Pressed += ViewButton_Pressed; + dialog.AddButton.Pressed += AddButton_Pressed; + dialog.AddFromTemplateButton.Pressed += AddFromTemplateButton_Pressed; + dialog.AddToEventButton.Pressed += AddToEventButton_Pressed; + dialog.EditButton.Pressed += EditButton_Pressed; + dialog.DuplicateButton.Pressed += DuplicateButton_Pressed; + + app.Run(dialog); + } + + private void EditButton_Pressed(object sender, EventArgs e) + { + ReservationInstance selectedOrder = dialog.SelectedOrder; + Guid guid = Guid.Empty; + if (selectedOrder != null) guid = selectedOrder.ID; + + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", guid.ToString()); + subscriptInfo.SelectScriptParam("Action", "Edit"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + + private void DuplicateButton_Pressed(object sender, EventArgs e) + { + ReservationInstance selectedOrder = dialog.SelectedOrder; + Guid guid = Guid.Empty; + if (selectedOrder != null) guid = selectedOrder.ID; + + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", guid.ToString()); + subscriptInfo.SelectScriptParam("Action", "Duplicate"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + private void ViewButton_Pressed(object sender, EventArgs e) + { + ReservationInstance selectedOrder = dialog.SelectedOrder; + Guid guid = Guid.Empty; + if (selectedOrder != null) guid = selectedOrder.ID; + + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", guid.ToString()); + subscriptInfo.SelectScriptParam("Action", "View"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + } + + + private void AddButton_Pressed(object sender, EventArgs e) + { + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", "-1"); + subscriptInfo.SelectScriptParam("Action", "Add"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + private void AddFromTemplateButton_Pressed(object sender, EventArgs e) + { + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", "-1"); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", "-1"); + subscriptInfo.SelectScriptParam("Action", "From template"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + private void AddToEventButton_Pressed(object sender, EventArgs e) + { + Event selectedEvent = dialog.SelectedEvent; + Guid guid = Guid.Empty; + if (selectedEvent != null) guid = selectedEvent.Id; + + SubScriptOptions subscriptInfo = engine.PrepareSubScript(CustomerUiScriptName); + + subscriptInfo.SelectScriptParam("JobID", guid.ToString()); + subscriptInfo.SelectScriptParam("BookingManagerID", String.Format("{0}/{1}", orderBookingManagerElement.DmaId, orderBookingManagerElement.ElementId)); + subscriptInfo.SelectScriptParam("BookingID", "-1"); + subscriptInfo.SelectScriptParam("Action", "Add"); + subscriptInfo.SelectScriptParam("OrderType", "Video"); + + subscriptInfo.Synchronous = true; + subscriptInfo.StartScript(); + + RefreshOrders(); + RefreshEvents(); + } + + private void RefreshOrders() + { + dialog.UpdateOrders(helpers.OrderManager.GetAllFutureAndOngoingVideoReservations()); + } + + private void RefreshEvents() + { + dialog.UpdateEvents(helpers.EventManager.GetAllEvents()); + } + + private void ShowExceptionDialog(Engine engine, Exception exception) + { + ExceptionDialog dialog = new ExceptionDialog(engine, exception); + dialog.OkButton.Pressed += (sender, args) => engine.ExitSuccess("Something went wrong during the creation of the new event."); + dialog.Show(); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } +} + +public class LaunchDialog : Dialog +{ + private IEnumerable orders; + private IEnumerable events; + + public LaunchDialog(Engine engine, IEnumerable orders, IEnumerable events) + : base(engine) + { + this.orders = orders; + this.events = events; + + Title = "Customer UI Launcher"; + + OrderDropdown = new DropDown(orders.Select(x => x.Name)) { Width = 500, IsDisplayFilterShown = true }; + EventDropDown = new DropDown(events.Select(x => x.Name)) { Width = 500, IsDisplayFilterShown = true }; + AddButton = new Button("Add"); + AddFromTemplateButton = new Button("Add From Template"); + AddToEventButton = new Button("Add to Event"); + EditButton = new Button("Edit"); + DuplicateButton = new Button("Duplicate"); + ViewButton = new Button("View"); + + GenerateUI(); + } + + public void UpdateOrders(IEnumerable orders) + { + this.orders = orders; + OrderDropdown.Options = orders.Select(x => x.Name); + } + + public void UpdateEvents(IEnumerable events) + { + this.events = events; + EventDropDown.Options = events.Select(x => x.Name); + } + + public ReservationInstance SelectedOrder + { + get + { + return orders.FirstOrDefault(x => x.Name.Equals(OrderDropdown.Selected)); + } + } + + public Event SelectedEvent + { + get + { + return events.FirstOrDefault(x => x.Name.Equals(EventDropDown.Selected)); + } + } + + public DropDown EventDropDown + { + get; + private set; + } + + public DropDown OrderDropdown + { + get; + private set; + } + + public Button AddButton + { + get; + private set; + } + + public Button AddFromTemplateButton + { + get; + private set; + } + + public Button AddToEventButton + { + get; + private set; + } + + public Button EditButton + { + get; + private set; + } + + public Button DuplicateButton + { + get; + private set; + } + + public Button ViewButton + { + get; + private set; + } + + private void GenerateUI() + { + int row = -1; + AddWidget(new Label("Create new Order"), ++row, 0); + AddWidget(AddButton, row, 1); + AddWidget(AddFromTemplateButton, ++row, 1); + + AddWidget(EventDropDown, ++row, 0); + AddWidget(AddToEventButton, row, 1); + + AddWidget(OrderDropdown, ++row, 0); + AddWidget(ViewButton, row, 1); + AddWidget(EditButton, ++row, 1); + AddWidget(DuplicateButton, ++row, 1); + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/app.config new file mode 100644 index 0000000..b8ffc0f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/FinnishBroadcastingCompany_CustomerUI_Launcher_3/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder.xml new file mode 100644 index 0000000..21b7a85 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder.xml @@ -0,0 +1,31 @@ + + + ForceDeleteOrder + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/SRM + + + + + + + + + + Order Name + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/ForceDeleteOrder_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/ForceDeleteOrder_1.csproj new file mode 100644 index 0000000..4318cf8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/ForceDeleteOrder_1.csproj @@ -0,0 +1,99 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {86177A39-B69B-40BC-AAA4-E5DDDCE80B54} + Library + Properties + ForceDeleteOrder_1 + ForceDeleteOrder_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ForceDeleteOrder_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ForceDeleteOrder_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4e0a13c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ForceDeleteOrder_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ForceDeleteOrder_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("787A1BEB-CEF8-450D-9BDD-4821D93EECC3")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/Script.cs new file mode 100644 index 0000000..040f92f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/Script.cs @@ -0,0 +1,305 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace ForceDeleteOrder_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.DataMinerInterface; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net; + using Skyline.DataMiner.Net.Jobs; + using Skyline.DataMiner.Net.Messages; + using Skyline.DataMiner.Net.Messages.Advanced; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Skyline.DataMiner.Net.Ticketing; + + /// + /// DataMiner Script Class. + /// + class Script : IDisposable + { + private Helpers helpers; + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + helpers = new Helpers(engine, Scripts.ForceDeleteOrder); + + var orderName = engine.GetScriptParam("Order Name").Value; + if (String.IsNullOrEmpty(orderName)) + { + engine.Log("(ForceDeleteOrder) No valid order name provided!"); + return; + } + + var orderReservationInstance = GetOrderReservationInstance(helpers, orderName); + RemoveOrderAndServices(helpers, orderReservationInstance); + RemoveOrderFromEvent(engine, orderReservationInstance); + RemoveOrderFromOrderManager(engine, orderReservationInstance); + } + + private static ServiceReservationInstance GetOrderReservationInstance(Helpers helpers, string name) + { + try + { + var filter = new ANDFilterElement(ReservationInstanceExposers.Name.Equal(name)); + var orderReservationInstance = DataMinerInterface.ResourceManager.GetReservationInstances(helpers, filter).FirstOrDefault() as ServiceReservationInstance; + if (orderReservationInstance == null) + { + helpers.Engine.ExitFail(String.Format("(GetOrderReservationInstance) Order '{0}' reservation instance not found", name)); + return null; + } + + return orderReservationInstance; + } + catch (Exception e) + { + helpers.Engine.ExitFail(String.Format("(GetOrderReservationInstance) Exception retrieving order '{0}' reservation instance: {1}", name, e)); + return null; + } + } + + private static void RemoveOrderAndServices(Helpers helpers, ServiceReservationInstance orderReservationInstance) + { + var ticketingHelper = new TicketingGatewayHelper { HandleEventsAsync = false }; + ticketingHelper.RequestResponseEvent += (sender, args) => args.responseMessage = Engine.SLNet.SendSingleResponseMessage(args.requestMessage); + + var reservationInstancesToRemove = new List { orderReservationInstance }; + + var servicesToRemove = new List(); + if (orderReservationInstance.ServiceID != null) servicesToRemove.Add(orderReservationInstance.ServiceID); + + var ticketsToRemove = new List(); + + foreach (var resourceUsage in orderReservationInstance.ResourcesInReservationInstance) + { + try + { + var resourceReservationInstance = DataMinerInterface.ResourceManager.GetReservationInstance(helpers, resourceUsage.GUID) as ServiceReservationInstance; + if (resourceReservationInstance == null) + { + helpers.Log(nameof(Script), nameof(RemoveOrderAndServices), $"Service '{resourceUsage.GUID}' reservation instance not found"); + continue; + } + + reservationInstancesToRemove.Add(resourceReservationInstance); + if (resourceReservationInstance.ServiceID != null) servicesToRemove.Add(resourceReservationInstance.ServiceID); + + try + { + var userTaskTickets = ticketingHelper.GetTickets(filter: TicketingExposers.CustomTicketFields.DictStringField("Service ID").Equal(resourceUsage.GUID.ToString())); + if (userTaskTickets.Any()) ticketsToRemove.AddRange(userTaskTickets); + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(RemoveOrderAndServices), $"Exception retrieving user tasks for service '{resourceUsage.GUID}': {e}"); + } + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(RemoveOrderAndServices), $"Exception retrieving order '{resourceUsage.GUID}' reservation instance: {e}"); + } + } + + RemoveReservationInstances(helpers, reservationInstancesToRemove); + RemoveServices((Engine)helpers.Engine, servicesToRemove); + RemoveTickets((Engine)helpers.Engine, ticketingHelper, ticketsToRemove); + } + + private static void RemoveReservationInstances(Helpers helpers, List reservationInstances) + { + try + { + DataMinerInterface.ResourceManager.RemoveReservationInstances(helpers, reservationInstances.ToArray()); + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(RemoveReservationInstances),$"Exception removing reservations: {e}"); + } + } + + private static void RemoveServices(Engine engine, List services) + { + foreach (var serviceId in services) + { + try + { + engine.SendSLNetMessage(new SetDataMinerInfoMessage + { + Uia1 = new UIA(new[] { (uint)serviceId.DataMinerID, (uint)serviceId.SID }), + What = 74 + }); + } + catch (Exception e) + { + engine.Log(String.Format("(RemoveServices) Exception removing service '{0}': {1}", serviceId, e)); + } + } + } + + private static void RemoveTickets(Engine engine, TicketingGatewayHelper ticketingHelper, List tickets) + { + if (tickets.Any()) + { + try + { + if (!ticketingHelper.RemoveTickets(out var error, tickets.ToArray())) + { + engine.Log(String.Format("(RemoveTickets) Error removing tickets: {0}", error)); + } + } + catch (Exception e) + { + engine.Log(String.Format("(RemoveTickets) Exception removing tickets: {0}", e)); + } + } + } + + private static void RemoveOrderFromEvent(Engine engine, ReservationInstance orderReservationInstance) + { + var eventIdPropertyValue = orderReservationInstance.Properties.FirstOrDefault(p => p.Key == "EventId").Value; + if (eventIdPropertyValue == null) + { + engine.Log("(RemoveOrderFromEvent) Order EventId property is null"); + return; + } + + if (!Guid.TryParse(Convert.ToString(eventIdPropertyValue), out var eventId)) + { + engine.Log(String.Format("(RemoveOrderFromEvent) Order EventId property is not a valid Guid: {0}", eventIdPropertyValue)); + return; + } + + var helper = new JobManagerHelper(m => engine.SendSLNetMessages(m)); + + Job job = null; + try + { + job = helper.Jobs.Read(JobExposers.ID.Equal(eventId)).FirstOrDefault(); + if (job == null) + { + engine.Log(String.Format("(RemoveOrderFromEvent) Job {0} not found", eventId)); + return; + } + } + catch (Exception e) + { + engine.Log(String.Format("(RemoveOrderFromEvent) Exception retrieving job '{0}': {1}", eventId, e)); + return; + } + + try + { + foreach (var section in job.Sections) + { + foreach (var fieldValue in section.FieldValues) + { + bool sectionContainsOrderId = fieldValue.Value.Type == typeof(Guid); + if (sectionContainsOrderId && (Guid)fieldValue.Value.Value == orderReservationInstance.ID) + { + job.Sections.Remove(section); + helper.Jobs.Update(job); + return; + } + } + } + } + catch (Exception e) + { + engine.Log(String.Format("(RemoveOrderFromEvent) Exception removing order '{0}' from job '{1}': {2}", orderReservationInstance.ID, eventId, e)); + } + } + + private static void RemoveOrderFromOrderManager(Engine engine, ReservationInstance orderReservationInstance) + { + try + { + var orderManagerElement = engine.FindElementsByProtocol("Finnish Broadcasting Company Order Manager").FirstOrDefault() ?? throw new NotFoundException("Unable to find order manager element"); + orderManagerElement.SetParameterByPrimaryKey(2006, orderReservationInstance.ID.ToString(), "Delete"); + } + catch (Exception e) + { + engine.Log(String.Format("(RemoveOrderFromOrderManager) Exception removing order '{0}' from order manager element: {1}", orderReservationInstance.ID, e)); + } + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteOrder_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource.xml new file mode 100644 index 0000000..932e2bf --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource.xml @@ -0,0 +1,32 @@ + + + ForceDeleteResource + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/SRM + + + + + + + + + + Resource Name + + + Force + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/ForceDeleteResource_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/ForceDeleteResource_1.cs new file mode 100644 index 0000000..6a03a37 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/ForceDeleteResource_1.cs @@ -0,0 +1,105 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +using System; +using System.Linq; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.Library.Solutions.SRM; +using Skyline.DataMiner.Net.Messages; +using Skyline.DataMiner.Net.Messages.SLDataGateway; +using Skyline.DataMiner.Net.ResourceManager.Objects; + +/// +/// DataMiner Script Class. +/// +public class Script +{ + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + var resourceName = engine.GetScriptParam("Resource Name").Value; + + var resource = SrmManagers.ResourceManager.GetResources(ResourceExposers.Name.Equal(resourceName)).FirstOrDefault(); + if (resource == null) + { + engine.Log($"(ForceDeleteResource) Resource {resourceName} not found"); + return; + } + + var force = Convert.ToBoolean(engine.GetScriptParam("Force").Value); + if (force) RemoveReservationsUsingResource(resource); + + var setResourceMessage = new SetResourceMessage(resource) + { + isDelete = true, + ForceQuarantine = force, + IgnorePastReservations = true, + //IgnoreCanceledReservations = true + }; + + engine.SendSLNetSingleResponseMessage(setResourceMessage); + } + + private static void RemoveReservationsUsingResource(Resource resource) + { + FilterElement filter = ReservationInstanceExposers.Status.NotEqual((int)ReservationStatus.Canceled); + filter = filter.AND(ReservationInstanceExposers.End.GreaterThanOrEqual(DateTime.UtcNow)); + filter = filter.AND(ReservationInstanceExposers.ResourceIDsInReservationInstance.Contains(resource.ID)); + + var reservationInstances = SrmManagers.ResourceManager.GetReservationInstances(filter); + if (!reservationInstances.Any()) return; + + SrmManagers.ResourceManager.RemoveReservationInstances(reservationInstances); + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/ForceDeleteResource_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/ForceDeleteResource_1.csproj new file mode 100644 index 0000000..ac4b1cd --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/ForceDeleteResource_1.csproj @@ -0,0 +1,90 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {BB6E867B-D3C5-4EB8-8A08-919A8E530753} + Library + Properties + ForceDeleteResource_1 + ForceDeleteResource_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\ForceDeleteResource_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\ForceDeleteResource_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..84372f8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ForceDeleteResource_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("ForceDeleteResource_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("E412BF55-E023-405F-A334-A31816C375EE")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/ForceDeleteResource_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction.xml new file mode 100644 index 0000000..07a7429 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction.xml @@ -0,0 +1,34 @@ + + + HandleEventAction + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/SRM + + + + + + + + + + EventIds + + + Status + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/HandleEventAction_3.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/HandleEventAction_3.csproj new file mode 100644 index 0000000..6fe9d8f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/HandleEventAction_3.csproj @@ -0,0 +1,103 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {3FF581CD-E646-48CE-8611-159999784EDB} + Library + Properties + HandleEventAction_3 + HandleEventAction_3 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\HandleEventAction_3.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\HandleEventAction_3.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + 13.0.3 + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..065ccd1 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("HandleEventAction_3")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("HandleEventAction_3")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("35D81339-0949-4B82-9090-FF790B76E655")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/Script.cs new file mode 100644 index 0000000..f2adc0f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/Script.cs @@ -0,0 +1,102 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +13/03/2020 1.0.0.1 JVT, Skyline Initial version + +**************************************************************************** +*/ + +namespace HandleEventAction_3 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using EventStatus = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event.Status; + + /// + /// DataMiner Script Class. + /// + class Script + { + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + engine.Timeout = TimeSpan.FromMinutes(30); + + var helpers = new Helpers(engine, Scripts.HandleEventAction); + + try + { + var eventIds = JsonConvert.DeserializeObject>(engine.GetScriptParam("EventIds").Value).Select(x => Guid.Parse(x)).ToList(); + var status = engine.GetScriptParam("Status").Value.GetEnumValue(); + + foreach (var eventId in eventIds) + { + if (!helpers.EventManager.UpdateEventStatus(eventId, status)) + { + helpers.Log(nameof(Script), nameof(Run), $"Event {eventId} status could not be updated to {status}"); + } + } + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Exception: {e}"); + } + finally + { + helpers.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleEventAction_3/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate.xml new file mode 100644 index 0000000..ae5c51d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate.xml @@ -0,0 +1,31 @@ + + + HandleIntegrationUpdate + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/Integrations + + + + + + + + + + update + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/HandleIntegrationUpdate_4.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/HandleIntegrationUpdate_4.csproj new file mode 100644 index 0000000..3a4cdd5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/HandleIntegrationUpdate_4.csproj @@ -0,0 +1,106 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {10DE679A-E842-4227-8120-AB0D91F02C3B} + Library + Properties + HandleIntegrationUpdate_4 + HandleIntegrationUpdate_4 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\HandleIntegrationUpdate_4.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\HandleIntegrationUpdate_4.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + C:\Skyline DataMiner\Files\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + 1.0.1.12 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9795af4 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("HandleIntegrationUpdate_4")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("HandleIntegrationUpdate_4")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("B9F9E401-0BB3-48E1-8D6C-C8481707B244")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/Script.cs new file mode 100644 index 0000000..e72401c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/Script.cs @@ -0,0 +1,157 @@ +namespace HandleIntegrationUpdate_4 +{ + using System; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Ceiton; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Feenix; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.PebbleBeach; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Plasma; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Utils.YLE.Integrations; + + /// + /// DataMiner Script Class. + /// + public class Script : IDisposable + { + private Helpers helpers; + private bool disposedValue; + + /// + /// The Script entry point. + /// + /// Link with SLScripting process. + public void Run(Engine engine) + { + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.Timeout = TimeSpan.FromHours(1); + + helpers = new Helpers(engine, Scripts.HandleIntegrationUpdate); + + OrderManagerElement orderManagerElement = null; + IntegrationRequest request = null; + try + { + orderManagerElement = new OrderManagerElement(helpers); + request = InitializeRequest(engine); + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Exception during initialization: {e.Message}"); + Dispose(); + return; + } + + Integration integration = null; + try + { + integration = InitializeIntegration(orderManagerElement, request.IntegrationType); + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Exception initializing integration: {e.Message}"); + orderManagerElement.SendResponse(new IntegrationResponse(request) + { + Status = UpdateStatus.Failed, + AdditionalInformation = $"Exception initializing integration {request.IntegrationType}: {e.Message}" + }); + + Dispose(); + return; + } + + if (integration == null) return; + + try + { + integration.HandleUpdate(request.IntegrationUpdateId, request.IntegrationData); + } + catch (LockNotGrantedException e) + { + helpers.Log(nameof(Script), nameof(Run), $"Lock not granted"); + orderManagerElement.SendResponse(new IntegrationResponse(request) + { + Status = UpdateStatus.Failed, + AdditionalInformation = e.ToString(), + }); + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Exception handling update: {e}"); + orderManagerElement.SendResponse(new IntegrationResponse(request) + { + Status = UpdateStatus.Failed, + AdditionalInformation = $"HandleUpdate|No action executed|Exception handling update: {e}", + }); + } + finally + { + Dispose(); + } + } + + private static IntegrationRequest InitializeRequest(IEngine engine) + { + string updateValue = engine.GetScriptParam("update").Value; + if (String.IsNullOrEmpty(updateValue)) throw new ScriptParameterException("Update script parameter is empty"); + + var request = JsonConvert.DeserializeObject(updateValue); + + return request; + } + + private Integration InitializeIntegration(OrderManagerElement orderManagerElement, IntegrationType type) + { + switch (type) + { + case IntegrationType.Ceiton: + return new CeitonIntegration(helpers, orderManagerElement); + case IntegrationType.Plasma: + return new PlasmaIntegration(helpers, orderManagerElement); + case IntegrationType.Feenix: + return new FeenixIntegration(helpers, orderManagerElement); + case IntegrationType.Eurovision: + return new EurovisionIntegration(helpers, orderManagerElement); + case IntegrationType.PebbleBeach: + return new PebbleBeachIntegration(helpers, orderManagerElement); + default: + throw new UnsupportedIntegrationException(type); + } + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + try + { + helpers.LockManager.ReleaseLocks(); + } + catch(Exception e) + { + helpers.Log(nameof(Script), nameof(Dispose), $"Exception releasing locks: {e}"); + } + + helpers.Dispose(); + } + + disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleIntegrationUpdate_4/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion.xml new file mode 100644 index 0000000..edbee76 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion.xml @@ -0,0 +1,26 @@ + + + HandleNonLiveFolderDeletion + Script 1.0.1.77 + Automation + SKYLINE2\GillesVH + FALSE + YLE/Tools + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/HandleNonLiveFolderDeletion_1.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/HandleNonLiveFolderDeletion_1.cs new file mode 100644 index 0000000..c2a57b3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/HandleNonLiveFolderDeletion_1.cs @@ -0,0 +1,153 @@ +/* +**************************************************************************** +* Copyright (c) 2022, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2022 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +using System; +using Skyline.DataMiner.Automation; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks.NonLiveUserTasks; +using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; +using Type = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.IngestExport.Type; + +/// +/// DataMiner Script Class. +/// +public class Script : IDisposable +{ + private bool disposedValue; + + private Helpers helpers; + + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + engine.Timeout = TimeSpan.FromHours(1); + helpers = new Helpers(engine, Scripts.HandleNonLiveFolderDeletion); + + try + { + var now = DateTime.Now.ToUniversalTime().Date; + var maxLookupTime = now.AddDays(15).Date; // All user tasks which will be tagged as deleted in a 14 days timespan. (15 days to be sure all of them are in there) + if (!helpers.NonLiveUserTaskManager.TryGetAllFutureUserTasks(now, maxLookupTime, out var allFutureUserTasks)) + { + helpers.Log(nameof(Script), nameof(Run), $"Failed to retrieve all pending user tasks in the system."); + } + else + { + foreach (var futureUserTask in allFutureUserTasks) + { + UpdateNonLiveUserTask(futureUserTask); + } + } + } + catch (ScriptAbortException) + { + // do nothing + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), "Something went wrong: " + e); + } + finally + { + Dispose(); + } + } + + private void UpdateNonLiveUserTask(NonLiveUserTask nonLiveUserTask) + { + try + { + var now = DateTime.Now; + var timeUntilDeletionDate = nonLiveUserTask.DeleteDate.Date - now.Date; + + nonLiveUserTask.Status = nonLiveUserTask.LinkedOrderType == Type.IplayFolderCreation ? UserTaskStatus.DeleteDateNear : UserTaskStatus.BackupDeleteDateNear; + + nonLiveUserTask.AddOrUpdate(helpers); + bool reminderMailShouldBeSend = timeUntilDeletionDate == TimeSpan.FromDays(1) || timeUntilDeletionDate == TimeSpan.FromDays(14); + if (reminderMailShouldBeSend) + { + nonLiveUserTask.SendReminderMail(); + } + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(UpdateNonLiveUserTask), $"Something went wrong during user task add or update with ticket id {nonLiveUserTask.ID}: {e}"); + } + } + + #region IDisposable Support + protected virtual void Dispose(bool disposing) + { + if (!disposedValue && disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + + ~Script() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + #endregion +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/HandleNonLiveFolderDeletion_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/HandleNonLiveFolderDeletion_1.csproj new file mode 100644 index 0000000..3a01d33 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/HandleNonLiveFolderDeletion_1.csproj @@ -0,0 +1,103 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {650813DD-F043-4C38-B235-4F2986B96DF4} + Library + Properties + HandleNonLiveFolderDeletion_1 + HandleNonLiveFolderDeletion_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\HandleNonLiveFolderDeletion_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\HandleNonLiveFolderDeletion_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + False + ..\..\..\..\..\..\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\System.Net.Http.dll + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d8cb3d0 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("HandleNonLiveFolderDeletion_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("HandleNonLiveFolderDeletion_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("445D1727-C131-49E6-B6FA-01A68D30C0E9")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/app.config new file mode 100644 index 0000000..dbef57a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleNonLiveFolderDeletion_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction.xml new file mode 100644 index 0000000..efc4e50 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction.xml @@ -0,0 +1,37 @@ + + + HandleOrderAction + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/SRM + + + + + + + + + + Action + + + Booking Manager Info + + + ReservationGuid + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/Action.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/Action.cs new file mode 100644 index 0000000..d8e2ef2 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/Action.cs @@ -0,0 +1,9 @@ +namespace HandleOrderAction_1 +{ + public enum Action + { + BookServices, + BookEventLevelReceptionServices, + DeleteServices + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/BookEventLevelReceptionServicesAction.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/BookEventLevelReceptionServicesAction.cs new file mode 100644 index 0000000..a7f83a6 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/BookEventLevelReceptionServicesAction.cs @@ -0,0 +1,91 @@ +namespace HandleOrderAction_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderUpdates; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.Status; + + public class BookEventLevelReceptionServicesAction : OrderAction + { + public BookEventLevelReceptionServicesAction(Helpers helpers, Guid orderId) : base(helpers, orderId) + { + + } + + public override void Execute() + { + if (!TryBookEventLevelReceptionServices(out var errorMessage)) + { + Log("Execute", "Update order manager element book event level reception service status with failure"); + helpers.OrderManagerElement.UpdateBookEventLevelReceptionServiceStatus(new Order { Id = orderId }, false, errorMessage); + } + else + { + Log("Execute", "Update order manager element book event level reception service status with success"); + helpers.OrderManagerElement.UpdateBookEventLevelReceptionServiceStatus(new Order { Id = orderId }, true); + } + } + + public override void HandleException(string errorMessage) + { + SendLiveOrderServicesBookedErrorNotification(errorMessage); + + if (errorMessage == LockNotGrantedException.DefaultMessage) + { + Log(nameof(HandleException), "Update order manager element book service status with failure"); + helpers.OrderManagerElement.UpdateBookEventLevelReceptionServiceStatus(new Order { Id = orderId }, false, errorMessage); + } + } + + private bool TryBookEventLevelReceptionServices(out string errorMessage) + { + errorMessage = ""; + + if (!TryGetOrder(out var order, out errorMessage)) + { + Log(nameof(TryBookEventLevelReceptionServices), errorMessage); + SendLiveOrderServicesBookedErrorNotification(errorMessage); + return false; + } + + UpdateResult result = null; + try + { + result = order.BookEventLevelReceptionServices(helpers); + } + catch (Exception e) + { + errorMessage = $"Exception executing book event level reception services: {e}"; + SendLiveOrderServicesBookedErrorNotification(errorMessage, order); + return false; + } + + if (result.UpdateWasSuccessful) + { + Log(nameof(TryBookEventLevelReceptionServices), "Event level reception services successfully booked (no tasks failed)"); + SendLiveOrderServicesBookedNotification(order, result.Tasks); + return true; + } + + RollBackFailedBlockingTasks(result.Tasks); + + var failedTaskCount = result.Tasks.Count(t => t.Status == Status.Fail); + var exceptions = new StringBuilder($"Event level reception services not successfully booked ({failedTaskCount}/{result.Tasks.Count} tasks failed):"); + foreach (var exception in result.Exceptions) + { + exceptions.AppendLine(exception.ToString()); + } + + errorMessage = exceptions.ToString(); + + SendLiveOrderServicesBookedErrorNotification(errorMessage, order); + return false; + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/BookServicesAction.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/BookServicesAction.cs new file mode 100644 index 0000000..4b00779 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/BookServicesAction.cs @@ -0,0 +1,96 @@ +namespace HandleOrderAction_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderUpdates; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.Status; + + public class BookServicesAction : OrderAction + { + public BookServicesAction(Helpers helpers, Guid orderId) : base(helpers, orderId) + { + + } + + public override void Execute() + { + var stopwatch = LogMethodStart(nameof(Execute), nameof(BookServicesAction)); + + if (!TryBookServices(out var errorMessage)) + { + Log(nameof(Execute), errorMessage); + Log(nameof(Execute), "Update order manager element book service status with failure"); + helpers.OrderManagerElement.UpdateBookServiceStatus(new Order { Id = orderId }, false, errorMessage); + } + else + { + Log(nameof(Execute), "Update order manager element book service status with success"); + helpers.OrderManagerElement.UpdateBookServiceStatus(new Order { Id = orderId }, true); + } + + LogMethodCompleted(nameof(Execute), stopwatch); + } + + public override void HandleException(string errorMessage) + { + SendLiveOrderServicesBookedErrorNotification(errorMessage); + + if (errorMessage == LockNotGrantedException.DefaultMessage) + { + Log(nameof(HandleException), "Update order manager element book service status with failure"); + helpers.OrderManagerElement.UpdateBookServiceStatus(new Order { Id = orderId }, false, errorMessage); + } + } + + private bool TryBookServices(out string errorMessage) + { + errorMessage = ""; + + if (!TryGetOrder(out var order, out errorMessage)) + { + Log(nameof(TryBookServices), errorMessage); + SendLiveOrderServicesBookedErrorNotification(errorMessage); + return false; + } + + UpdateResult result = null; + try + { + result = order.BookServices(helpers); + } + catch (Exception e) + { + errorMessage = $"Exception executing book services: {e}"; + SendLiveOrderServicesBookedErrorNotification(errorMessage, order); + return false; + } + + if (result.UpdateWasSuccessful) + { + Log("TryBookServices", "Services successfully booked (no tasks failed)"); + SendLiveOrderServicesBookedNotification(order, result.Tasks); + return true; + } + + RollBackFailedBlockingTasks(result.Tasks); + + var failedTaskCount = result.Tasks.Count(t => t.Status == Status.Fail); + var exceptions = new StringBuilder($"Services not successfully booked ({failedTaskCount}/{result.Tasks.Count} tasks failed):"); + foreach (var exception in result.Exceptions) + { + exceptions.AppendLine(exception.ToString()); + } + + errorMessage = exceptions.ToString(); + + SendLiveOrderServicesBookedErrorNotification(errorMessage, order); + return false; + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/DeleteServicesAction.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/DeleteServicesAction.cs new file mode 100644 index 0000000..aa91903 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/DeleteServicesAction.cs @@ -0,0 +1,106 @@ +namespace HandleOrderAction_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class DeleteServicesAction : OrderAction + { + private readonly List semiColonSeparatedServiceIds; + private readonly bool removeAllServices; + + public DeleteServicesAction(Helpers helpers, Guid orderId, List semiColonSeparatedServiceIds, bool removeAllServices) : base(helpers, orderId) + { + this.semiColonSeparatedServiceIds = semiColonSeparatedServiceIds ?? throw new ArgumentNullException(nameof(semiColonSeparatedServiceIds)); + this.removeAllServices = removeAllServices; + } + + public override void Execute() + { + if (TryDeleteServices(out var errorMessage)) + { + Log(nameof(Execute), "Deleting services succeeded"); + } + else + { + Log(nameof(Execute), $"Deleting services couldn't proceed: {errorMessage}"); + } + } + + public override void HandleException(string errorMessage) + { + // nothing to do + } + + private bool TryDeleteServices(out string errorMessage) + { + errorMessage = string.Empty; + + if (!TryGetOrder(out var order, out errorMessage)) return false; + var servicesToRemove = GetServicesToRemove(order); + + try + { + Log(nameof(TryDeleteServices), $"Removing the following services: {string.Join(";", servicesToRemove.Select(x => x.Id))}"); + + if (!servicesToRemove.Any()) + { + errorMessage = "No services to remove"; + Log(nameof(TryDeleteServices), errorMessage); + + return false; + } + + if (order.RemoveBookedServices(helpers, servicesToRemove)) + { + return true; + } + else + { + errorMessage = "Removing booked services failed"; + return false; + } + + } + catch (Exception e) + { + errorMessage = $"Exception deleting services from order: {e}"; + return false; + } + } + + private List GetServicesToRemove(Order order) + { + Log(nameof(GetServicesToRemove), $"ServiceIds script param value: '{string.Join(";", semiColonSeparatedServiceIds)}', Remove all services: {removeAllServices}"); + + if (removeAllServices) return order.AllServices.Where(x => x.IsBooked).ToList(); + + var servicesToRemove = new List(); + foreach (string serviceIdValue in semiColonSeparatedServiceIds) + { + Log(nameof(GetServicesToRemove), $"Service id value: {serviceIdValue}"); + + if (!Guid.TryParse(serviceIdValue, out var serviceId)) + { + Log(nameof(GetServicesToRemove), $"Parsing service guid {serviceIdValue} failed"); + continue; + } + + // Services need to be retrieved, services to be removed are already detached from the order. + if (!helpers.ServiceManager.TryGetService(serviceId, out var service)) + { + Log(nameof(GetServicesToRemove), $"Retrieving service with id {serviceId} failed"); + } + else + { + servicesToRemove.Add(service); + } + } + + return servicesToRemove; + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/HandleOrderActionInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/HandleOrderActionInfo.cs new file mode 100644 index 0000000..0f3c9f4 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/HandleOrderActionInfo.cs @@ -0,0 +1,45 @@ +namespace HandleOrderAction_1 +{ + using Newtonsoft.Json; + using System; + using System.Collections.Generic; + + public class HandleOrderActionInfo + { + [JsonRequired] + public string Action { get; set; } + + [JsonRequired] + public string OrderId { get; set; } + + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public List ServiceIds { get; set; } + + [JsonRequired] + public bool RemoveAllServices { get; set; } + + public static HandleOrderActionInfo Deserialize(string json) + { + try + { + return JsonConvert.DeserializeObject(json); + } + catch (Exception) + { + return null; + } + } + + public string Serialize() + { + try + { + return JsonConvert.SerializeObject(this, Formatting.None); + } + catch (Exception) + { + return null; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/HandleOrderAction_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/HandleOrderAction_1.csproj new file mode 100644 index 0000000..5e24ff9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/HandleOrderAction_1.csproj @@ -0,0 +1,111 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {6BDE17DC-A368-4EB8-9BA5-222E2E8469D1} + Library + Properties + HandleOrderAction_1 + HandleOrderAction_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\HandleOrderAction_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\HandleOrderAction_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 13.0.3 + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/OrderAction.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/OrderAction.cs new file mode 100644 index 0000000..2755512 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/OrderAction.cs @@ -0,0 +1,177 @@ +namespace HandleOrderAction_1 +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Text; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notifications; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.Status; + + public abstract class OrderAction + { + protected readonly Helpers helpers; + protected readonly Guid orderId; + + protected OrderAction(Helpers helpers, Guid orderId) + { + this.helpers = helpers ?? throw new ArgumentNullException(nameof(helpers)); + this.orderId = orderId; + } + + public abstract void Execute(); + + //public abstract void HandleLockFailure(); + + public abstract void HandleException(string errorMessage); + + protected bool TryGetOrder(out Order order, out string errorMessage) + { + order = null; + errorMessage = string.Empty; + + try + { + order = helpers.OrderManager.GetOrder(orderId); + + errorMessage = order != null ? string.Empty : $"Order with ID {orderId} could not be found"; + + return order != null; + } + catch (Exception e) + { + errorMessage = $"Exception while retrieving order with ID {orderId}: {e}"; + return false; + } + } + + protected bool TryGetService(Guid serviceId, out Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service service, out string errorMessage) + { + service = null; + errorMessage = ""; + + try + { + service = helpers.ServiceManager.GetService(serviceId); + if (service == null) + { + errorMessage = "Service could not be retrieved"; + + return false; + } + + return true; + } + catch (Exception e) + { + errorMessage = $"Exception retrieving service: {e}"; + + return false; + } + } + + protected void RollBackFailedBlockingTasks(List tasks) + { + try + { + foreach (var failedTask in tasks.Where(t => t.Status == Status.Fail)) + { + Log("RollBackFailedBlockingTasks", $"Task {failedTask.Description} failed: {failedTask.Exception}"); + } + + var shouldRollBack = tasks.Any(t => t.Status == Status.Fail && t.IsBlocking); + if (!shouldRollBack) return; + + Log("RollBackFailedBlockingTasks", "Tasks will be rolled back because some blocking tasks failed"); + + var rollbackTasks = tasks.Where(t => t.Status == Status.Ok).Select(t => t.CreateRollbackTask()).Where(t => t != null).Reverse().ToList(); + foreach (var rollbackTask in rollbackTasks) + { + if (!rollbackTask.Execute()) Log("RollBackFailedBlockingTasks", $"(BookServices) Rolling back {rollbackTask.Description} failed: {rollbackTask.Exception.ToString()}"); + } + } + catch (Exception e) + { + Log("RollBackFailedBlockingTasks", $"Exception rolling back book event level reception services: {e}"); + } + } + + protected void SendLiveOrderServicesBookedNotification(Order order, List tasks) + { + var message = new StringBuilder(); + + var blockingTaskFailed = false; + var nonBlockingTaskFailed = false; + foreach (var task in tasks) + { + if (task.Status == Status.Fail) + { + if (task.IsBlocking) blockingTaskFailed = true; + else nonBlockingTaskFailed = true; + } + + //message.AppendLine(String.Format("Task '{0}' {1}", task.Description, task.Status == Tasks.Status.Ok ? "Succeeded" : "Failed")); + } + + if (blockingTaskFailed) message.Insert(0, "Order services could not successfully be booked (some blocking tasks failed) and all changes were rolled back."); + else if (nonBlockingTaskFailed) message.Insert(0, "Order services could not be successfully booked (some non-blocking tasks failed)."); + else message.Insert(0, "Order services were successfully booked."); + + var successful = !blockingTaskFailed && !nonBlockingTaskFailed; + SendLiveOrderServicesBookedNotification(order, successful, message.ToString()); + } + + protected void SendLiveOrderServicesBookedNotification(Order order, bool successful, string message) + { + Stopwatch stopwatch = LogMethodStart(nameof(SendLiveOrderServicesBookedNotification)); + + try + { + NotificationManager.SendLiveOrderServicesBookedMail(helpers, order, successful, message); + Log("SendLiveOrderServicesBookedNotification", "Live order booked services notification sent"); + } + catch (Exception e) + { + Log("SendLiveOrderServicesBookedNotification", $"Exception sending live order booked services notification: {e}"); + } + + LogMethodCompleted(nameof(SendLiveOrderServicesBookedNotification), stopwatch); + } + + protected void SendLiveOrderServicesBookedErrorNotification(string message, Order order = null) + { + Stopwatch stopwatch = LogMethodStart(nameof(SendLiveOrderServicesBookedErrorNotification)); + + try + { + NotificationManager.SendLiveOrderServicesBookedMail(helpers, order, false, message); + Log(nameof(SendLiveOrderServicesBookedErrorNotification), "Live order booked services notification sent"); + } + catch (Exception e) + { + Log(nameof(SendLiveOrderServicesBookedErrorNotification), $"Exception sending live order booked services notification: {e}"); + } + + LogMethodCompleted(nameof(SendLiveOrderServicesBookedErrorNotification), stopwatch); + } + + protected void Log(string nameOfMethod, string message) + { + helpers.Log(nameof(OrderAction),nameOfMethod, message); + } + + protected Stopwatch LogMethodStart(string nameOfMethod, string nameOfObject = null) + { + helpers.LogMethodStart(nameof(OrderAction), nameOfMethod, out Stopwatch stopwatch, nameOfObject); + return stopwatch; + } + + protected void LogMethodCompleted(string nameOfMethod, Stopwatch stopwatch) + { + helpers.LogMethodCompleted(nameof(OrderAction), nameOfMethod, null, stopwatch); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..553557e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("HandleOrderAction_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("HandleOrderAction_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("A74A84AB-D6BB-4D2B-A936-EEC4FA98EB00")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/Script.cs new file mode 100644 index 0000000..3311f54 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/Script.cs @@ -0,0 +1,233 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2020 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace HandleOrderAction_1 +{ + using System; + using System.Collections.Generic; + using System.Threading; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages; + + public class Script : IDisposable + { + private Helpers helpers; + + private bool triggeredByBookingAction; + private string inputAction; + private Guid inputOrderId; + private List inputServiceIdsToRemove; + private bool removeAllServices; + + public void Run(IEngine engine) + { + bool lockRetrieved = false; + OrderAction action = null; + + try + { + Initialize(engine); + + if (triggeredByBookingAction) + { + StartUpdateOrderStatusAsyncScript(); + } + else + { + action = GetAction(); + if (!(action is DeleteServicesAction)) + { + RetrieveLock(inputOrderId); + lockRetrieved = true; + } + + action.Execute(); + } + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Exception handling order action: {e}"); + + action?.HandleException(e.Message); + } + finally + { + Dispose(); + if (lockRetrieved) ReleaseLock(); + } + } + + private void Initialize(IEngine engine) + { + engine.Timeout = TimeSpan.FromHours(1); + engine.SetFlag(RunTimeFlags.NoKeyCaching); + helpers = new Helpers(engine, Scripts.HandleOrderAction); + + var action = engine.GetScriptParam("Action").Value; + + inputOrderId = Guid.Parse(engine.GetScriptParam("ReservationGuid").Value); + helpers.AddOrderReferencesForLogging(inputOrderId); + + inputAction = action; + var handleOrderActionInfo = HandleOrderActionInfo.Deserialize(action); // Will succeed when Order Manager Element triggers this script. + + if (handleOrderActionInfo == null) + { + triggeredByBookingAction = true; + return; + } + + inputAction = handleOrderActionInfo.Action; + inputServiceIdsToRemove = handleOrderActionInfo.ServiceIds ?? new List(); + removeAllServices = handleOrderActionInfo.RemoveAllServices; + } + + private OrderAction GetAction() + { + switch (inputAction) + { + case "Book Services": + return new BookServicesAction(helpers, inputOrderId); + case "Book Event Level Reception Services": + return new BookEventLevelReceptionServicesAction(helpers, inputOrderId); + case "Delete Services": + return new DeleteServicesAction(helpers, inputOrderId, inputServiceIdsToRemove, removeAllServices); + default: + throw new InvalidOperationException("Invalid action: " + inputAction); + } + } + + private void StartUpdateOrderStatusAsyncScript() + { + helpers.Log(nameof(Script), nameof(StartUpdateOrderStatusAsyncScript), $"Launching script UpdateOrderStatus asynchronous from Handle Order Action"); + + helpers.Engine.SendSLNetSingleResponseMessage(new ExecuteScriptMessage("UpdateOrderStatus") + { + Options = new SA(new[] + { + $"PARAMETER:3:{inputAction}", + $"PARAMETER:4:{inputOrderId}", + "OPTIONS:0", + "CHECKSETS:FALSE", + "EXTENDED_ERROR_INFO", + "DEFER:TRUE" // async execution + }) + }); + } + + private void RetrieveLock(Guid reservationId) + { + try + { + var lockInfo = helpers.LockManager.RequestOrderLock(reservationId); + if (!lockInfo.IsLockGranted) + { + helpers.Log(nameof(Script), "RetrieveLock", "Lock could not be retrieved"); + throw new LockNotGrantedException(); + } + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(RetrieveLock), $"Exception retrieving order lock: {e}"); + throw; + } + } + + private void ReleaseLock() + { + try + { + if (helpers.LockManager == null) return; + + helpers.LockManager.ReleaseLocks(); + } + catch (Exception e) + { + helpers.Log(nameof(Script), nameof(ReleaseLock), $"Exception releasing order lock: {e}"); + } + } + + #region IDisposable Support + private bool disposedValue; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + ~Script() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(false); + } + + // This code added to correctly implement the disposable pattern. + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + + GC.SuppressFinalize(this); + } + #endregion + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderAction_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure.xml new file mode 100644 index 0000000..624ec0e --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure.xml @@ -0,0 +1,28 @@ + + + HandleOrderStartFailure + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/SRM + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/HandleOrderStartFailure_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/HandleOrderStartFailure_1.csproj new file mode 100644 index 0000000..2c2368f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/HandleOrderStartFailure_1.csproj @@ -0,0 +1,100 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {24C6898B-ACF8-4406-8767-4EB388950D3B} + Library + Properties + HandleOrderStartFailure_1 + HandleOrderStartFailure_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\HandleOrderStartFailure_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\HandleOrderStartFailure_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..20b67d2 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("HandleOrderStartFailure_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("HandleOrderStartFailure_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("13F450E7-5169-4D8D-9D18-92774756BAC6")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/Script.cs new file mode 100644 index 0000000..0aff168 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/Script.cs @@ -0,0 +1,113 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace HandleOrderStartFailure_1 +{ + using System; + using System.Collections.Generic; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.ResourceManager.Objects; + + /// + /// DataMiner Script Class. + /// + class Script + { + [AutomationEntryPoint(AutomationEntryPointType.Types.OnSrmStartActionsFailure)] + public void OnSrmStartActionsFailure(Engine engine, List errorData) + { + foreach (var item in errorData) + { + string errorMessage = ""; + switch (item.ErrorReason) + { + case StartActionsFailureErrorData.Reason.UnexpectedException: + errorMessage = "Reservation failed to start due an unexpected exception"; + break; + case StartActionsFailureErrorData.Reason.ResourceElementNotActive: + errorMessage = $"Reservation failed to start due to resource element {item.Resource.DmaID}/{item.Resource.ElementID} was not set to active when the reservation started"; + break; + case StartActionsFailureErrorData.Reason.ReservationInstanceNotFound: + errorMessage = "Reservation failed to start due to reservation instance not found."; + break; + default: + errorMessage = "Reservation failed to start due an unknown reason."; + break; + } + + var orderId = item.ReservationInstanceId; + if (!orderId.HasValue) + { + engine.Log($"HandleOrderStartFailure|OnSrmStartActionsFailure|Unknown order could not be started: {errorMessage}"); + } + else + { + LogErrorInOrderLogging(engine, orderId.Value, errorMessage); + } + } + } + + private void LogErrorInOrderLogging(Engine engine, Guid orderId, string errorMessage) + { + try + { + var helpers = new Helpers(engine, Scripts.HandleOrderStartFailure, orderIds:orderId); + helpers.Log("HandleOrderStartFailure", "LogErrorInOrderLogging", $"Order {orderId} could not be started: {errorMessage}"); + } + catch (Exception) + { + engine.Log($"HandleOrderStartFailure|OnSrmStartActionsFailure|Order {orderId} could not be started: {errorMessage}"); + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleOrderStartFailure_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction.xml new file mode 100644 index 0000000..a47a85c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction.xml @@ -0,0 +1,32 @@ + + + HandleRecurringOrderAction + Script 1.0.1.77 + Automation + SKYLINE2\VictorSC + FALSE + YLE/SRM + + + + + + + + + + RecurringOrderInfo + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/GlobalSuppressions.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/GlobalSuppressions.cs new file mode 100644 index 0000000..30d4e41 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Minor Code Smell", "S6602:\"Find\" method should be used instead of the \"FirstOrDefault\" extension", Justification = "", Scope = "member", Target = "~M:HandleRecurringOrderAction_2.RecurringSequenceManager.BookRecurringOrder(System.DateTime)")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/HandleRecurringOrderAction_2.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/HandleRecurringOrderAction_2.csproj new file mode 100644 index 0000000..c187f47 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/HandleRecurringOrderAction_2.csproj @@ -0,0 +1,104 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {2F80BDCE-7606-4F23-99CE-B980E1E8C70E} + Library + Properties + HandleRecurringOrderAction_2 + HandleRecurringOrderAction_2 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\HandleRecurringOrderAction_2.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\HandleRecurringOrderAction_2.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + 13.0.3 + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a0395db --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("HandleRecurringOrderAction_2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("HandleRecurringOrderAction_2")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("54C01101-D832-4B52-92D3-77E3AC995D37")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/RecurringSequenceManager.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/RecurringSequenceManager.cs new file mode 100644 index 0000000..e3b96a7 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/RecurringSequenceManager.cs @@ -0,0 +1,373 @@ +namespace HandleRecurringOrderAction_2 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notifications; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.OrderManagerElement; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Status = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Status; + + public class RecurringSequenceManager : IDisposable + { + private readonly TimeSpan slidingWindowSize; + private readonly int maxBookingAmount; + private readonly OrderTemplate template; + private readonly Helpers helpers; + private readonly RecurringSequenceInfo recurringSequenceInfo; + private readonly List allFutureOccurrences; + private readonly List allExistingOrders; + private readonly UserInfo userInfo; + private readonly Event _event; + + // DCP200430 + private readonly Dictionary> vizremOrdersUnableToBook = new Dictionary>(); + + public RecurringSequenceManager(Helpers helpers, RecurringSequenceInfo recurringOrderInfo) + { + this.helpers = helpers ?? throw new ArgumentNullException(nameof(helpers)); + this.slidingWindowSize = helpers.OrderManagerElement.GetRecurringOrdersSlidingWindowSize(); + this.maxBookingAmount = helpers.OrderManagerElement.GetRecurringOrdersMaxBookingAmount(); + this.recurringSequenceInfo = recurringOrderInfo ?? throw new ArgumentNullException(nameof(recurringOrderInfo)); + + if (!helpers.ContractManager.TryGetOrderTemplate(recurringOrderInfo.TemplateId, out this.template)) + { + throw new ArgumentException($"Unable to retrieve order template {recurringOrderInfo.TemplateId}", nameof(recurringOrderInfo)); + } + + this._event = helpers.EventManager.GetEvent(recurringOrderInfo.EventId); + + this.userInfo = string.IsNullOrWhiteSpace(template.CreatedByUserName) ? null : helpers.ContractManager.GetUserInfo(template.CreatedByUserName, _event); + + allFutureOccurrences = recurringOrderInfo.GetAllFutureOccurrences(); + + Log(nameof(RecurringSequenceManager), $"All occurrences for {recurringSequenceInfo.Name}: {string.Join(";", allFutureOccurrences.Select(o => o.ToString("o")))}"); + + this.allExistingOrders = helpers.OrderManager.GetAllReservationInstancesFromTemplate(recurringOrderInfo.TemplateId).ToList(); + + Log(nameof(RecurringSequenceManager), $"All existing orders for {recurringSequenceInfo.Name}: '{string.Join(", ", allExistingOrders.Select(o => $"{o.Name}({o.ID})"))}'"); + + Log(nameof(RecurringSequenceManager), $"Template has{(recurringSequenceInfo.TemplateIsUpdated ? string.Empty : " not")} been updated."); + // Boolean is true when + // - Reprocess button was pressed in Recurring Orders table in Order Manager element + // - Recurring Order Sequence was edited using LOF + // Boolean is false when daily evaluation is triggered by Order Manager timer + } + + public void ProcessRecurringOrderInfo() + { + try + { + if (recurringSequenceInfo.TemplateId == Guid.Empty) + { + Log(nameof(ProcessRecurringOrderInfo), $"Recurring order {recurringSequenceInfo.Name} has empty template ID."); + return; + } + + if (recurringSequenceInfo.TemplateIsUpdated || recurringSequenceInfo.Recurrence.EffectiveEndDate < DateTime.Now) + { + DeleteAllFutureRecurringOrders(); + } + + BookNewRecurringOrders(); + + HandleRecurrenceEnding(); + + ReportResults(); + } + catch (Exception e) + { + Log(nameof(ProcessRecurringOrderInfo), $"Something went wrong: {e}"); + } + } + + private void ReportResults() + { + foreach (var failedOrder in vizremOrdersUnableToBook) + { + NotificationManager.SendUnableToBookVizremOrderMail(helpers, failedOrder.Key, failedOrder.Value); + } + } + + private void BookNewRecurringOrders() + { + var now = DateTime.Now; + + var existingOrderOccurrences = allExistingOrders.Select(x => x.Start.FromReservation().Add(x.GetPreRoll())).ToList(); + Log(nameof(BookNewRecurringOrders), $"All existing reservations for {recurringSequenceInfo.Name}: {string.Join(";", existingOrderOccurrences.Select(o => o.ToString("o")))}"); + + int bookingCounter = 0; + foreach (var occurrence in allFutureOccurrences) + { + var existingOrderForThisDay = allExistingOrders.SingleOrDefault(o => occurrence.Date <= o.Start && o.Start <= occurrence.Date.AddDays(1)); + if (existingOrderForThisDay != null) + { + Log(nameof(BookNewRecurringOrders), $"Order {existingOrderForThisDay.Name}({existingOrderForThisDay.ID}) already exists for occurrence {occurrence}, no need to create new one"); + continue; + } + + bool occurrenceFallsWithinSlidingWindow = recurringSequenceInfo.Recurrence.StartTime <= occurrence && occurrence <= now + slidingWindowSize; + if (!occurrenceFallsWithinSlidingWindow) continue; + + bool occurrenceAlreadyExists = existingOrderOccurrences.Any(o => o == occurrence); + if (occurrenceAlreadyExists) + { + Log(nameof(BookNewRecurringOrders), $"Recurring order {recurringSequenceInfo.Name} occurrence {occurrence.ToString("o")} already exists"); + continue; + } + + BookRecurringOrder(occurrence); + + if (++bookingCounter >= maxBookingAmount) + { + Log(nameof(BookNewRecurringOrders), $"Booked the max of {maxBookingAmount} new orders for {recurringSequenceInfo.Name}, aborting script."); + break; + } + } + } + + private void HandleRecurrenceEnding() + { + bool recurrenceHasEnded = !allFutureOccurrences.Any() && !allExistingOrders.Any(o => DateTime.Now <= o.Start.FromReservation().Add(o.GetPreRoll())); + + if (recurrenceHasEnded) + { + Log(nameof(HandleRecurrenceEnding), $"Recurrence {recurringSequenceInfo.Name} has ended, deleting order template, event (if empty) and recurring order row..."); + + // Delete Template + if (!helpers.ContractManager.TryDeleteOrderTemplate(recurringSequenceInfo.TemplateId)) + { + Log(nameof(DeleteRecurringOrder), $"Unable to delete order template {recurringSequenceInfo.TemplateId}"); + } + + // Delete Event if empty + if (_event != null && !helpers.EventManager.GetLiteOrdersInEvent(_event.Id).Any()) + { + helpers.EventManager.DeleteEvent(_event.Id); + } + + // Delete Recurring Orders table row + helpers.OrderManagerElement.DeleteRow(2400, recurringSequenceInfo.TemplateId.ToString()); + } + } + + private bool OrderTimingMatchesRecurrenceSequence(ReservationInstance existingOrder) + { + var orderStart = existingOrder.Start.FromReservation().Add(existingOrder.GetPreRoll()); + var orderEnd = existingOrder.End.FromReservation().Add(-existingOrder.GetPostRoll()); + + bool orderStartsBeforeRecurrenceEnd = orderStart < recurringSequenceInfo.Recurrence.EffectiveEndDate; + + Log(nameof(OrderTimingMatchesRecurrenceSequence), $"Existing order {existingOrder.Name} start {orderStart.ToString("o")} falls {(orderStartsBeforeRecurrenceEnd ? "inside" : "outside")} recurrence end {recurringSequenceInfo.Recurrence.EffectiveEndDate.ToString("o")}"); + + bool orderStartTimeMatchesSequence = allFutureOccurrences.Any(occurrence => occurrence == orderStart); + + Log(nameof(OrderTimingMatchesRecurrenceSequence), $"Existing order {existingOrder.Name} start {orderStart.ToString("o")} {(orderStartTimeMatchesSequence ? "matches a" : "does not match any")} value from {string.Join(" ; ", allFutureOccurrences.Select(o => o.ToString("o")))}"); + + var allOccurrenceEndTimes = allFutureOccurrences.Select(o => o.Add(template.Duration)).ToList(); + bool orderEndTimeMatchesSequence = allOccurrenceEndTimes.Any(occurrenceEnd => occurrenceEnd == orderEnd); + + Log(nameof(OrderTimingMatchesRecurrenceSequence), $"Existing order {existingOrder.Name} end {orderEnd.ToString("o")} {(orderEndTimeMatchesSequence ? "matches a" : "does not match any")} value from {string.Join(" ; ", allOccurrenceEndTimes.Select(o => o.ToString("o")))}"); + + return orderStartsBeforeRecurrenceEnd && orderStartTimeMatchesSequence && orderEndTimeMatchesSequence; + } + + private Status DetermineOrderStatus(Order order) + { + if (order.AllServices.Exists(s => s.Definition.Name.Contains("Unknown"))) + { + return Status.PlannedUnknownSource; + } + else + { + return userInfo != null && userInfo.IsMcrUser ? Status.Confirmed : Status.Planned; + } + } + + private void BookRecurringOrder(DateTime occurrence) + { + var order = Order.FromTemplate(helpers, template, $"{recurringSequenceInfo.Name} [{occurrence.ToFinnishDateString()}]", occurrence); + + order.Status = DetermineOrderStatus(order); + + order.CreatedByUserName = string.IsNullOrWhiteSpace(template.CreatedByUserName) ? "DataMiner Agent" : template.CreatedByUserName; + order.LastUpdatedBy = "DataMiner Agent"; + order.Event = _event; + + if (order.Subtype == OrderSubType.Vizrem) + { + order.IsInternal = true; + + foreach (var service in order.AllServices) + { + if (!service.AllCurrentlyAssignedResourcesAreAvailable(helpers, out var unavailableResources)) + { + Log(nameof(BookRecurringOrder), $"Resources {string.Join(", ", unavailableResources.Select(r => r.Name))} used in VIZREM order {order.Name} are not available, order will not be created"); + + vizremOrdersUnableToBook.Add(order, unavailableResources); + return; + } + } + } + + var tasks = order.AddOrUpdate(helpers, false).Tasks; + + var failedBlockingTask = tasks.FirstOrDefault(t => t.IsBlocking && t.Status == Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.Status.Fail); + bool orderAddOrUpdateFailed = failedBlockingTask != null; + if (orderAddOrUpdateFailed) + { + Log(nameof(BookRecurringOrder), $"Failed to book recurred order {order.Name} (start {occurrence.ToString("o")}): {failedBlockingTask.Exception}"); + } + else + { + Log(nameof(BookRecurringOrder), $"Successfully booked recurred order {order.Name} (start {occurrence.ToString("o")})"); + } + } + + private void DeleteRecurringOrder(ReservationInstance orderReservation) + { + Log(nameof(DeleteRecurringOrder), $"Deleting existing recurring order {orderReservation.Name}"); + + ManageBookServicesFlow(orderReservation.ID); + + helpers.OrderManager.DeleteOrder(orderReservation.ID); + } + + private void ManageBookServicesFlow(Guid orderId) + { + bool orderHasOngoingBookServicesProcess = helpers.OrderManagerElement.TryGetBookServicesStatus(orderId, out BookServicesStatus bookServicesStatus) && bookServicesStatus == BookServicesStatus.Ongoing; + var timeoutTimer = TimeSpan.Zero; + + while (orderHasOngoingBookServicesProcess && timeoutTimer < TimeSpan.FromMinutes(2)) + { + Log(nameof(ManageBookServicesFlow), $"Entry {orderId} has status {bookServicesStatus.ToString()} in Orders table in Order Manager element, waiting 10 seconds..."); + + var fiveSeconds = TimeSpan.FromSeconds(5); + Thread.Sleep(fiveSeconds); + timeoutTimer += fiveSeconds; + + orderHasOngoingBookServicesProcess = helpers.OrderManagerElement.TryGetBookServicesStatus(orderId, out bookServicesStatus) && bookServicesStatus == BookServicesStatus.Ongoing; + } + } + + private void VerifyAndDeleteRecurringOrders() + { + // Delete order in case of + // - name not matching with recurrence sequence + // - timing not matching with recurrence sequence + // - updated template + + Log(nameof(VerifyAndDeleteRecurringOrders), $"Template has{(recurringSequenceInfo.TemplateIsUpdated ? string.Empty : " not")} been updated."); + + if (recurringSequenceInfo.TemplateIsUpdated || recurringSequenceInfo.Recurrence.EffectiveEndDate < DateTime.Now) + { + DeleteAllFutureRecurringOrders(); + } + else if(recurringSequenceInfo.Recurrence.EffectiveEndDate < DateTime.Now) + { + var deletedOrderIds = new List(); + + foreach (var existingOrder in allExistingOrders) + { + bool orderTimingMatchesRecurrenceSequence = OrderTimingMatchesRecurrenceSequence(existingOrder); + + bool orderNameMatchesSequence = OrderNameMatchesSequence(existingOrder); + + if ((!orderTimingMatchesRecurrenceSequence || !orderNameMatchesSequence) && TryDeleteOrder(existingOrder)) + { + deletedOrderIds.Add(existingOrder.ID); + } + } + + allExistingOrders.RemoveAll(o => deletedOrderIds.Contains(o.ID)); + } + else + { + // nothing + } + } + + private bool OrderNameMatchesSequence(ReservationInstance existingOrder) + { + var orderName = existingOrder.Name.Contains(" [") ? existingOrder.Name.Substring(0, existingOrder.Name.LastIndexOf(" [", StringComparison.InvariantCulture)) : existingOrder.Name; + + bool orderNameMatchesSequence = orderName == recurringSequenceInfo.Name; + + Log(nameof(OrderNameMatchesSequence), $"Existing order name {orderName} {(orderNameMatchesSequence ? "matches" : "does not match")} recurring sequence name {recurringSequenceInfo.Name}"); + + return orderNameMatchesSequence; + } + + private bool TryDeleteOrder(ReservationInstance existingOrder) + { + var orderLock = helpers.LockManager.RequestOrderLock(existingOrder.ID); + + if (orderLock.IsLockGranted) + { + DeleteRecurringOrder(existingOrder); + return true; + } + else + { + Log(nameof(VerifyAndDeleteRecurringOrders), $"Unable to delete order {existingOrder.Name} because lock was not granted"); + return false; + } + } + + private void DeleteAllFutureRecurringOrders() + { + var deletedOrderIds = new List(); + + foreach (var order in allExistingOrders.Where(o => DateTime.Now <= o.Start)) + { + if (TryDeleteOrder(order)) + { + deletedOrderIds.Add(order.ID); + } + } + + allExistingOrders.RemoveAll(o => deletedOrderIds.Contains(o.ID)); + } + + private void Log(string nameOfMethod, string message, string nameOfObject = null) + { + helpers.Log(nameof(RecurringSequenceManager), nameOfMethod, message, nameOfObject); + } + + #region IDisposable Support + private bool disposedValue; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + ~RecurringSequenceManager() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/Script.cs new file mode 100644 index 0000000..a3398bb --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/Script.cs @@ -0,0 +1,113 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version + +**************************************************************************** +*/ + + + +//--------------------------------- +// HandleRecurringOrderAction_2.cs +//--------------------------------- + +namespace HandleRecurringOrderAction_2 +{ + using System; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order.Recurrence; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + /// + /// DataMiner Script Class. + /// + class Script + { + /// + /// The Script entry point. + /// + /// Link with SLAutomation process. + public void Run(Engine engine) + { + engine.SetFlag(RunTimeFlags.NoKeyCaching); + engine.Timeout = TimeSpan.FromMinutes(30); + + var helpers = new Helpers(engine, Scripts.HandleRecurringOrderAction); + + try + { + var scriptInput = Convert.ToString(engine.GetScriptParam(1).Value); + + var recurringOrderInfo = JsonConvert.DeserializeObject(scriptInput); + + if (recurringOrderInfo == null) + { + helpers.Log(nameof(Script), nameof(Run), $"Recurring Order Info is null"); + return; + } + + helpers.OrderManagerElement.SetHandleRecurringOrderActionScriptIsRunningFlag(true, recurringOrderInfo.Name); + + var recurringOrdersManager = new RecurringSequenceManager(helpers, recurringOrderInfo); + + recurringOrdersManager.ProcessRecurringOrderInfo(); + } + catch(Exception e) + { + helpers.Log(nameof(Script), nameof(Run), $"Exception occurred: {e}"); + } + finally + { + helpers.OrderManagerElement.SetHandleRecurringOrderActionScriptIsRunningFlag(false); + helpers.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleRecurringOrderAction_2/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction.xml new file mode 100644 index 0000000..c53f299 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction.xml @@ -0,0 +1,36 @@ + + + HandleServiceAction + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/SRM + + + + + + + + + + Action + + + Booking Manager Info + + + ReservationGuid + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/HandleServiceAction_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/HandleServiceAction_1.csproj new file mode 100644 index 0000000..9752598 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/HandleServiceAction_1.csproj @@ -0,0 +1,100 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {C5A5B136-224B-43B4-B220-C677BF4D8294} + Library + Properties + HandleServiceAction_1 + HandleServiceAction_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\HandleServiceAction_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\HandleServiceAction_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..20e33e8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("HandleServiceAction_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("HandleServiceAction_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("361EDED2-F639-4AC7-BF0C-DD922F89E341")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/Script.cs new file mode 100644 index 0000000..3d9dca5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/Script.cs @@ -0,0 +1,160 @@ +/* +**************************************************************************** +* Copyright (c) 2020, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2020 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace HandleServiceAction_1 +{ + using System; + using System.Diagnostics; + using System.Linq; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Net.Messages; + + /// + /// DataMiner Script Class. + /// + public class Script : IDisposable + { + private Helpers helpers; + + public void Run(Engine engine) + { + try + { + Initialize(engine); + + var serviceReservationId = Guid.Parse(engine.GetScriptParam("ReservationGuid").Value); + + var service = helpers.ServiceManager.GetService(serviceReservationId) ?? throw new ServiceNotFoundException(serviceReservationId); + + var orderReservationId = service.OrderReferences.First(); + + helpers.AddOrderReferencesForLogging(orderReservationId); + + var rawAction = engine.GetScriptParam("Action").Value.ToLower(); + var rawBookingManagerInfo = engine.GetScriptParam("Booking Manager Info").Value; + + Log(nameof(Run), $"Launching script UpdateServiceStatus asynchronous from Handle Service Action"); + + engine.SendSLNetSingleResponseMessage(new ExecuteScriptMessage("UpdateServiceStatus") + { + Options = new SA(new[] + { + $"PARAMETER:3:{rawAction}", + $"PARAMETER:4:{rawBookingManagerInfo}", + $"PARAMETER:5:{serviceReservationId}", + "OPTIONS:0", + "CHECKSETS:FALSE", + "EXTENDED_ERROR_INFO", + "DEFER:TRUE" // async execution + }) + }); + } + catch (Exception e) + { + Log(nameof(Run), $"Exception handling service action: {e}"); + } + finally + { + Dispose(); + } + } + + private void Initialize(Engine engine) + { + engine.Timeout = TimeSpan.FromHours(1); + engine.SetFlag(RunTimeFlags.NoKeyCaching); + + this.helpers = new Helpers(engine, Scripts.HandleServiceAction); + } + + private void Log(string nameOfMethod, string message, string nameOfObject = null) + { + helpers?.Log(nameof(Script), nameOfMethod, message, nameOfObject); + } + + #region IDisposable Support + private bool disposedValue; // To detect redundant calls + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + // override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. + ~Script() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(false); + } + + // This code added to correctly implement the disposable pattern. + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + + // Uncomment the following line if the finalizer is overridden above. + GC.SuppressFinalize(this); + } + #endregion + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceAction_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure.xml new file mode 100644 index 0000000..32a40f8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure.xml @@ -0,0 +1,31 @@ + + + HandleServiceStartFailure + Script 1.0.1.77 + Automation + SKYLINE2\Joey + FALSE + YLE/SRM + + + + + + + + + + ErrorData + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/HandleServiceStartFailure_1.csproj b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/HandleServiceStartFailure_1.csproj new file mode 100644 index 0000000..9577cad --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/HandleServiceStartFailure_1.csproj @@ -0,0 +1,103 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {DB1D40BF-6C1B-4565-B629-4647834B8F40} + Library + Properties + HandleServiceStartFailure_1 + HandleServiceStartFailure_1 + v4.7.2 + 512 + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-debug.ruleset + bin\Debug\HandleServiceStartFailure_1.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + ..\Internal\Code Analysis\qaction-release.ruleset + bin\Release\HandleServiceStartFailure_1.xml + + + None + + + + ..\Dlls\SLMediationSnippets.dll + + + ..\Dlls\SLSRMLibrary.dll + C:\Skyline DataMiner\Files\SLSRMLibrary.dll + + + + + + + + + + + + + + + + + + + + + + + + + + 13.0.3 + + + 10.3.5 + + + 7.0.1 + + + + + {121dd302-df4b-4f49-b6f9-b3ad358bd842} + Library_1 + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/Properties/AssemblyInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..85c5d16 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("HandleServiceStartFailure_1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Skyline Communications")] +[assembly: AssemblyProduct("HandleServiceStartFailure_1")] +[assembly: AssemblyCopyright("Copyright © Skyline Communications")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("28A631DF-C81F-43D1-96BC-FC193B0171DF")] +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/Script.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/Script.cs new file mode 100644 index 0000000..c9bac56 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/Script.cs @@ -0,0 +1,187 @@ +/* +**************************************************************************** +* Copyright (c) 2021, Skyline Communications NV All Rights Reserved. * +**************************************************************************** + +By using this script, you expressly agree with the usage terms and +conditions set out below. +This script and all related materials are protected by copyrights and +other intellectual property rights that exclusively belong +to Skyline Communications. + +A user license granted for this script is strictly for personal use only. +This script may not be used in any way by anyone without the prior +written consent of Skyline Communications. Any sublicensing of this +script is forbidden. + +Any modifications to this script by the user are only allowed for +personal use and within the intended purpose of the script, +and will remain the sole responsibility of the user. +Skyline Communications will not be responsible for any damages or +malfunctions whatsoever of the script resulting from a modification +or adaptation by the user. + +The content of this script is confidential information. +The user hereby agrees to keep this confidential information strictly +secret and confidential and not to disclose or reveal it, in whole +or in part, directly or indirectly to any person, entity, organization +or administration without the prior written consent of +Skyline Communications. + +Any inquiries can be addressed to: + + Skyline Communications NV + Ambachtenstraat 33 + B-8870 Izegem + Belgium + Tel. : +32 51 31 35 69 + Fax. : +32 51 31 01 29 + E-mail : info@skyline.be + Web : www.skyline.be + Contact : Ben Vandenberghe + +**************************************************************************** +Revision History: + +DATE VERSION AUTHOR COMMENTS + +dd/mm/2021 1.0.0.1 XXX, Skyline Initial version +**************************************************************************** +*/ + +namespace HandleServiceStartFailure_1 +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Notifications; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Automation; + using Skyline.DataMiner.Library.Solutions.SRM.Model.StartBookingFailure; + using Skyline.DataMiner.Net.ResourceManager.Objects; + using Service = Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service.Service; + + /// + /// DataMiner Script Class. + /// + public class Script : IDisposable + { + private Helpers helpers; + private bool disposedValue; + + /// + /// Script entry point. + /// + /// Link to DataMiner. + public void Run(Engine engine) + { + helpers = new Helpers(engine, Scripts.HandleServiceStartFailure); + + try + { + // Attention: This line needs to be always like this, if the custom converter is not used, it will throw an exception + var errorData = engine.GetScriptParamValue( + "ErrorData", + rawData => JsonConvert.DeserializeObject>( + rawData, + new StartActionsFailureErrorDataConverter() + ) + ); + + // Will handle the errors. + // Custom handling can be implemented in HandlerError + HandleError(errorData); + + Dispose(); + } + catch (Exception e) + { + string scriptInput = engine.GetScriptParam("ErrorData").Value; + + NotificationManager.SendMailToSkylineDevelopers(helpers, "Service Start Failure", $"An error occurred while executing the HandleServiceStartFailure script with input: {scriptInput}"); + + engine.GenerateInformation($"Script Booking Start Failure Template failed due to: {e}"); + + Dispose(); + + // Optional: Reports the correct exception to the caller script + AutomationScript.HandleException(engine, e); + } + } + + public void HandleError(List errorData) + { + foreach (var item in errorData) + { + string errorMessage = GetErrorMessage(item); + + var serviceId = item.ReservationInstanceId; + var service = serviceId.HasValue ? helpers.ServiceManager.GetService(serviceId.Value) : null; + + if (service == null) + { + helpers.Log(nameof(Script), nameof(HandleError), $"Unknown service could not be started: {errorMessage}"); + continue; + } + + if (service.OrderReferences == null || !service.OrderReferences.Any()) + { + helpers.Log(nameof(Script), nameof(HandleError), $"Service {item.ReservationInstanceId} could not be started: {errorMessage}"); + continue; + } + + string message = $"Service {service.Name} ({service.Id}) part of Order(s) {string.Join(", ", service.OrderReferences)} could not be started:\n {errorMessage}"; + + NotificationManager.SendMailToSkylineDevelopers(helpers, $"Service Start Failure", message); + + helpers.Log(nameof(Script), nameof(HandleError), message); + + helpers.AddOrderReferencesForLogging(service.OrderReferences.ToArray()); + } + } + + private static string GetErrorMessage(StartActionsFailureErrorData item) + { + switch (item.ErrorReason) + { + case StartActionsFailureErrorData.Reason.UnexpectedException: + return "Reservation failed to start due an unexpected exception"; + case StartActionsFailureErrorData.Reason.ResourceElementNotActive: + return $"Reservation failed to start due to resource element {item.Resource.DmaID}/{item.Resource.ElementID} was not set to active when the reservation started"; + case StartActionsFailureErrorData.Reason.ReservationInstanceNotFound: + return "Reservation failed to start due to reservation instance not found."; + default: + return "Reservation failed to start due an unknown reason."; + } + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + helpers.Dispose(); + } + + disposedValue = true; + } + } + + ~Script() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: false); + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/app.config b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/app.config new file mode 100644 index 0000000..fda1974 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/stylecop.json b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/stylecop.json new file mode 100644 index 0000000..3703ae9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/HandleServiceStartFailure_1/stylecop.json @@ -0,0 +1,76 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [ + "ab", + "ac", + "ad", + "af", + "ai", + "al", + "ao", + "as", + "ax", + "b", + "by", + "c", + "d", + "dt", + "e", + "f", + "hs", + "i", + "ip", + "is", + "l", + "lb", + "lc", + "ld", + "lf", + "li", + "ll", + "lo", + "ls", + "lx", + "my", + "no", + "o", + "qb", + "qc", + "qd", + "qf", + "qi", + "ql", + "qo", + "qs", + "qx", + "rx", + "s", + "sb", + "sc", + "sd", + "sf", + "sh", + "si", + "sl", + "so", + "ss", + "sx", + "to", + "ts", + "tx", + "ui", + "ul", + "x" + ] + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Internal/Code Analysis/qaction-debug.ruleset b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Internal/Code Analysis/qaction-debug.ruleset new file mode 100644 index 0000000..26e7d46 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Internal/Code Analysis/qaction-debug.ruleset @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Internal/Code Analysis/qaction-release.ruleset b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Internal/Code Analysis/qaction-release.ruleset new file mode 100644 index 0000000..de0890a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Internal/Code Analysis/qaction-release.ruleset @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library.xml b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library.xml new file mode 100644 index 0000000..e8fdbfb --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library.xml @@ -0,0 +1,28 @@ + + + Library + Script 1.0.1.77 + Automation + SKYLINE2\ThomasRE + FALSE + YLE/Library + + + + + + + + + + + + \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/.editorconfig b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/.editorconfig new file mode 100644 index 0000000..a612a7a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = crlf +trim_trailing_whitespace = true + +[*.cs] +dotnet_sort_system_directives_first = true \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/AvidInterplayPamManager.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/AvidInterplayPamManager.cs new file mode 100644 index 0000000..c0ffb9d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/AvidInterplayPamManager.cs @@ -0,0 +1,215 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.AvidInterplayPAM +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + + using Newtonsoft.Json; + + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.AvidInterplayPAM; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.NonLive; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class AvidInterplayPamManager : INonLiveIntegrationManager + { + private readonly int sleepTimeForElementCommunication = 100; + + private readonly int maxAmountOfRetriesForElementCommunication = 20; + + private readonly int sleepTimeForResponse = 250; + + private readonly int maxAmountOfRetriesForResponse = 80; + + private readonly Element element; + + private readonly List cachedResponses = new List(); + + public Helpers Helpers { get; private set; } + + public AvidInterplayPamManager(Helpers helpers, InterplayPamElements elementName) + { + Helpers = helpers ?? throw new ArgumentNullException(nameof(helpers)); + var allIplayElements = helpers.Engine.FindElementsByProtocol(AvidInterplayPamProtocol.Name); + + switch (elementName) + { + case InterplayPamElements.Helsinki: + element = allIplayElements.SingleOrDefault(e => e.ElementName.Contains("Helsinki") || e.ElementName.Contains("helsinki") || e.ElementName.Contains("HKI")); + if (element == null) + throw new ElementNotFoundException(AvidInterplayPamProtocol.Name, InterplayPamElements.Helsinki); + break; + case InterplayPamElements.Tampere: + element = allIplayElements.SingleOrDefault(e => e.ElementName.Contains("Tampere") || e.ElementName.Contains("tampere") || e.ElementName.Contains("TRE")); + if (element == null) + throw new ElementNotFoundException(AvidInterplayPamProtocol.Name, InterplayPamElements.Tampere); + break; + case InterplayPamElements.Vaasa: + element = allIplayElements.SingleOrDefault(e => e.ElementName.Contains("Vaasa") || e.ElementName.Contains("vaasa") || e.ElementName.Contains("VSA")); + if (element == null) + throw new ElementNotFoundException(AvidInterplayPamProtocol.Name, InterplayPamElements.Vaasa); + break; + default: + throw new ArgumentException(nameof(elementName)); + } + } + + public List GetRootFolders() + { + var response = GetFilesAndFolders(String.Empty); + var rootFolders = new List(); + foreach(string rootPath in response.AccessiblePaths) + { + string friendlyName = rootPath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last(); + rootFolders.Add(new Folder { FriendlyName = friendlyName, URL = rootPath }); + } + + return rootFolders; + } + + public NonLiveManagerResponse GetChildren(string parentPath) + { + var response = GetFilesAndFolders(parentPath); + return new NonLiveManagerResponse + { + Files = response.RequestedFiles, + Folders = response.RequestedFolders + }; + } + + private Response GetFilesAndFolders(string folderPath) + { + return GetFilesAndFolders(Helpers.Engine.UserLoginName, folderPath); + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + private Response GetFilesAndFolders(string userLoginName, string folderPath) + { + if (String.IsNullOrWhiteSpace(userLoginName)) throw new ArgumentNullException(nameof(userLoginName)); + + if (!element.IsActive) throw new ElementNotActiveException(element.Name); + + Response response; + if (cachedResponses.Any(r => r.RequestedFolderPath == folderPath)) + { + response = GetCachedResponse(folderPath); + } + else + { + SendRequest(userLoginName, folderPath, out string requestId); + + if (!RequestSuccessfullyReceivedByElement(requestId)) + throw new ElementDidNotLogRequestException(element.ElementName); + + if (!RequestSuccessfullyProcessedByElement(requestId)) + throw new IplayServiceDidNotRespondException(element.ElementName); + + response = GetResponse(requestId); + + SetFullUrlsAndFriendlyNamesOnFolders(response, folderPath); + + CacheResponse(folderPath, response); + } + + return response; + } + + private Response GetCachedResponse(string folderPath) + { + return cachedResponses.Single(r => r.RequestedFolderPath == folderPath).Response; + } + + private void CacheResponse(string folderPath, Response response) + { + cachedResponses.Add(new CachedResponse { RequestedFolderPath = folderPath, Response = response }); + } + + private void SendRequest(string userLoginName, string folderPath, out string requestId) + { + requestId = Guid.NewGuid().ToString(); + + Request request = new Request { Id = requestId, Username = userLoginName, FolderPath = folderPath }; + + element.SetParameter(AvidInterplayPamProtocol.Parameter.ExternalFolderRequest, JsonConvert.SerializeObject(request, Formatting.None)); + } + + private bool RequestSuccessfullyReceivedByElement(string requestId) + { + int retries = 0; + string[] requestKeys; + do + { + requestKeys = element.GetTablePrimaryKeys(AvidInterplayPamProtocol.FolderRequestsTable.PID); + retries++; + Thread.Sleep(sleepTimeForElementCommunication); + } + while (retries < maxAmountOfRetriesForElementCommunication && !requestKeys.Contains(requestId)); + + bool requestSuccessfullyReceived = requestKeys.Contains(requestId); + + if (!requestSuccessfullyReceived) + Helpers.Log(nameof(AvidInterplayPamManager), nameof(RequestSuccessfullyReceivedByElement), "Request not successfully received"); + + return requestSuccessfullyReceived; + } + + private bool RequestSuccessfullyProcessedByElement(string requestId) + { + int retries = 0; + RequestStatus requestStatus; + do + { + requestStatus = (RequestStatus)Convert.ToInt32(element.GetParameterByPrimaryKey(AvidInterplayPamProtocol.FolderRequestsTable.StatusColumnPid, requestId)); + retries++; + + Thread.Sleep(sleepTimeForResponse); + } + while (retries < maxAmountOfRetriesForResponse && requestStatus == RequestStatus.Pending); + + bool requestSuccessfullyProcessed = requestStatus == RequestStatus.Completed; + + if (!requestSuccessfullyProcessed) + Helpers.Log(nameof(AvidInterplayPamManager), nameof(RequestSuccessfullyProcessedByElement), "Request not successfully processed"); + + return requestSuccessfullyProcessed; + } + + private Response GetResponse(string requestId) + { + string responseString = null; + try + { + responseString = element.GetParameterByPrimaryKey(AvidInterplayPamProtocol.FolderRequestsTable.ResponseColumnPid, requestId).ToString(); + + Response response = JsonConvert.DeserializeObject(responseString); + + return response; + } + catch (Exception) + { + Helpers.Log(nameof(AvidInterplayPamManager), nameof(GetResponse), $"Exception while deserializing {responseString}"); + throw; + } + } + + private void SetFullUrlsAndFriendlyNamesOnFolders(Response response, string folderPath) + { + foreach (var folder in response.RequestedFolders) + { + folder.FriendlyName = folder.URL.Trim('/'); + folder.URL = folderPath + folder.URL; + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/CachedResponse.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/CachedResponse.cs new file mode 100644 index 0000000..c3d70d8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/CachedResponse.cs @@ -0,0 +1,15 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.AvidInterplayPAM +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + + public class CachedResponse + { + public string RequestedFolderPath { get; set; } + + public Response Response { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Enums.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Enums.cs new file mode 100644 index 0000000..28ab73f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Enums.cs @@ -0,0 +1,33 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.AvidInterplayPAM +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + + public enum InterplayPamElements + { + [Description("IPLAY Helsinki")] + Helsinki, + + [Description("IPLAY Tampere")] + Tampere, + + [Description("IPLAY Vaasa")] + Vaasa, + + [Description("IPLAY UA")] + UA + } + + public enum RequestStatus + { + Pending = 0, + + Completed = 1, + + Failed = 2 + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/File.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/File.cs new file mode 100644 index 0000000..5ba911d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/File.cs @@ -0,0 +1,24 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.AvidInterplayPAM +{ + public class File + { + public string URL { get; set; } + + public string Parent { get; set; } + + public string DisplayName { get; set; } + + public override bool Equals(object obj) + { + File other = obj as File; + if (other == null) return false; + + return this.URL == other.URL; + } + + public override int GetHashCode() + { + return URL.GetHashCode(); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Folder.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Folder.cs new file mode 100644 index 0000000..babd0f5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Folder.cs @@ -0,0 +1,80 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.AvidInterplayPAM +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + + public class Folder + { + public string URL { get; set; } + + public string FriendlyName { get; set; } + + public HashSet Children { get; set; } = new HashSet(); + + public HashSet Files { get; set; } = new HashSet(); + + public void Update(string folderPath, IEnumerable folders) + { + if (this.URL == folderPath) + { + foreach (Folder folder in folders) Children.Add(folder); + } + else + { + foreach (Folder child in Children) child.Update(folderPath, folders); + } + } + + public bool IsChildOf(string possibleParentFolderUrl) + { + var splitPossibleParentUrl = possibleParentFolderUrl.Split('\\'); + + var splitUrl = URL.Split('\\'); + var splitUrlWithoutLastElement = splitUrl.Take(splitUrl.Length - 1); + + return splitUrlWithoutLastElement.SequenceEqual(splitPossibleParentUrl); + } + + public override bool Equals(object obj) + { + Folder other = obj as Folder; + if (other == null) return false; + + return URL.Equals(other.URL); + } + + public override int GetHashCode() + { + return URL.GetHashCode(); + } + + public List GetAllChildren() + { + List allChildren = new List(); + + foreach (Folder folder in Children) + { + allChildren.Add(folder); + allChildren.AddRange(folder.GetAllChildren()); + } + + return allChildren; + } + + public List GetAllFiles() + { + List allFiles = new List(); + allFiles.AddRange(Files); + + foreach (Folder folder in Children) + { + allFiles.AddRange(folder.GetAllFiles()); + } + + return allFiles; + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Request.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Request.cs new file mode 100644 index 0000000..852d2ae --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Request.cs @@ -0,0 +1,17 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.AvidInterplayPAM +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + + public class Request + { + public string Id { get; set; } + + public string Username { get; set; } + + public string FolderPath { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Response.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Response.cs new file mode 100644 index 0000000..f50f4db --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/AvidInterplayPAM/Response.cs @@ -0,0 +1,15 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.AvidInterplayPAM +{ + public class Response + { + public string Id { get; set; } + + public string Username { get; set; } + + public string[] AccessiblePaths { get; set; } + + public Folder[] RequestedFolders { get; set; } + + public File[] RequestedFiles { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/ChangeTrackedAttribute.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/ChangeTrackedAttribute.cs new file mode 100644 index 0000000..bc3ecf5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/ChangeTrackedAttribute.cs @@ -0,0 +1,10 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking +{ + using System; + + [AttributeUsage(AttributeTargets.Property)] + public class ChangeTrackedAttribute : Attribute + { + + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/ChangeTrackingHelper.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/ChangeTrackingHelper.cs new file mode 100644 index 0000000..2c7957f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/ChangeTrackingHelper.cs @@ -0,0 +1,388 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using NPOI.SS.Formula.Functions; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public static class ChangeTrackingHelper + { + private static List GetChangeTrackedProperties() + { + var properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public); + + var changeTrackedProperties = properties.Where(p => p.GetCustomAttributes(typeof(ChangeTrackedAttribute), true).Any()).ToList(); + + return changeTrackedProperties; + } + + /// + /// Updates the given dictionary with the current values of the ChangeTracked properties of the objectInstance. + /// + /// + /// An instance of type T to take the current values of ChangeTracked properties from. + /// The dictionary of initial values to be updated. + /// Optional Helpers object for logging. + public static void AcceptChanges(T objectInstance, Dictionary initialValues, Helpers helpers = null) + { + helpers?.LogMethodStart(typeof(T).Name, nameof(AcceptChanges), out var stopwatch, ((IYleChangeTracking)objectInstance).UniqueIdentifier); + + foreach (var property in GetChangeTrackedProperties()) + { + var currentValue = property.GetValue(objectInstance); + + helpers?.Log(typeof(T).Name, nameof(AcceptChanges), $"Setting initial value for property {property.Name} to '{currentValue}'"); + + CallAccceptChangesOnChangeTrackingObjects(helpers, property.Name, currentValue); + + SaveCurrentValueAsInitialValue(helpers, initialValues, property, currentValue); + } + + helpers?.Log(typeof(T).Name, nameof(AcceptChanges), $"Initial values: \n{string.Join("\n", initialValues.Select(v => $"{v.Key}={v.Value}"))}"); + + helpers?.LogMethodCompleted(typeof(T).Name, nameof(AcceptChanges)); + } + + public static Change GetUpdatedChange(T objectInstance, Dictionary initialValues, Change changeToUpdate, Helpers helpers = null) + { + foreach (var property in GetChangeTrackedProperties()) + { + try + { + var currentValue = property.GetValue(objectInstance); + + if (currentValue is IYleChangeTracking changeTrackingObject) + { + RegisterChangeTrackingChanges(initialValues, changeToUpdate, changeTrackingObject, property, currentValue, helpers); + } + else if (currentValue is IEnumerable collectionOfChangeTrackingObjects) + { + RegisterChangeTrackingCollectionChanges(initialValues, changeToUpdate, collectionOfChangeTrackingObjects, property, helpers); + } + else if (!(currentValue is string) && currentValue is IEnumerable) + { + RegisterCollectionChanges(initialValues, changeToUpdate, property, currentValue, helpers); + } + else + { + RegisterObjectChanges(initialValues, changeToUpdate, property, currentValue, helpers); + } + } + catch (Exception ex) + { + throw new InvalidOperationException($"Getting change for property {property.Name} failed for object '{((IYleChangeTracking)objectInstance).UniqueIdentifier}' of type {typeof(T).Name}: {ex}"); + } + } + + return changeToUpdate; + } + + private static void RegisterChangeTrackingChanges(Dictionary initialValues, Change changeToUpdate, IYleChangeTracking changeTrackingObject, PropertyInfo property, object currentValue, Helpers helpers = null) + { + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Property {property.Name} implements {nameof(IYleChangeTracking)}"); + + bool successfullyAdded; + if (initialValues[property.Name] is null) + { + successfullyAdded = changeToUpdate.TryAddChange(new PropertyChange(property.Name, string.Empty, currentValue.ToString())); + } + else + { + successfullyAdded = changeToUpdate.TryAddChange(changeTrackingObject.Change); + } + + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Adding change for ChangeTracking object {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + + private static void RegisterChangeTrackingCollectionChanges(Dictionary initialValues, Change changeToUpdate, IEnumerable collectionOfChangeTrackingObjects, PropertyInfo property, Helpers helpers = null) + { + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Property {property.Name} implements IEnumerable<{nameof(IYleChangeTracking)}>"); + + foreach (var changeTrackingItem in collectionOfChangeTrackingObjects) + { + bool successfullyAdded = changeToUpdate.TryAddChange(changeTrackingItem.Change); + + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Adding change for item {changeTrackingItem.UniqueIdentifier} in collection {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + + var initialValue = initialValues[property.Name] as IEnumerable; + + var addedObjects = collectionOfChangeTrackingObjects.Except(initialValue).ToList(); + var removedObjects = initialValue.Except(collectionOfChangeTrackingObjects).ToList(); + + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Removed objects in collection {property.Name}: '{string.Join(", ", removedObjects.Select(o => o.UniqueIdentifier))}'"); + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Added objects in collection {property.Name}: '{string.Join(", ", addedObjects.Select(o => o.UniqueIdentifier))}'"); + + foreach (var addedObject in addedObjects) + { + bool successfullyAdded = changeToUpdate.TryAddChange(new CollectionChanges(property.Name, CollectionChangeType.Add, addedObject.UniqueIdentifier, addedObject.DisplayName)); + + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Adding collection change for added item {addedObject.UniqueIdentifier} in collection {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + + foreach (var removedObject in removedObjects) + { + bool successfullyAdded = changeToUpdate.TryAddChange(new CollectionChanges(property.Name, CollectionChangeType.Remove, removedObject.UniqueIdentifier, removedObject.DisplayName)); + + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Adding collection change for removed item {removedObject.UniqueIdentifier} in collection {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + } + + private static void RegisterCollectionChanges(Dictionary initialValues, Change changeToUpdate, PropertyInfo property, object currentValue, Helpers helpers = null) + { + CollectionChanges collectionChanges = null; + + if (currentValue is IEnumerable integerCollection) + { + var initialCollection = initialValues[property.Name] as IEnumerable; + collectionChanges = CreateCollectionChange(helpers, property.Name, integerCollection, initialCollection); + } + else if (currentValue is IEnumerable stringCollection) + { + var initialCollection = initialValues[property.Name] as IEnumerable; + collectionChanges = CreateCollectionChange(helpers, property.Name, stringCollection, initialCollection); + } + else if (currentValue is IEnumerable guidCollection) + { + var initialCollection = initialValues[property.Name] as IEnumerable; + collectionChanges = CreateCollectionChange(helpers, property.Name, guidCollection, initialCollection); + } + else + { + throw new NotSupportedException($"Property {property.Name} of class {typeof(T).Name} is a collection of an unsupported type"); + } + + if (collectionChanges != null && collectionChanges.Changes.Any()) + { + changeToUpdate.TryAddChange(collectionChanges); + } + } + + private static void RegisterObjectChanges(Dictionary initialValues, Change changeToUpdate, PropertyInfo property, object currentValue, Helpers helpers = null) + { + var initialValueToSave = initialValues[property.Name]?.ToString() ?? String.Empty; + var currentValueToSave = currentValue?.ToString() ?? String.Empty; + + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Accepting value '{currentValueToSave}' for property {property.Name}, initial value is '{initialValueToSave}'"); + + if (initialValueToSave != currentValueToSave) + { + var propertyChangeHistory = new PropertyChange(property.Name, initialValueToSave, currentValueToSave); + + bool successfullyAdded = changeToUpdate.TryAddChange(propertyChangeHistory); + + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Adding change for property {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + } + + public static Change GetChangeComparedTo(T firstObjectInstance, T secondObjectInstance, Change changeToUpdate, Helpers helpers = null) + { + foreach (var property in GetChangeTrackedProperties()) + { + var firstValue = property.GetValue(firstObjectInstance); + var secondValue = property.GetValue(secondObjectInstance); + + if (firstValue is IYleChangeTracking firstChangeTrackingObject) + { + RegisterChangeTrackingChangeComparedTo(firstChangeTrackingObject, secondValue, property, changeToUpdate, helpers); + } + else if (firstValue is IEnumerable firstCollectionOfChangeTrackingObjects && secondValue is IEnumerable secondCollectionOfChangeTrackingObjects) + { + RegisterChangeTrackingCollectionChangeComparedTo(firstCollectionOfChangeTrackingObjects, secondCollectionOfChangeTrackingObjects, property, changeToUpdate, helpers); + } + else if (!(firstValue is string) && firstValue is IEnumerable) + { + RegisterCollectionChangesComparedTo(firstValue, secondValue, property, changeToUpdate, helpers); + } + else + { + RegisterObjectChangesComparedTo(firstValue, secondValue, property, changeToUpdate, helpers); + } + } + + return changeToUpdate; + } + + private static void RegisterChangeTrackingChangeComparedTo(IYleChangeTracking firstValue, object secondValue, PropertyInfo property, Change changeToUpdate, Helpers helpers = null) + { + helpers?.Log(typeof(T).Name, nameof(GetChangeComparedTo), $"Property {property.Name} implements {nameof(IYleChangeTracking)}"); + + bool successfullyAdded = false; + if (secondValue is null) + { + successfullyAdded = changeToUpdate.TryAddChange(new PropertyChange(property.Name, string.Empty, firstValue.ToString())); + } + else if (secondValue is IYleChangeTracking secondChangeTrackingObject) + { + var change = firstValue.GetChangeComparedTo(helpers, secondChangeTrackingObject); + successfullyAdded = changeToUpdate.TryAddChange(change); + } + else + { + // nothing + } + + helpers?.Log(typeof(T).Name, nameof(GetUpdatedChange), $"Adding change for ChangeTracking object {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + + private static void RegisterChangeTrackingCollectionChangeComparedTo(IEnumerable firstCollectionOfChangeTrackingObjects, IEnumerable secondCollectionOfChangeTrackingObjects, PropertyInfo property, Change changeToUpdate, Helpers helpers = null) + { + helpers?.Log(typeof(T).Name, nameof(GetChangeComparedTo), $"Property {property.Name} implements IEnumerable<{nameof(IYleChangeTracking)}>"); + + foreach (var changeTrackingItem in firstCollectionOfChangeTrackingObjects) + { + var otherChangeTrackingItem = secondCollectionOfChangeTrackingObjects.SingleOrDefault(o => o.UniqueIdentifier == changeTrackingItem.UniqueIdentifier); + if (otherChangeTrackingItem is null) continue; + + var change = changeTrackingItem.GetChangeComparedTo(helpers, otherChangeTrackingItem); + + bool successfullyAdded = changeToUpdate.TryAddChange(change); + + helpers?.Log(typeof(T).Name, nameof(GetChangeComparedTo), $"Adding change for item {changeTrackingItem.UniqueIdentifier} in collection {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + + var addedObjects = firstCollectionOfChangeTrackingObjects.Except(secondCollectionOfChangeTrackingObjects).ToList(); + var removedObjects = secondCollectionOfChangeTrackingObjects.Except(firstCollectionOfChangeTrackingObjects).ToList(); + + helpers?.Log(typeof(T).Name, nameof(GetChangeComparedTo), $"Removed objects in collection {property.Name}: '{string.Join(", ", removedObjects.Select(o => o.UniqueIdentifier))}'"); + helpers?.Log(typeof(T).Name, nameof(GetChangeComparedTo), $"Added objects in collection {property.Name}: '{string.Join(", ", addedObjects.Select(o => o.UniqueIdentifier))}'"); + + foreach (var addedObject in addedObjects) + { + bool successfullyAdded = changeToUpdate.TryAddChange(new CollectionChanges(property.Name, CollectionChangeType.Add, addedObject.UniqueIdentifier, addedObject.DisplayName)); + + helpers?.Log(typeof(T).Name, nameof(GetChangeComparedTo), $"Adding collection change for added item {addedObject.UniqueIdentifier} in collection {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + + foreach (var removedObject in removedObjects) + { + bool successfullyAdded = changeToUpdate.TryAddChange(new CollectionChanges(property.Name, CollectionChangeType.Remove, removedObject.UniqueIdentifier, removedObject.DisplayName)); + + helpers?.Log(typeof(T).Name, nameof(GetChangeComparedTo), $"Adding collection change for removed item {removedObject.UniqueIdentifier} in collection {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + } + + private static void RegisterCollectionChangesComparedTo(object firstValue, object secondValue, PropertyInfo property, Change changeToUpdate, Helpers helpers = null) + { + CollectionChanges collectionChanges = null; + + if (firstValue is IEnumerable integerCollection && secondValue is IEnumerable secondIntegerCollection) + { + collectionChanges = CreateCollectionChange(helpers, property.Name, integerCollection, secondIntegerCollection); + } + else if (firstValue is IEnumerable stringCollection && secondValue is IEnumerable secondStringCollection) + { + collectionChanges = CreateCollectionChange(helpers, property.Name, stringCollection, secondStringCollection); + } + else if (firstValue is IEnumerable guidCollection && secondValue is IEnumerable secondGuidCollection) + { + collectionChanges = CreateCollectionChange(helpers, property.Name, guidCollection, secondGuidCollection); + } + else + { + throw new NotSupportedException($"Property {property.Name} of class {typeof(T).Name} is a collection of an unsupported type"); + } + + if (collectionChanges != null && collectionChanges.Changes.Any()) + { + changeToUpdate.TryAddChange(collectionChanges); + } + } + + private static void RegisterObjectChangesComparedTo(object firstValue, object secondValue, PropertyInfo property, Change changeToUpdate, Helpers helpers = null) + { + var currentValueToSave = firstValue?.ToString() ?? String.Empty; + var initialValueToSave = secondValue?.ToString() ?? String.Empty; + + helpers?.Log(typeof(T).Name, nameof(GetChangeComparedTo), $"Accepting value '{currentValueToSave}' for property {property.Name}, initial value is '{initialValueToSave}'"); + + if (initialValueToSave != currentValueToSave) + { + var propertyChangeHistory = new PropertyChange(property.Name, initialValueToSave, currentValueToSave); + + bool successfullyAdded = changeToUpdate.TryAddChange(propertyChangeHistory); + + helpers?.Log(typeof(T).Name, nameof(GetChangeComparedTo), $"Adding change for property {property.Name} {(successfullyAdded ? "succeeded" : "failed")}"); + } + } + + private static CollectionChanges CreateCollectionChange(Helpers helpers, string collectionName, IEnumerable newCollection, IEnumerable initialCollection) + { + var collectionChange = new CollectionChanges(collectionName); + + var removedObjects = initialCollection.Except(newCollection).ToList(); + var addedObjects = newCollection.Except(initialCollection).ToList(); + + helpers?.Log(typeof(ChangeTrackingHelper).Name, nameof(GetUpdatedChange), $"{removedObjects.Count} removed objects in collection {collectionName}: '{string.Join(", ", removedObjects.Select(ro => ro.ToString()))}'"); + helpers?.Log(typeof(ChangeTrackingHelper).Name, nameof(GetUpdatedChange), $"{addedObjects.Count} added objects in collection {collectionName}: '{string.Join(", ", addedObjects.Select(ro => ro.ToString()))}'"); + + foreach (var addedObject in addedObjects) + { + collectionChange.AddCollectionChange(new CollectionChange + { + ItemIdentifier = addedObject.ToString(), + Type = CollectionChangeType.Add, + DisplayName = addedObject.ToString(), + }); + } + + foreach (var removedObject in removedObjects) + { + collectionChange.AddCollectionChange(new CollectionChange + { + ItemIdentifier = removedObject.ToString(), + Type = CollectionChangeType.Remove, + DisplayName = removedObject.ToString(), + }); + } + + return collectionChange; + } + + private static void SaveCurrentValueAsInitialValue(Helpers helpers, Dictionary initialValues, PropertyInfo property, object currentValue) + { + object initialValueToSave; + + if (!(currentValue is string) && currentValue is IEnumerable) + { + helpers?.Log(nameof(ChangeTrackingHelper), nameof(AcceptChanges), $"Creating collection copy for property {property.Name} to set as initial value"); + + var copyConstructor = property.PropertyType.GetConstructor(new[] { property.PropertyType }); + initialValueToSave = copyConstructor.Invoke(new object[] { currentValue }); + } + else + { + initialValueToSave = currentValue; + } + + initialValues[property.Name] = initialValueToSave; + } + + private static void CallAccceptChangesOnChangeTrackingObjects(Helpers helpers, string propertyName, object currentPropertyValue) + { + if (currentPropertyValue is IYleChangeTracking changeTrackingObject) + { + helpers?.Log(nameof(ChangeTrackingHelper), nameof(AcceptChanges), $"Property {propertyName} implements {nameof(IYleChangeTracking)}, calling {nameof(AcceptChanges)}"); + + changeTrackingObject.AcceptChanges(); + } + else if (currentPropertyValue is IEnumerable collectionOfChangeTrackingObjects) + { + helpers?.Log(nameof(ChangeTrackingHelper), nameof(AcceptChanges), $"Property {propertyName} implements IEnumerable<{nameof(IYleChangeTracking)}>, calling {nameof(AcceptChanges)} on each element"); + + foreach (var changeTrackingItem in collectionOfChangeTrackingObjects) + { + changeTrackingItem.AcceptChanges(); + } + } + else + { + // No change tracking object + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/Change.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/Change.cs new file mode 100644 index 0000000..2ce3ba9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/Change.cs @@ -0,0 +1,34 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using System; + using System.Collections.Generic; + using System.Text; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + + public abstract class Change + { + public abstract ChangeSummary Summary { get; } + + public bool TryAddChanges(List changesToAdd) + { + bool success = true; + + foreach (var changeToAdd in changesToAdd) + { + success &= TryAddChange(changeToAdd); + } + + return success; + } + + public abstract bool TryAddChange(Change changeToAdd); + + public abstract Change GetActualChanges(); + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ClassChange.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ClassChange.cs new file mode 100644 index 0000000..29a1a7b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ClassChange.cs @@ -0,0 +1,96 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + + public class ClassChange : Change + { + private readonly PropertyChangeSummary summary = new PropertyChangeSummary(); + + public ClassChange(string className) + { + ClassName = className; + } + + public string ClassName { get; set; } + + public HashSet ClassChanges { get; set; } = new HashSet(); + + public HashSet PropertyChanges { get; set; } = new HashSet(); + + public HashSet CollectionChanges { get; set; } = new HashSet(); + + [JsonIgnore] + public override ChangeSummary Summary => summary; + + public CollectionChanges GetCollectionChanges(string collectionName) + { + return CollectionChanges.SingleOrDefault(cc => cc.CollectionName == collectionName); + } + + public PropertyChange GetPropertyChange(string propertyName) + { + return PropertyChanges.SingleOrDefault(cc => cc.PropertyName == propertyName); + } + + public override Change GetActualChanges() + { + if (!Summary.IsChanged) return null; + + var change = new ClassChange(ClassName); + + change.TryAddChanges(ClassChanges.Select(c => c.GetActualChanges()).OfType().ToList()); + change.TryAddChanges(PropertyChanges.Select(c => c.GetActualChanges()).OfType().ToList()); + change.TryAddChanges(CollectionChanges.Select(c => c.GetActualChanges()).OfType().ToList()); + + return change; + } + + public override bool TryAddChange(Change changeToAdd) + { + summary.TryAddChangeSummary(changeToAdd.Summary); + + if (changeToAdd is PropertyChange propertyChangeToAdd) + { + PropertyChanges.Add(propertyChangeToAdd); + return true; + } + else if(changeToAdd is ClassChange classChangeToAdd) + { + ClassChanges.Add(classChangeToAdd); + return true; + } + else if(changeToAdd is CollectionChanges collectionChangesToAdd) + { + var existingCollectionChange = CollectionChanges.SingleOrDefault(c => c.CollectionName == collectionChangesToAdd.CollectionName); + + if (existingCollectionChange is null) + { + CollectionChanges.Add(collectionChangesToAdd); + } + else + { + existingCollectionChange.TryAddChange(collectionChangesToAdd); + } + + return true; + } + + return false; + } + + public bool PropertyHasChange(string property) + { + var propertyChange = PropertyChanges.SingleOrDefault(x => x.PropertyName.Equals(property)); + + if (propertyChange == null) + { + return false; + } + + return propertyChange.Summary.IsChanged; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/CollectionChange.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/CollectionChange.cs new file mode 100644 index 0000000..96c9592 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/CollectionChange.cs @@ -0,0 +1,25 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using System; + + public enum CollectionChangeType + { + None, + Add, + Remove, + } + + public sealed class CollectionChange : IEquatable + { + public CollectionChangeType Type { get; set; } + + public string ItemIdentifier { get; set; } + + public string DisplayName { get; set; } + + public bool Equals(CollectionChange other) + { + return Type == other.Type && ItemIdentifier == other.ItemIdentifier && DisplayName == other.DisplayName; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/CollectionChanges.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/CollectionChanges.cs new file mode 100644 index 0000000..80d84c9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/CollectionChanges.cs @@ -0,0 +1,78 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + + public class CollectionChanges : Change + { + private readonly CollectionChangesSummary summary = new CollectionChangesSummary(); + + [JsonConstructor] + public CollectionChanges(string collectionName) + { + CollectionName = collectionName; + } + + public CollectionChanges(string collectionName, CollectionChangeType collectionChangeType, string itemIdentifier, string shortDescription) + { + CollectionName = collectionName; + + Changes.Add(new CollectionChange + { + ItemIdentifier = itemIdentifier, + Type = collectionChangeType, + DisplayName = shortDescription + }); + + if (collectionChangeType == CollectionChangeType.Add) + { + summary.MarkItemsAdded(); + } + else if(collectionChangeType == CollectionChangeType.Remove) + { + summary.MarkItemsRemoved(); + } + } + + public string CollectionName { get; set; } + + public HashSet Changes { get; set; } = new HashSet(); + + [JsonIgnore] + public override ChangeSummary Summary => summary; + + public void AddCollectionChange(CollectionChange collectionChangeToAdd) + { + Changes.Add(collectionChangeToAdd); + + if (collectionChangeToAdd.Type == CollectionChangeType.Add) + { + summary.MarkItemsAdded(); + } + else if (collectionChangeToAdd.Type == CollectionChangeType.Remove) + { + summary.MarkItemsRemoved(); + } + } + + public override Change GetActualChanges() + { + return this; + } + + public override bool TryAddChange(Change changeToAdd) + { + if (changeToAdd is CollectionChanges collectionChangesToAdd && collectionChangesToAdd.CollectionName == CollectionName) + { + Changes.UnionWith(collectionChangesToAdd.Changes); + summary.TryAddChangeSummary(collectionChangesToAdd.summary); + return true; + } + + return false; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/FunctionChange.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/FunctionChange.cs new file mode 100644 index 0000000..0f608a8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/FunctionChange.cs @@ -0,0 +1,114 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Function; + using Skyline.DataMiner.Net.ResourceManager.Objects; + + public class FunctionChange : Change + { + private readonly FunctionChangeSummary summary = new FunctionChangeSummary(); + + public FunctionChange() + { + + } + + public FunctionChange(Function function, FunctionResource initialResource, FunctionResource newResource) + { + FunctionLabel = function.Definition.Label; + FunctionId = function.Id; + + bool resourceWasAdded = initialResource == null && newResource != null; + bool resourceWasRemoved = initialResource != null && newResource == null; + bool resourceWasChanged = initialResource != null && newResource != null && !initialResource.Equals(newResource); + + if (resourceWasAdded || resourceWasRemoved || resourceWasChanged) + { + var oldValue = string.IsNullOrWhiteSpace(initialResource?.Name) ? Constants.None : initialResource.Name; + var newValue = string.IsNullOrWhiteSpace(newResource?.Name) ? Constants.None : newResource.Name; + + ResourceChange = new ValueChange(oldValue, newValue); + } + + if (resourceWasAdded || resourceWasChanged) summary.ResourceChangeSummary.MarkResourceAddedOrSwapped(); + else if (resourceWasRemoved) summary.ResourceChangeSummary.MarkResourceRemoved(); + } + + public string FunctionLabel { get; set; } + + public Guid FunctionId { get; set; } + + public HashSet ProfileParameterChanges { get; set; } = new HashSet(); + + public ValueChange ResourceChange { get; set; } = new ValueChange(); + + [JsonIgnore] + public override ChangeSummary Summary => summary; + + public override Change GetActualChanges() + { + if (!Summary.IsChanged) return null; + + var change = new FunctionChange + { + FunctionId = FunctionId, + FunctionLabel = FunctionLabel, + ResourceChange = ResourceChange.NewValue != ResourceChange.OldValue ? ResourceChange : null, + }; + + change.TryAddChanges(ProfileParameterChanges.Select(c => c.GetActualChanges()).OfType().ToList()); + + return change; + } + + public override bool TryAddChange(Change changeToAdd) + { + if (changeToAdd is null) return false; + + summary.TryAddChangeSummary(changeToAdd.Summary); + + if (changeToAdd is ProfileParameterChange profileParameterChangeToAdd) + { + ProfileParameterChanges.Add(profileParameterChangeToAdd); + return true; + } + + return false; + } + + public void UpdateSummaryWithServiceInfo(ServiceDefinition serviceDefinition) + { + if (!Summary.IsChanged) return; + + if (serviceDefinition.FunctionIsFirst(FunctionLabel)) + { + if (summary.ResourceChangeSummary.ResourcesAddedOrSwapped) + { + summary.ResourceChangeSummary.MarkResourceAtBeginningOfServiceDefinitionAddedOrSwapped(); + } + else if(summary.ResourceChangeSummary.ResourcesRemoved) + { + summary.ResourceChangeSummary.MarkResourceAtBeginningOfServiceDefinitionRemoved(); + } + } + else if (serviceDefinition.FunctionIsLast(FunctionLabel)) + { + if (summary.ResourceChangeSummary.ResourcesAddedOrSwapped) + { + summary.ResourceChangeSummary.MarkResourceAtEndOfServiceDefinitionAddedOrSwapped(); + } + else if (summary.ResourceChangeSummary.ResourcesRemoved) + { + summary.ResourceChangeSummary.MarkResourceAtEndOfServiceDefinitionRemoved(); + + } + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/OrderChange.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/OrderChange.cs new file mode 100644 index 0000000..c9a4b88 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/OrderChange.cs @@ -0,0 +1,179 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + using Status = Order.Status; + + public class OrderChange : ClassChange + { + private readonly OrderChangeSummary summary = new OrderChangeSummary(); + + [JsonConstructor] + public OrderChange(string orderName, HashSet serviceChanges = null) : base(nameof(Order)) + { + OrderName = orderName; + ServiceChanges = serviceChanges ?? new HashSet(); + } + + [JsonIgnore] + public string OrderName { get; } + + public HashSet ServiceChanges { get; } + + [JsonIgnore] + public override ChangeSummary Summary => summary; + + public override bool TryAddChange(Change changeToAdd) + { + UpdateSummary(changeToAdd); + + if (changeToAdd is PropertyChange propertyChangeToAdd) + { + PropertyChanges.Add(propertyChangeToAdd); + return true; + } + else if (changeToAdd is ServiceChange serviceChangeToAdd) + { + bool changeForThisServiceIsAlreadyAdded = ServiceChanges.Select(sc => sc.ServiceName).Contains(serviceChangeToAdd.ServiceName); + + if (!changeForThisServiceIsAlreadyAdded) + { + ServiceChanges.Add(serviceChangeToAdd); + } + + return true; + } + else if (changeToAdd is ClassChange classChangeToAdd) + { + ClassChanges.Add(classChangeToAdd); + return true; + } + else if (changeToAdd is CollectionChanges collectionChangesToAdd) + { + var existingCollectionChange = CollectionChanges.SingleOrDefault(c => c.CollectionName == collectionChangesToAdd.CollectionName); + + if (existingCollectionChange is null) + { + CollectionChanges.Add(collectionChangesToAdd); + } + else + { + existingCollectionChange.TryAddChange(collectionChangesToAdd); + } + + return true; + } + + return false; + } + + /// + /// Gets a new Change object containing only values that really changed and without summaries. This is the object that should be saved on the Order Manager driver. + /// + /// A new Change object containing only values that really changed and without summaries. + public override Change GetActualChanges() + { + var change = new OrderChange(OrderName); + + change.TryAddChanges(ServiceChanges.Select(s => s.GetActualChanges()).OfType().ToList()); + change.TryAddChanges(CollectionChanges.Select(s => s.GetActualChanges()).OfType().ToList()); + change.TryAddChanges(ClassChanges.Select(s => s.GetActualChanges()).OfType().ToList()); + change.TryAddChanges(PropertyChanges.Select(s => s.GetActualChanges()).OfType().ToList()); + + return change; + } + + public OrderChange GetChangeForCreationHistory() + { + var change = new OrderChange(OrderName); + + var allServicesChange = GetCollectionChanges(nameof(Order.AllServices)); + + if (allServicesChange != null) + { + change.TryAddChange(allServicesChange); + } + + foreach (var serviceChange in ServiceChanges) + { + var serviceChangeForCreationHistory = serviceChange.GetChangeForCreationHistory(); + if (serviceChangeForCreationHistory is null) continue; + + change.TryAddChange(serviceChangeForCreationHistory); + } + + foreach (var serviceChange in ServiceChanges) + { + var serviceChangeForCreationHistory = serviceChange.GetChangeForCreationHistory(); + if (serviceChangeForCreationHistory is null) continue; + + change.TryAddChange(serviceChangeForCreationHistory); + } + + return change; + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + + private void UpdateSummary(Change changeToAdd) + { + summary.TryAddChangeSummary(changeToAdd.Summary); + + if (changeToAdd is PropertyChange propertyChangeToAdd) + { + switch (propertyChangeToAdd.PropertyName) + { + case nameof(LiteOrder.Status): + if (propertyChangeToAdd.Change.OldValue == Status.Preliminary.ToString() && propertyChangeToAdd.Change.NewValue != Status.Preliminary.ToString()) + { + summary.SavedOrderIsBeingBooked = true; + } + break; + case nameof(LiteOrder.StartNow): + if (propertyChangeToAdd.Change.OldValue == false.ToString() && propertyChangeToAdd.Change.NewValue == true.ToString()) + { + summary.BookedOrderWasModifiedToStartNow = true; + } + break; + case nameof(Order.PreRoll): + summary.TimingChangeSummary.MarkPrerollChanged(); + break; + case nameof(LiteOrder.Start): + summary.TimingChangeSummary.MarkStartTimingChanged(); + break; + case nameof(LiteOrder.End): + summary.TimingChangeSummary.MarkEndTimingChanged(); + break; + case nameof(Order.PostRoll): + summary.TimingChangeSummary.MarkPostrollChanged(); + break; + case nameof(LiteOrder.Name): + summary.NameChanged = true; + break; + + default: + break; + } + } + else if (changeToAdd is CollectionChanges collectionChangesToAdd) + { + if (collectionChangesToAdd.CollectionName == nameof(Order.AllServices)) + { + summary.ServicesWereAdded |= collectionChangesToAdd.Changes.Any(c => c.Type == CollectionChangeType.Add); + summary.ServicesWereRemoved |= collectionChangesToAdd.Changes.Any(c => c.Type == CollectionChangeType.Remove); + } + + summary.SecurityViewIdsChanged |= collectionChangesToAdd.CollectionName == nameof(Order.SecurityViewIds); + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ProfileParameterChange.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ProfileParameterChange.cs new file mode 100644 index 0000000..1b2c193 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ProfileParameterChange.cs @@ -0,0 +1,51 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using System; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + using Newtonsoft.Json; + + public class ProfileParameterChange : Change + { + private readonly ProfileParameterChangeSummary summary = new ProfileParameterChangeSummary(); + + public ProfileParameterChange() + { + + } + + public ProfileParameterChange(ProfileParameter profileParameter, object oldValue, object newValue) + { + ProfileParameterName = profileParameter.Name; + ProfileParameterId = profileParameter.Id; + + Change = new ValueChange(oldValue?.ToString() ?? string.Empty, newValue?.ToString() ?? string.Empty); + + if (Change.OldValue != Change.NewValue) + { + summary.MarkChanges(profileParameter, oldValue, newValue); + } + } + + public string ProfileParameterName { get; set; } + + public Guid ProfileParameterId { get; set; } + + public ValueChange Change { get; set; } = new ValueChange(); + + [JsonIgnore] + public override ChangeSummary Summary => summary; + + public override Change GetActualChanges() + { + if (!Summary.IsChanged) return null; + + return this; + } + + public override bool TryAddChange(Change changeToAdd) + { + return false; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/PropertyChange.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/PropertyChange.cs new file mode 100644 index 0000000..55076c8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/PropertyChange.cs @@ -0,0 +1,46 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + + public class PropertyChange : Change + { + private readonly PropertyChangeSummary summary = new PropertyChangeSummary(); + + public PropertyChange() + { + + } + + public PropertyChange(string propertyName, string oldValue, string newValue) + { + PropertyName = propertyName; + + Change = new ValueChange(oldValue, newValue); + + if (oldValue != newValue) + { + summary.MarkIsChanged(); + } + } + + public string PropertyName { get; set; } + + public ValueChange Change { get; set; } = new ValueChange(); + + [JsonIgnore] + public override ChangeSummary Summary => summary; + + public override Change GetActualChanges() + { + if(!Summary.IsChanged) return null; + + return this; + } + + public override bool TryAddChange(Change changeToAdd) + { + return false; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ServiceChange.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ServiceChange.cs new file mode 100644 index 0000000..1854a98 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ServiceChange.cs @@ -0,0 +1,177 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service; + + public class ServiceChange : ClassChange + { + private readonly ServiceChangeSummary summary = new ServiceChangeSummary(); + + [JsonConstructor] + public ServiceChange(string serviceName, string serviceDisplayName, HashSet functionChanges = null) : base(nameof(Service)) + { + ServiceName = serviceName; + ServiceDisplayName = serviceDisplayName; + FunctionChanges = functionChanges ?? new HashSet(); + } + + public string ServiceName { get; } + + public string ServiceDisplayName { get; } + + public HashSet FunctionChanges { get; } + + [JsonIgnore] + public override ChangeSummary Summary => summary; + + public override Change GetActualChanges() + { + if(!Summary.IsChanged || summary.IsNew) return null; + + var change = new ServiceChange(ServiceName, ServiceDisplayName); + + change.TryAddChanges(FunctionChanges.Select(c => c.GetActualChanges()).OfType().ToList()); + change.TryAddChanges(CollectionChanges.Select(s => s.GetActualChanges()).OfType().ToList()); + change.TryAddChanges(ClassChanges.Select(s => s.GetActualChanges()).OfType().ToList()); + change.TryAddChanges(PropertyChanges.Select(s => s.GetActualChanges()).OfType().ToList()); + + return change; + } + + public ServiceChange GetChangeForCreationHistory() + { + var synopsisFilesChange = GetCollectionChanges(nameof(Service.SynopsisFiles)); + if (synopsisFilesChange is null) return null; + + if (synopsisFilesChange.Summary.IsChanged) + { + var change = new ServiceChange(ServiceName, ServiceDisplayName); + + change.TryAddChange(synopsisFilesChange); + + return change; + } + else + { + return null; + } + } + + public override bool TryAddChange(Change changeToAdd) + { + bool successful = false; + + if (changeToAdd is PropertyChange propertyChangeToAdd) + { + PropertyChanges.Add(propertyChangeToAdd); + successful = true; + } + else if (changeToAdd is ClassChange classChangeToAdd) + { + ClassChanges.Add(classChangeToAdd); + successful = true; + } + else if (changeToAdd is CollectionChanges collectionChangesToAdd) + { + var existingCollectionChange = CollectionChanges.SingleOrDefault(c => c.CollectionName == collectionChangesToAdd.CollectionName); + + if (existingCollectionChange is null) + { + CollectionChanges.Add(collectionChangesToAdd); + } + else + { + existingCollectionChange.TryAddChange(collectionChangesToAdd); + } + + successful = true; + } + else if (changeToAdd is FunctionChange functionChangeToAdd) + { + FunctionChanges.Add(functionChangeToAdd); + successful = true; + } + + UpdateSummary(changeToAdd); + + return successful; + } + + public void UpdateSummaryWithServiceInfo(Service service) + { + summary.IsNew = !service.IsBooked; + + summary.IsMissingResources = service.IsMissingResources(null); + + foreach (var functionChange in FunctionChanges) + { + functionChange.UpdateSummaryWithServiceInfo(service.Definition); + summary.TryAddChangeSummary(functionChange.Summary); + } + } + + private void UpdateSummary(Change changeToAdd) + { + if (!changeToAdd.Summary.IsChanged) return; + + summary.TryAddChangeSummary(changeToAdd.Summary); + + if (changeToAdd is PropertyChange propertyChangeToAdd) + { + switch (propertyChangeToAdd.PropertyName) + { + case nameof(Service.PreRoll): + summary.TimingChangeSummary.MarkPrerollChanged(); + break; + case nameof(Service.Start): + summary.TimingChangeSummary.MarkStartTimingChanged(); + break; + case nameof(Service.End): + summary.TimingChangeSummary.MarkEndTimingChanged(); + break; + case nameof(Service.PostRoll): + summary.TimingChangeSummary.MarkPostrollChanged(); + break; + case nameof(Service.RecordingConfiguration): + summary.PropertyChangeSummary.RecordingConfigurationChanged = true; + break; + default: + break; + } + } + else if (changeToAdd is CollectionChanges collectionChangeToAdd) + { + if (collectionChangeToAdd.CollectionName == nameof(Service.Functions)) + { + summary.ServiceDefinitionChanged = true; + } + else if(collectionChangeToAdd.CollectionName == nameof(Service.SecurityViewIds)) + { + summary.SecurityViewIdsHaveChanged = true; + } + else + { + summary.PropertyChangeSummary.MarkIsChanged(); + } + } + else if(changeToAdd is ClassChange classChangeToAdd && classChangeToAdd.ClassName == nameof(Service.RecordingConfiguration)) + { + summary.PropertyChangeSummary.RecordingConfigurationChanged = true; + } + else if(changeToAdd is FunctionChange) + { + // no actions (?) + } + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ValueChange.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ValueChange.cs new file mode 100644 index 0000000..f86261b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Changes/ValueChange.cs @@ -0,0 +1,28 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History +{ + using System; + using Newtonsoft.Json; + + public sealed class ValueChange : IEquatable + { + public ValueChange() + { + + } + + public ValueChange(string oldValue, string newValue) + { + OldValue = oldValue; + NewValue = newValue; + } + + public string OldValue { get; set; } + + public string NewValue { get; set; } + + public bool Equals(ValueChange other) + { + return OldValue == other.OldValue && NewValue == other.NewValue; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/IYleChangeTracking.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/IYleChangeTracking.cs new file mode 100644 index 0000000..dc93dff --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/IYleChangeTracking.cs @@ -0,0 +1,25 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking +{ + using System.Collections.Generic; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public interface IYleChangeTracking + { + string UniqueIdentifier { get; } + + string DisplayName { get; } + + /// + /// Gets a boolean indicating if Change Tracking is enabled. + /// + bool ChangeTrackingStarted { get; } + + Change Change { get; } + + void AcceptChanges(Helpers helpers = null); + + Change GetChangeComparedTo(Helpers helpers, T oldObjectInstance); + } + +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/OrderHistoryChapter.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/OrderHistoryChapter.cs new file mode 100644 index 0000000..dfb8a0c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/OrderHistoryChapter.cs @@ -0,0 +1,67 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking +{ + using System; + using System.Collections.Generic; + using System.Reflection; + using System.Linq; + using Newtonsoft.Json; + using Newtonsoft.Json.Serialization; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.History; + using System.Collections; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class OrderHistoryChapter + { + private static JsonSerializerSettings jsonSettings = new JsonSerializerSettings + { + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + ContractResolver = ShouldSerializeContractResolver.Instance, + }; + + public OrderHistoryChapter() + { + + } + + public OrderHistoryChapter(OrderChange orderChange, string userName, DateTime timestamp, string scriptName) + { + UserName = userName; + Timestamp = timestamp.Truncate(TimeSpan.FromMinutes(1)); + ScriptName = scriptName; + OrderChange = orderChange; + } + + public string UserName { get; set; } + + public string ScriptName { get; set; } + + public DateTime Timestamp { get; set; } + + public OrderChange OrderChange { get; set; } + + public override string ToString() + { + return JsonConvert.SerializeObject(this, jsonSettings); + } + } + + public class ShouldSerializeContractResolver : DefaultContractResolver + { + public static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver(); + + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + JsonProperty property = base.CreateProperty(member, memberSerialization); + + if (property.PropertyType != typeof(string) && property.PropertyType.GetInterface(nameof(IEnumerable)) != null) + { + property.ShouldSerialize = instance => (instance?.GetType().GetProperty(property.PropertyName).GetValue(instance) as IEnumerable)?.Count() > 0; + } + + return property; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ChangeSummary.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ChangeSummary.cs new file mode 100644 index 0000000..bf3cfd5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ChangeSummary.cs @@ -0,0 +1,25 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries +{ + using System.Collections.Generic; + + public abstract class ChangeSummary + { + public abstract bool IsChanged { get; } + + public bool TryAddChangeSummaries(List changeSummariesToAdd) + { + bool success = true; + + foreach (var changeSummaryToAdd in changeSummariesToAdd) + { + success &= TryAddChangeSummary(changeSummaryToAdd); + } + + return success; + } + + public abstract bool TryAddChangeSummary(ChangeSummary changeSummaryToAdd); + + public abstract override string ToString(); + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/CollectionChangesSummary.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/CollectionChangesSummary.cs new file mode 100644 index 0000000..af8bdd9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/CollectionChangesSummary.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Newtonsoft.Json; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries +{ + public class CollectionChangesSummary : ChangeSummary + { + public override bool IsChanged => ItemsAdded || ItemsRemoved; + + public bool ItemsAdded { get; private set; } + + public bool ItemsRemoved { get; private set; } + + public void MarkItemsAdded() + { + ItemsAdded = true; + } + + public void MarkItemsRemoved() + { + ItemsRemoved = true; + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + + public override bool TryAddChangeSummary(ChangeSummary changeSummaryToAdd) + { + if (changeSummaryToAdd is CollectionChangesSummary collectionChangesSummaryToAdd) + { + ItemsAdded |= collectionChangesSummaryToAdd.ItemsAdded; + ItemsRemoved |= collectionChangesSummaryToAdd.ItemsRemoved; + return true; + } + + return false; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/FunctionChangeSummary.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/FunctionChangeSummary.cs new file mode 100644 index 0000000..63365b7 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/FunctionChangeSummary.cs @@ -0,0 +1,43 @@ +using Newtonsoft.Json; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries +{ + public class FunctionChangeSummary : ChangeSummary + { + public override bool IsChanged => IsNew || ProfileParameterChangeSummary.IsChanged || ResourceChangeSummary.IsChanged; + + public bool IsNew { get; set; } + + public ProfileParameterChangeSummary ProfileParameterChangeSummary { get; } = new ProfileParameterChangeSummary(); + + public ResourceChangeSummary ResourceChangeSummary { get; } = new ResourceChangeSummary(); + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + + public override bool TryAddChangeSummary(ChangeSummary changeSummaryToAdd) + { + if (changeSummaryToAdd is FunctionChangeSummary functionChangeSummaryToAdd) + { + IsNew &= functionChangeSummaryToAdd.IsNew; + ResourceChangeSummary.TryAddChangeSummary(functionChangeSummaryToAdd.ResourceChangeSummary); + ProfileParameterChangeSummary.TryAddChangeSummary(functionChangeSummaryToAdd.ProfileParameterChangeSummary); + return true; + } + else if(changeSummaryToAdd is ResourceChangeSummary resourceChangeSummaryToAdd) + { + ResourceChangeSummary.TryAddChangeSummary(resourceChangeSummaryToAdd); + return true; + } + else if (changeSummaryToAdd is ProfileParameterChangeSummary profileParameterChangeSummaryToAdd) + { + ProfileParameterChangeSummary.TryAddChangeSummary(profileParameterChangeSummaryToAdd); + return true; + } + + return false; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/OrderChangeSummary.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/OrderChangeSummary.cs new file mode 100644 index 0000000..3af0edc --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/OrderChangeSummary.cs @@ -0,0 +1,78 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + + public class OrderChangeSummary : ChangeSummary + { + public override bool IsChanged + { + get + { + bool changed = false; + changed |= TimingChangeSummary.IsChanged; + changed |= PropertyChangeSummary.IsChanged; + changed |= ServiceChangeSummary.IsChanged; + changed |= CollectionChangesSummary.IsChanged; + changed |= SecurityViewIdsChanged; + return changed; + } + } + + public TimingChangeSummary TimingChangeSummary { get; } = new TimingChangeSummary(); + + public PropertyChangeSummary PropertyChangeSummary { get; } = new PropertyChangeSummary(); + + public ServiceChangeSummary ServiceChangeSummary { get; } = new ServiceChangeSummary(); + + public CollectionChangesSummary CollectionChangesSummary { get; } = new CollectionChangesSummary(); + + public bool NameChanged { get; set; } + + public bool SecurityViewIdsChanged { get; set; } + + public bool ServicesWereAdded { get; set; } + + public bool ServicesWereRemoved { get; set;} + + public bool SavedOrderIsBeingBooked { get; set; } + + public bool BookedOrderWasModifiedToStartNow { get; set; } + + public bool AreThereAnyCrucialServiceChanges => ServiceChangeSummary.TimingChangeSummary.IsChanged || ServiceChangeSummary.FunctionChangeSummary.IsChanged; + + public override bool TryAddChangeSummary(ChangeSummary changeSummaryToAdd) + { + if (changeSummaryToAdd is TimingChangeSummary timingChangeSummaryToAdd) + { + TimingChangeSummary.TryAddChangeSummary(timingChangeSummaryToAdd); + return true; + } + else if (changeSummaryToAdd is ServiceChangeSummary serviceChangeSummaryToAdd) + { + ServiceChangeSummary.TryAddChangeSummary(serviceChangeSummaryToAdd); + return true; + } + else if (changeSummaryToAdd is PropertyChangeSummary propertyChangeSummaryToAdd) + { + PropertyChangeSummary.TryAddChangeSummary(propertyChangeSummaryToAdd); + return true; + } + else if (changeSummaryToAdd is CollectionChangesSummary collectionChangesSummaryToAdd) + { + CollectionChangesSummary.TryAddChangeSummary(collectionChangesSummaryToAdd); + return true; + } + + return false; + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ProfileParameterChangeSummary.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ProfileParameterChangeSummary.cs new file mode 100644 index 0000000..a0b8665 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ProfileParameterChangeSummary.cs @@ -0,0 +1,174 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile; + + public class ProfileParameterChangeSummary : ChangeSummary + { + [Flags] + private enum TypesOfProfileParameterChanges + { + None = 0, + AudioProcessingProfileParametersChanged = 1, + VideoProcessingProfileParametersChanged = 2, + GraphicsProcessingProfileParametersChanged = 4, + CapabilitiesChanged = 8, + OtherProfileParametersChanged = 16, + NewAudioProcessingShouldBeAdded = 32, + NewGraphicsProcessingShouldBeAdded = 64, + NewVideoProcessingShouldBeAdded = 128, + } + + private const TypesOfProfileParameterChanges AllTypesOfProfileParametersChanges = + TypesOfProfileParameterChanges.AudioProcessingProfileParametersChanged | + TypesOfProfileParameterChanges.GraphicsProcessingProfileParametersChanged | + TypesOfProfileParameterChanges.VideoProcessingProfileParametersChanged | + TypesOfProfileParameterChanges.CapabilitiesChanged | + TypesOfProfileParameterChanges.OtherProfileParametersChanged; + + private TypesOfProfileParameterChanges typesOfChanges = TypesOfProfileParameterChanges.None; + + public override bool IsChanged => typesOfChanges != TypesOfProfileParameterChanges.None; + + public bool AudioProcessingProfileParametersChanged => typesOfChanges.HasFlag(TypesOfProfileParameterChanges.AudioProcessingProfileParametersChanged); + + public bool NewAudioProcessingNeedsToBeAdded => typesOfChanges.HasFlag(TypesOfProfileParameterChanges.NewAudioProcessingShouldBeAdded); + + public bool VideoProcessingProfileParametersHaveChanged => typesOfChanges.HasFlag(TypesOfProfileParameterChanges.VideoProcessingProfileParametersChanged); + + public bool NewVideoProcessingNeedsToBeAdded => typesOfChanges.HasFlag(TypesOfProfileParameterChanges.NewVideoProcessingShouldBeAdded); + + public bool GraphicsProcessingProfileParametersHaveChanged => typesOfChanges.HasFlag(TypesOfProfileParameterChanges.GraphicsProcessingProfileParametersChanged); + + public bool NewGraphicsProcessingNeedsToBeAdded => typesOfChanges.HasFlag(TypesOfProfileParameterChanges.NewGraphicsProcessingShouldBeAdded); + + public bool CapabilitiesChanged => typesOfChanges.HasFlag(TypesOfProfileParameterChanges.CapabilitiesChanged); + + public bool OtherProfileParametersChanged => typesOfChanges.HasFlag(TypesOfProfileParameterChanges.OtherProfileParametersChanged); + + public bool OnlyAudioProcessingProfileParametersChanged => typesOfChanges.HasFlag(AllTypesOfProfileParametersChanges); + + public bool OnlyVideoProcessingProfileParametersChanged => typesOfChanges.HasFlag(AllTypesOfProfileParametersChanges); + + public bool OnlyGraphicsProcessingProfileParametersChanged => typesOfChanges.HasFlag(AllTypesOfProfileParametersChanges); + + public bool OnlyCapabilitiesChanged => typesOfChanges.HasFlag(AllTypesOfProfileParametersChanges); + + public bool OnlyOtherProfileParametersChanged => typesOfChanges.HasFlag(AllTypesOfProfileParametersChanges); + + public void MarkAudioProcessingProfileParametersChanged() + { + typesOfChanges |= TypesOfProfileParameterChanges.AudioProcessingProfileParametersChanged | TypesOfProfileParameterChanges.CapabilitiesChanged; + } + + public void MarkNewAudioProcessingNeeded() + { + typesOfChanges |= TypesOfProfileParameterChanges.NewAudioProcessingShouldBeAdded; + } + + public void MarkVideoProcessingProfileParametersChanged() + { + typesOfChanges |= TypesOfProfileParameterChanges.VideoProcessingProfileParametersChanged | TypesOfProfileParameterChanges.CapabilitiesChanged; + } + + public void MarkNewVideoProcessingNeeded() + { + typesOfChanges |= TypesOfProfileParameterChanges.NewVideoProcessingShouldBeAdded; + } + + public void MarkGraphicsProcessingProfileParametersChanged() + { + typesOfChanges |= TypesOfProfileParameterChanges.GraphicsProcessingProfileParametersChanged | TypesOfProfileParameterChanges.CapabilitiesChanged; + } + + public void MarkNewGraphicsProcessingNeeded() + { + typesOfChanges |= TypesOfProfileParameterChanges.NewGraphicsProcessingShouldBeAdded; + } + + public void MarkCapabilitiesChanged() + { + typesOfChanges |= TypesOfProfileParameterChanges.CapabilitiesChanged; + } + + public void MarkOtherProfileParametersChanged() + { + typesOfChanges |= TypesOfProfileParameterChanges.OtherProfileParametersChanged; + } + + public void MarkChanges(ProfileParameter profileParameter, object oldValue, object newValue) + { + bool currentValueIsDefaultValue = newValue == null || newValue.Equals(profileParameter.DefaultValue?.StringValue ?? String.Empty); + bool oldValueWasDefaultValue = oldValue == null || oldValue.Equals(profileParameter.DefaultValue?.StringValue ?? String.Empty); + bool valueChangedFromDefaultToNonDefault = oldValueWasDefaultValue && !currentValueIsDefaultValue; + + if (ProfileParameterGuids.AllAudioProcessingRequiredGuids.Contains(profileParameter.Id)) + { + MarkAudioProcessingChanges(valueChangedFromDefaultToNonDefault); + } + else if (profileParameter.Id == ProfileParameterGuids.VideoFormat) + { + MarkVideoProcessingChanges(valueChangedFromDefaultToNonDefault); + } + else if (profileParameter.Id == ProfileParameterGuids.RemoteGraphics) + { + MarkGraphicsProcessingChanges(valueChangedFromDefaultToNonDefault); + } + else if (profileParameter.IsCapability) MarkCapabilitiesChanged(); + else MarkOtherProfileParametersChanged(); + } + + private void MarkGraphicsProcessingChanges(bool valueChangedFromDefaultToNonDefault) + { + MarkGraphicsProcessingProfileParametersChanged(); + + if (GraphicsProcessingProfileParametersHaveChanged && valueChangedFromDefaultToNonDefault) + { + MarkNewGraphicsProcessingNeeded(); + } + } + + private void MarkVideoProcessingChanges(bool valueChangedFromDefaultToNonDefault) + { + MarkVideoProcessingProfileParametersChanged(); + + if (VideoProcessingProfileParametersHaveChanged && valueChangedFromDefaultToNonDefault) + { + MarkNewVideoProcessingNeeded(); + } + } + + private void MarkAudioProcessingChanges(bool valueChangedFromDefaultToNonDefault) + { + MarkAudioProcessingProfileParametersChanged(); + + if (AudioProcessingProfileParametersChanged && valueChangedFromDefaultToNonDefault) + { + MarkNewAudioProcessingNeeded(); + } + } + + public override bool TryAddChangeSummary(ChangeSummary changeSummaryToAdd) + { + if (changeSummaryToAdd is ProfileParameterChangeSummary profileParameterChangeSummaryToAdd) + { + typesOfChanges |= profileParameterChangeSummaryToAdd.typesOfChanges; + return true; + } + + return false; + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } + +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/PropertyChangeSummary.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/PropertyChangeSummary.cs new file mode 100644 index 0000000..d2c1e17 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/PropertyChangeSummary.cs @@ -0,0 +1,39 @@ +using Newtonsoft.Json; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries +{ + public class PropertyChangeSummary : ChangeSummary + { + private bool isChanged; + + public override bool IsChanged => isChanged; + + public bool RecordingConfigurationChanged { get; set; } + + public void MarkIsChanged() + { + isChanged = true; + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + + public override bool TryAddChangeSummary(ChangeSummary changeSummaryToAdd) + { + if (changeSummaryToAdd is PropertyChangeSummary propertyChangeSummaryToAdd) + { + isChanged |= propertyChangeSummaryToAdd.IsChanged; + return true; + } + else if(changeSummaryToAdd is CollectionChangesSummary collectionChangesSummaryToAdd) + { + isChanged |= collectionChangesSummaryToAdd.IsChanged; + return true; + } + + return false; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ResourceChangeSummary.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ResourceChangeSummary.cs new file mode 100644 index 0000000..8b3ebc6 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ResourceChangeSummary.cs @@ -0,0 +1,80 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries +{ + using System; + using Newtonsoft.Json; + + public class ResourceChangeSummary : ChangeSummary + { + [Flags] + private enum TypesOfResourceChanges + { + None = 0, + ResourceWasAddedOrSwapped = 1, + ResourceWasRemoved = 2, + ResourceAtBeginningOfServiceDefinitionHasChanged = 4, + ResourceAtEndOfServiceDefinitionHasChanged = 8, + } + + private TypesOfResourceChanges typesOfChanges = TypesOfResourceChanges.None; + + public override bool IsChanged => typesOfChanges != TypesOfResourceChanges.None; + + public bool ResourcesAddedOrSwapped => typesOfChanges.HasFlag(TypesOfResourceChanges.ResourceWasAddedOrSwapped); + + public bool ResourcesRemoved => typesOfChanges.HasFlag(TypesOfResourceChanges.ResourceWasRemoved); + + public bool ResourceAtBeginningOfServiceDefinitionChanged => typesOfChanges.HasFlag(TypesOfResourceChanges.ResourceAtBeginningOfServiceDefinitionHasChanged); + + public bool ResourceAtEndOfServiceDefinitionChanged => typesOfChanges.HasFlag(TypesOfResourceChanges.ResourceAtEndOfServiceDefinitionHasChanged); + + public void MarkResourceAddedOrSwapped() + { + typesOfChanges |= TypesOfResourceChanges.ResourceWasAddedOrSwapped; + } + + public void MarkResourceRemoved() + { + typesOfChanges |= TypesOfResourceChanges.ResourceWasRemoved; + } + + public void MarkResourceAtBeginningOfServiceDefinitionAddedOrSwapped() + { + typesOfChanges |= TypesOfResourceChanges.ResourceWasAddedOrSwapped; + typesOfChanges |= TypesOfResourceChanges.ResourceAtBeginningOfServiceDefinitionHasChanged; + } + + public void MarkResourceAtBeginningOfServiceDefinitionRemoved() + { + typesOfChanges |= TypesOfResourceChanges.ResourceWasRemoved; + typesOfChanges |= TypesOfResourceChanges.ResourceAtBeginningOfServiceDefinitionHasChanged; + } + + public void MarkResourceAtEndOfServiceDefinitionAddedOrSwapped() + { + typesOfChanges |= TypesOfResourceChanges.ResourceWasAddedOrSwapped; + typesOfChanges |= TypesOfResourceChanges.ResourceAtEndOfServiceDefinitionHasChanged; + } + + public void MarkResourceAtEndOfServiceDefinitionRemoved() + { + typesOfChanges |= TypesOfResourceChanges.ResourceWasRemoved; + typesOfChanges |= TypesOfResourceChanges.ResourceAtEndOfServiceDefinitionHasChanged; + } + + public override bool TryAddChangeSummary(ChangeSummary changeSummaryToAdd) + { + if (changeSummaryToAdd is ResourceChangeSummary resourceChangeInfoToAdd) + { + typesOfChanges |= resourceChangeInfoToAdd.typesOfChanges; + return true; + } + + return false; + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ServiceChangeSummary.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ServiceChangeSummary.cs new file mode 100644 index 0000000..f332cd6 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/ServiceChangeSummary.cs @@ -0,0 +1,101 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Tasks.ServiceTasks; + + public class ServiceChangeSummary : ChangeSummary + { + public override bool IsChanged + { + get + { + bool changed = false; + changed |= IsNew; + changed |= IsMissingResources; + changed |= PropertyChangeSummary.IsChanged; + changed |= TimingChangeSummary.IsChanged; + changed |= FunctionChangeSummary.IsChanged; + changed |= CollectionChangesSummary.IsChanged; + changed |= SecurityViewIdsHaveChanged; + return changed; + } + } + + public bool IsNew { get; set; } + + public bool IsMissingResources { get; set; } + + public bool SecurityViewIdsHaveChanged { get; set; } + + public bool ServiceDefinitionChanged { get; set; } + + public TimingChangeSummary TimingChangeSummary { get; } = new TimingChangeSummary(); + + public PropertyChangeSummary PropertyChangeSummary { get; } = new PropertyChangeSummary(); + + public FunctionChangeSummary FunctionChangeSummary { get; } = new FunctionChangeSummary(); + + public CollectionChangesSummary CollectionChangesSummary { get; } = new CollectionChangesSummary(); + + public bool OnlyResourcesHaveChanged + { + get + { + bool changed = false; + changed |= IsNew; + changed |= PropertyChangeSummary.IsChanged; + changed |= TimingChangeSummary.IsChanged; + changed |= SecurityViewIdsHaveChanged; + changed |= FunctionChangeSummary.ProfileParameterChangeSummary.IsChanged; + + return FunctionChangeSummary.ResourceChangeSummary.IsChanged && !changed; + } + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + + public override bool TryAddChangeSummary(ChangeSummary changeSummaryToAdd) + { + if (changeSummaryToAdd is FunctionChangeSummary functionChangeSummaryToAdd) + { + FunctionChangeSummary.TryAddChangeSummary(functionChangeSummaryToAdd); + return true; + } + else if(changeSummaryToAdd is PropertyChangeSummary propertyChangeSummaryToAdd) + { + PropertyChangeSummary.TryAddChangeSummary(propertyChangeSummaryToAdd); + return true; + } + else if(changeSummaryToAdd is TimingChangeSummary timingChangeSummaryToAdd) + { + TimingChangeSummary.TryAddChangeSummary(timingChangeSummaryToAdd); + return true; + } + else if(changeSummaryToAdd is ServiceChangeSummary serviceChangeSummaryToAdd) + { + IsNew |= serviceChangeSummaryToAdd.IsNew; + IsMissingResources |= serviceChangeSummaryToAdd.IsMissingResources; + SecurityViewIdsHaveChanged |= serviceChangeSummaryToAdd.SecurityViewIdsHaveChanged; + ServiceDefinitionChanged |= serviceChangeSummaryToAdd.ServiceDefinitionChanged; + + FunctionChangeSummary.TryAddChangeSummary(serviceChangeSummaryToAdd.FunctionChangeSummary); + PropertyChangeSummary.TryAddChangeSummary(serviceChangeSummaryToAdd.PropertyChangeSummary); + TimingChangeSummary.TryAddChangeSummary(serviceChangeSummaryToAdd.TimingChangeSummary); + CollectionChangesSummary.TryAddChangeSummary(serviceChangeSummaryToAdd.CollectionChangesSummary); + } + else if(changeSummaryToAdd is CollectionChangesSummary collectionChangesSummaryToAdd) + { + CollectionChangesSummary.TryAddChangeSummary(collectionChangesSummaryToAdd); + } + + return false; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/TimingChangeSummary.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/TimingChangeSummary.cs new file mode 100644 index 0000000..4c62558 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/ChangeTracking/Summaries/TimingChangeSummary.cs @@ -0,0 +1,71 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ChangeTracking.Summaries; + + public class TimingChangeSummary : ChangeSummary + { + [Flags] + private enum TypesOfTimingChanges + { + None = 0, + StartTimingChanged = 1, + EndTimingChanged = 2, + PrerollHasChanged = 3, + PostrollHasChanged = 4, + } + + private TypesOfTimingChanges typesOfChanges; + + public override bool IsChanged => typesOfChanges != TypesOfTimingChanges.None; + + public bool StartTimingChanged => typesOfChanges.HasFlag(TypesOfTimingChanges.StartTimingChanged); + + public bool EndTimingChanged => typesOfChanges.HasFlag(TypesOfTimingChanges.EndTimingChanged); + + public bool PrerollChanged => typesOfChanges.HasFlag(TypesOfTimingChanges.PrerollHasChanged); + + public bool PostrollChanged => typesOfChanges.HasFlag(TypesOfTimingChanges.PostrollHasChanged); + + public override bool TryAddChangeSummary(ChangeSummary changeSummaryToAdd) + { + if (changeSummaryToAdd is TimingChangeSummary timingChangeSummaryToAdd) + { + typesOfChanges |= timingChangeSummaryToAdd.typesOfChanges; + return true; + } + + return false; + } + + public void MarkStartTimingChanged() + { + typesOfChanges |= TypesOfTimingChanges.StartTimingChanged; + } + + public void MarkEndTimingChanged() + { + typesOfChanges |= TypesOfTimingChanges.EndTimingChanged; + } + + public void MarkPrerollChanged() + { + typesOfChanges |= TypesOfTimingChanges.PrerollHasChanged; + } + + public void MarkPostrollChanged() + { + typesOfChanges |= TypesOfTimingChanges.PostrollHasChanged; + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/Agents.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/Agents.cs new file mode 100644 index 0000000..8d90e99 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/Agents.cs @@ -0,0 +1,65 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Skyline.DataMiner.Automation; + + public static class Agents + { + public enum DataMinerSystem + { + Internal, + Staging, + Production, + } + + public static readonly IReadOnlyDictionary AgentIDs = new Dictionary { + { 665, "slc-h42-g06.skyline.local" }, + { 127601, "dataminer-test.yleisradio.fi" }, + { 127602, "dataminer-test.yleisradio.fi" }, + { 127609, "dataminer-test.yleisradio.fi" }, + { 127603, "dataminer.ylead.fi" }, + { 127604, "dataminer.ylead.fi" }, + { 127608, "dataminer.ylead.fi" }, + }; + + public const int InternalSetupAgentId = 665; + + public static readonly IReadOnlyList StagingAgentIds = new List { 127601, 127602, 127609 }; + + public static readonly IReadOnlyList ProductionAgentIds = new List { 127603, 127604, 127608 }; + + public static DataMinerSystem CurrentSystem + { + get + { + int agentId = Engine.SLNetRaw.ServerDetails.AgentID; + + if (agentId == InternalSetupAgentId) + { + return DataMinerSystem.Internal; + } + else if (IsStaging(agentId)) + { + return DataMinerSystem.Staging; + } + else if (IsProduction(agentId)) + { + return DataMinerSystem.Production; + } + else throw new InvalidOperationException($"Unknown Agent ID: '{agentId}'"); + } + } + + public static bool IsStaging(int agentId) + { + return StagingAgentIds.Contains(agentId); + } + + public static bool IsProduction(int agentId) + { + return ProductionAgentIds.Contains(agentId); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/AvidInterplayPamProtocol.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/AvidInterplayPamProtocol.cs new file mode 100644 index 0000000..0cf7dfe --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/AvidInterplayPamProtocol.cs @@ -0,0 +1,32 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class AvidInterplayPamProtocol + { + public static readonly string Name = "Avid Interplay PAM"; + + public static class AccessRulesRequestsTable + { + public static readonly int PID = 1600; + + public static readonly int StatusColumnPid = 1604; + + public static readonly int ResponseColumnPid = 1605; + + public static readonly int RequestWritePid = 1621; + } + + public static class FolderRequestsTable + { + public static readonly int PID = 1700; + + public static readonly int StatusColumnPid = 1704; + + public static readonly int ResponseColumnPid = 1705; + } + + public static class Parameter + { + public static readonly int ExternalFolderRequest = 1720; + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/CeitonProtocol.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/CeitonProtocol.cs new file mode 100644 index 0000000..1cb34c9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/CeitonProtocol.cs @@ -0,0 +1,60 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class CeitonProtocol + { + public static readonly string Name = "Ceiton Resource Planning"; + + public static class ProjectTasksTable + { + public static readonly int PID = 1200; + + public static readonly int ProjectIdIdx = 1; + + public static readonly int ProjectIdPid = 1202; + + public static readonly int StartTimeIdx = 5; + + public static readonly int StartTimePid = 1206; + + public static readonly int EndTimeIdx = 6; + + public static readonly int EndTimePid = 1207; + + public static readonly int ActivityTypeNameIdx = 9; + + public static readonly int ActivityTypeNamePid = 1210; + } + + public static class ProductTasksTable + { + public static readonly int PID = 1300; + + public static readonly int ProjectIdIdx = 1; + + public static readonly int ProjectIdPid = 1302; + + public static readonly int StartTimeIdx = 5; + + public static readonly int StartTimePid = 1306; + + public static readonly int EndTimeIdx = 6; + + public static readonly int EndTimePid = 1307; + + public static readonly int ActivityTypeNameIdx = 9; + + public static readonly int ActivityTypeNamePid = 1310; + } + + public static class AdHocTasksTable + { + public static readonly int PID = 1400; + + public static readonly int StartTimeIdx = 5; + + public static readonly int EndTimeIdx = 6; + + public static readonly int ActivityTypeNameIdx = 8; + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/Constants.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/Constants.cs new file mode 100644 index 0000000..f864d10 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/Constants.cs @@ -0,0 +1,20 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class Constants + { + public static readonly string None = "None"; + public static readonly string NotFound = "Not found"; + + public static readonly string Automatic = "Automatic"; + + public static readonly string NotApplicable = "N/A"; + + public static readonly int MaximumAllowedCharacters = 400; + + public static readonly string OrderLoggingDirectoryName = "OrderLogging"; + + public static readonly string MetricLoggingDirectoryName = "MetricLogging"; + + public static readonly string ReplacedKeyWord = "_Replaced"; + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ContractManagerProtocol.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ContractManagerProtocol.cs new file mode 100644 index 0000000..353a62f --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ContractManagerProtocol.cs @@ -0,0 +1,80 @@ +using Skyline.DataMiner.Library; +using System.Collections.Generic; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class ContractManagerProtocol + { + public static readonly string ProtocolName = "Finnish Broadcasting Company Contract Manager"; + + public static readonly int UsersGroupTableID = 3000; + public static readonly int GroupId = 0; + public static readonly int GroupNameIdx = 1; + public static readonly int CompanyIdx = 11; + public static readonly int SportsIdx = 12; + public static readonly int McrIdx = 13; + public static readonly int GroupCustomNameIdx = 14; + public static readonly int FilterInternalItemsIdx = 24; + public static readonly int ConfigureTemplatesIdx = 25; + public static readonly int NewsIdx = 32; + public static readonly int SwapResourcesIdx = 33; + + public static readonly IReadOnlyDictionary UserGroupParamsIDX = new Dictionary { + { CompanyIdx, "Company" }, + { SportsIdx, "Sports" }, + { McrIdx, "MCR" }, + { GroupCustomNameIdx, "Custom Name" }, + { FilterInternalItemsIdx, "Filter Internal Items" }, + { ConfigureTemplatesIdx, "Configure Templates" }, + { NewsIdx, "News" }, + { SwapResourcesIdx, "Swap Resources" } + }; + + public static readonly int UsersTableID = 14000; + public static readonly int UsersID = 0; + public static readonly int UsersNameIDX = 1; + public static readonly int UsersEmailIDX = 3; + public static readonly int ConfirmationByOperatorIDX = 4; + public static readonly int RejectionByOperatorIDX = 5; + public static readonly int CompletionByDataminerIDX = 6; + public static readonly int CompletionWithErrorByDataminerIDX = 7; + public static readonly int CancellationByCustomerIDX = 8; + public static readonly int CancellationByOperatorIDX = 9; + public static readonly int CancellationByIntegrationIDX = 10; + public static readonly int NloReassignedByOperatorIDX = 11; + public static readonly int NloRejectionByOperatorIDX = 12; + public static readonly int NloCompletionByDataminerIDX = 13; + public static readonly int NloCancellationByOperatorIDX = 14; + public static readonly int NloWorkInProgressByOperatorIDX = 15; + public static readonly int ServicesBookedIDX = 17; + public static readonly int ServicesBookedByIntegrationsIDX = 18; + public static readonly int NloEditedByOperatorIDX = 19; + public static readonly int NloCreationByOperatorIDX = 20; + public static readonly int NloIplayFolderCreationByOperatorIDX = 21; + public static readonly int UsersPhoneIDX = 22; + public static readonly int UnableToBookRecurringVizrem = 23; + + public static readonly IReadOnlyDictionary NotificationParamsIDX = new Dictionary { + { UsersEmailIDX, "Email" }, + { UsersPhoneIDX, "Phone" }, + { ConfirmationByOperatorIDX, "Live Order Confirmation by Operator Notification" }, + { RejectionByOperatorIDX, "Live Order Rejection by Operator Notification" }, + { CompletionByDataminerIDX, "Live Order Completion by DataMiner Notification" }, + { CompletionWithErrorByDataminerIDX, "Live Order Completion with Errors by DataMiner Notification" }, + { CancellationByCustomerIDX, "Live Order Cancellation by Customer Notification" }, + { CancellationByOperatorIDX, "Live Order Cancellation by Operator Notification" }, + { CancellationByIntegrationIDX, "Live Order Cancellation by Integration Notification" }, + { NloReassignedByOperatorIDX, "Non Live Order Reassigned by Operator" }, + { NloRejectionByOperatorIDX, "Non Live Order Rejection by Operator" }, + { NloCompletionByDataminerIDX, "Non Live Order Completion by DataMiner" }, + { NloCancellationByOperatorIDX, "Non Live Order Cancellation by Operator" }, + { NloWorkInProgressByOperatorIDX, "Non Live Order Work in Progress by Operator" }, + { ServicesBookedIDX, "Live Order Services Booked Notification" }, + { ServicesBookedByIntegrationsIDX, "Live Order Services Booked by Integrations Notification" }, + { NloEditedByOperatorIDX, "Non Live Order Edited by Operator" }, + { NloCreationByOperatorIDX, "Non Live Order Creation by Operator" }, + { NloIplayFolderCreationByOperatorIDX, "Non Live Order Iplay Folder Creation by Operator" }, + { UnableToBookRecurringVizrem, "Unable to Book Recurring Vizrem Order" } + }; + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/EvsIpdViaProtocol.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/EvsIpdViaProtocol.cs new file mode 100644 index 0000000..954897a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/EvsIpdViaProtocol.cs @@ -0,0 +1,186 @@ +using System.ComponentModel; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class EvsIpdViaProtocol + { + public static readonly string Name = "EVS IPD-VIA"; + + public static class RecordersTable + { + public static readonly int TablePid = 1000; + + public static class Idx + { + public static readonly int RecordersName = 1; + } + } + + public static class TargetsTable + { + public static readonly int TablePid = 1100; + + public static class Idx + { + public static readonly int TargetsName = 1; + } + } + + public static class RecordingSessionsTable + { + public static readonly int TablePid = 1400; + + public static readonly int RecordingSessionsName = 1402; + + public static class Idx + { + public static readonly int RecordingSessionsInstanceIdx = 0; + + public static readonly int RecordingSessionsNameIdx = 1; + + public static readonly int RecordingSessionsStatusIdx = 2; + + public static readonly int RecordingSessionsStartIdx = 3; + + public static readonly int RecordingSessionsEndIdx = 4; + + public static readonly int RecordingSessionsRecorderIdx = 5; + } + } + + public class ProfileFieldsTable + { + /// PID: 1900 + public static readonly int TablePid = 1900; + + public class Pid + { + public static readonly int ProfileFieldsInstance = 1901; + + public static readonly int ProfileFieldsKey = 1902; + + public static readonly int ProfileFieldsLabel = 1903; + + public static readonly int ProfileFieldsType = 1904; + + public static readonly int ProfileFieldsRequired = 1905; + + public static readonly int ProfileFieldsValueConstraints = 1906; + + public static readonly int ProfileFieldsPredefinedValue = 1907; + + public static readonly int ProfileFieldsProfileFqn = 1908; + + public static readonly int ProfileFieldsProfileName = 1909; + + public static readonly int ProfileFieldsDisplayKey = 1910; + + public static readonly int ProfileFieldsFqnContraints = 1911; + } + + public class Idx + { + public static readonly int ProfileFieldsInstance = 0; + + public static readonly int ProfileFieldsKey = 1; + + public static readonly int ProfileFieldsLabel = 2; + + public static readonly int ProfileFieldsType = 3; + + public static readonly int ProfileFieldsRequired = 4; + + public static readonly int ProfileFieldsValueConstraints = 5; + + public static readonly int ProfileFieldsPredefinedValue = 6; + + public static readonly int ProfileFieldsProfileFqn = 7; + + public static readonly int ProfileFieldsProfileName = 8; + + public static readonly int ProfileFieldsDisplayKey = 9; + + public static readonly int ProfileFieldsFqnContraints = 10; + } + } + + public static class RecordingSessionsTargetsTable + { + public static readonly int TablePid = 1500; + + public class Pid + { + public static readonly int RecordingSessionsTargetsInstance = 1501; + + public static readonly int RecordingSessionsTargetsRecordingSessionDisplayKey = 1502; + + public static readonly int RecordingSessionsTargetsRecordingSessionInstance = 1503; + + public static readonly int RecordingSessionsTargetsRecordingSession = 1504; + + public static readonly int RecordingSessionsTargetsTargetInstance = 1505; + + public static readonly int RecordingSessionsTargetsTarget = 1506; + } + + public class Idx + { + public static readonly int RecordingSessionsTargetsInstance = 0; + + public static readonly int RecordingSessionsTargetsRecordingSessionDisplayKey = 1; + + public static readonly int RecordingSessionsTargetsRecordingSessionInstance = 2; + + public static readonly int RecordingSessionsTargetsRecordingSession = 3; + + public static readonly int RecordingSessionsTargetsTargetInstance = 4; + + public static readonly int RecordingSessionsTargetsTarget = 5; + } + } + + public class RecordingSessionsMetadataValuesTable + { + public static readonly int TablePid = 1700; + + public class Pid + { + public static readonly int RecordingSessionsMetadataValuesInstance = 1701; + + public static readonly int RecordingSessionsMetadataValuesKey = 1702; + + public static readonly int RecordingSessionsMetadataValuesValue = 1703; + + public static readonly int RecordingSessionsMetadataValuesRecordingSession = 1704; + + public static readonly int RecordingSessionsMetadataValuesRecordingSessionId = 1705; + + public static readonly int RecordingSessionsMetadataValuesDisplayKey = 1706; + + public static readonly int RecordingSessionsMetadataValuesProfile = 1707; + + public static readonly int RecordingSessionsMetadataValuesProfileId = 1708; + } + + public class Idx + { + + public static readonly int RecordingSessionsMetadataValuesInstance = 0; + + public static readonly int RecordingSessionsMetadataValuesKey = 1; + + public static readonly int RecordingSessionsMetadataValuesValue = 2; + + public static readonly int RecordingSessionsMetadataValuesRecordingSession = 3; + + public static readonly int RecordingSessionsMetadataValuesRecordingSessionId = 4; + + public static readonly int RecordingSessionsMetadataValuesDisplayKey = 5; + + public static readonly int RecordingSessionsMetadataValuesProfile = 6; + + public static readonly int RecordingSessionsMetadataValuesProfileId = 7; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/FeenixProtocol.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/FeenixProtocol.cs new file mode 100644 index 0000000..bdc7b0d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/FeenixProtocol.cs @@ -0,0 +1,52 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class FeenixProtocol + { + public static readonly int LastReceivedNotificationParameterId = 10; + + public static class LiveStreamOrdersTable + { + public const int AreenaIdIdx = 0; + + public const int MainFinnishTitleIdx = 10; + + public const int MainSwedishTitleIdx = 11; + + public const int MainSamiTitleIdx = 79; + + public const int VideoResolutionIdx = 37; + + public const int VideoFrameRateIdx = 38; + + public const int SourceNameIdx = 39; + + public const int ProgramLanguageIdx = 41; + + public const int DestinationIdx = 42; + + public const int StartIdx = 47; + + public const int EndIdx = 48; + + public const int ExactEndIdx = 54; + + public const int DeletedIdx = 57; + + public const int SourceLabelIdx = 71; + + public const int PlasmaIdIdx = 72; + + public const int CeitonProjectIdIdx = 74; + + public const int CeitonProductIdIdx = 75; + + public const int MainDescriptionSamiIdx = 76; + public const int ShortDescriptionSamiIdx = 77; + public const int MemberOfDescriptionSamiIdx = 78; + public const int MainTitleSamiIdx = 79; + public const int PromoTitleSamiIdx = 80; + public const int MemberOfMainTitleSamiIdx = 81; + public const int MemberOfPromoTitleSamiIdx = 82; + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/FunctionElementPropertyNames.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/FunctionElementPropertyNames.cs new file mode 100644 index 0000000..e4e6ab1 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/FunctionElementPropertyNames.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class FunctionElementPropertyNames + { + public const string EventName = "Event Name"; + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/FunctionGuids.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/FunctionGuids.cs new file mode 100644 index 0000000..c2aca0c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/FunctionGuids.cs @@ -0,0 +1,119 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using Skyline.DataMiner.Library.Solutions.SRM; + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Linq; + + public static class FunctionGuids + { + private static readonly ConcurrentDictionary functionIdCache = new ConcurrentDictionary(); + +#pragma warning disable S2339 // Public constant members should not be used + public static readonly Guid Dummy = Guid.Empty; + public const string DummyString = "00000000-0000-0000-0000-000000000000"; + + public static readonly Guid Satellite = new Guid(SatelliteString); + public const string SatelliteString = "b4ac401c-455c-4e62-85fc-d0261dd9b922"; + + public static readonly Guid Antenna = new Guid(AntennaString); + public const string AntennaString = "3e578238-3588-4c74-820f-def427cc9953"; + + public static readonly Guid Demodulating = new Guid(DemodulatingString); + public const string DemodulatingString = "f6af0f47-fc8c-4be2-9eba-50593e1488bf"; + + public static readonly Guid Decoding = new Guid(DecodingString); + public const string DecodingString = "89c8f8ae-ef77-45b1-b6d3-6a2d8a87d9f1"; + + public static readonly Guid Recording = new Guid(RecordingString); + public const string RecordingString = "b141ee05-2154-4b5e-82bd-3751bc8ccd5b"; + + public static readonly Guid Destination = new Guid(DestinationString); + public const string DestinationString = "8e9af1bd-6ebb-48e3-b817-161c5a767b83"; + + public static readonly Guid FiberDecoding = new Guid("f52e89f0-c646-4bf9-84ee-1fb126c247d1"); + + public static readonly Guid FiberSource = new Guid("5ab13709-198d-42e2-b0ed-cb48caa96852"); + + public static readonly Guid FiberDestination = new Guid("9ab71ea5-13ce-4bc8-b412-9bd2df69a66f"); + + public static readonly Guid LiveUPasilaSource = new Guid("0f855e47-797a-4fae-b4ea-bf581ab57b8e"); + + public const string LiveUPasilaSourceString = "0f855e47-797a-4fae-b4ea-bf581ab57b8e"; + + public static readonly Guid GenericEncoding = new Guid("a6c7084d-c0b8-4b37-be7a-014f15eed3b4"); + + public static readonly Guid GenericModulating = new Guid(GenericModulatingString); + public const string GenericModulatingString = "24042a26-41e0-47d7-9ba9-59b14f11f21c"; +#pragma warning restore S2339 // Public constant members should not be used + + public static readonly Guid MatrixInputAsi = GetFunctionDefinitionIdByName("Matrix Input ASI"); + + public static readonly Guid MatrixOutputAsi = GetFunctionDefinitionIdByName("Matrix Output ASI"); + + public static readonly Guid MatrixInputLband = GetFunctionDefinitionIdByName("Matrix Input LBand"); + + public static readonly Guid MatrixOutputLband = GetFunctionDefinitionIdByName("Matrix Output LBand"); + + public static readonly Guid MatrixInputSdi = GetFunctionDefinitionIdByName("Matrix Input SDI"); + + public static readonly Guid MatrixOutputSdi = GetFunctionDefinitionIdByName("Matrix Output SDI"); + + public static readonly Guid IpDecodingOutput = GetFunctionDefinitionIdByName("IP Decoding Output"); + + public static readonly Guid IpDecoding= GetFunctionDefinitionIdByName("IP Decoding"); + + public static readonly IEnumerable AllMatrixGuids = new[] { MatrixInputAsi, MatrixOutputAsi, MatrixInputSdi, MatrixOutputSdi, MatrixInputLband, MatrixOutputLband }; + + public static readonly IEnumerable AllMatrixInputGuids = new[] { MatrixInputSdi, MatrixInputAsi, MatrixInputLband }; + + public static readonly IEnumerable AllMatrixOutputGuids = new[] { MatrixOutputAsi, MatrixOutputSdi, MatrixOutputLband }; + + public static readonly IReadOnlyDictionary MatrixFunctionPairs = new Dictionary + { + { MatrixInputAsi, MatrixOutputAsi }, + { MatrixInputLband, MatrixOutputLband }, + { MatrixInputSdi, MatrixOutputSdi }, + { MatrixOutputAsi, MatrixInputAsi }, + { MatrixOutputLband, MatrixInputLband }, + { MatrixOutputSdi, MatrixInputSdi } + }; + + public static bool IsMatrixFunction(Guid functionID) + { + return AllMatrixGuids.Contains(functionID); + } + + private static Guid GetFunctionDefinitionIdByName(string name) + { + if (!functionIdCache.ContainsKey(name)) + { + // This try catch was added because Unit tests don't have access to a DM System. + try + { + BuildFunctionIdCache(); + } + catch (Exception) + { + return Guid.NewGuid(); + } + } + + return functionIdCache[name]; + } + + private static void BuildFunctionIdCache() + { + var activeProtocolFunctionVersions = SrmManagers.ProtocolFunctionManager.GetAllProtocolFunctions(true).Select(p => p.ProtocolFunctionVersions.FirstOrDefault()); + foreach (var activeProtocolFunctionVersion in activeProtocolFunctionVersions) + { + foreach (var functionDefinition in activeProtocolFunctionVersion.FunctionDefinitions) + { + var functionDefinitionId = functionDefinition.FunctionDefinitionID.Id; + functionIdCache[functionDefinition.Name] = functionDefinitionId; + } + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/MediaParkki.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/MediaParkki.cs new file mode 100644 index 0000000..f8ea480 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/MediaParkki.cs @@ -0,0 +1,19 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + + public static class MediaParkki + { + public static readonly string Name = "Generic SMB"; + + public static readonly int filesTablePid = 200; + + public static readonly int rootFoldersTablePid = 300; + + public static readonly int foldersTablePid = 400; + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/OrderManagerProtocol.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/OrderManagerProtocol.cs new file mode 100644 index 0000000..518f746 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/OrderManagerProtocol.cs @@ -0,0 +1,208 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System.Collections.Generic; + using Skyline.DataMiner.Utils.YLE.Integrations; + + public static class OrderManagerProtocol + { + public static readonly string Name = "Finnish Broadcasting Company Order Manager"; + + public static readonly int EnableResourceElementTimeoutPid = 70; + public static readonly int ReprocessIntegrationOrdersPid = 20; + public static readonly int DeleteIntegrationOrdersPid = 21; + public static readonly int ClearIntegrationOrdersFailuresPid = 22; + + public static readonly int CeitonElementIdParameterId = 100; + public static readonly int PlasmaElementIdParameterId = 120; + public static readonly int FeenixElementIdParameterId = 140; + public static readonly int PebbleBeachElementIdParameterId = 160; + public static readonly int EbuElementIdParameterId = 180; + + public static readonly int CeitonStatusParameterId = 104; + public static readonly int PlasmaStatusParameterId = 124; + public static readonly int FeenixStatusParameterId = 144; + public static readonly int PebbleBeachStatusParameterId = 165; + public static readonly int EbuStatusParameterId = 184; + + public static readonly int IntegrationResponseParameterId = 201; + + public static readonly int LockRequestParameterId = 5200; + + public static readonly int OrderUpdateParameterId = 11; + + public static readonly int EventUpdateParameterId = 13; + + public static readonly int RecurringOrderUpdateParameterId = 2499; + + public static readonly int RecurringOrdersScriptStatusParameterId = 2494; + + public static readonly int RecurringOrdersLatestScriptStartParameterId = 2495; + + public static readonly int RecurringOrdersSlidingWindowSizeParameterId = 2420; + + public static readonly int RecurringOrdersMaxBookingAmountParameterId = 2421; + + public static readonly int DefaultServiceResourceAllocationWindowStartParameterId = 4100; + public static readonly int DefaultServiceResourceAllocationWindowEndParameterId = 4101; + + public static readonly int OrderServiceDeletionDelayParameterId = 2200; + + public static class UserGroupsTable + { + public static readonly int TablePid = 3000; + + public static readonly int EurovisionElementParameterId = 3004; + } + + public static class EventsTable + { + public static readonly int TablePid = 2500; + + public static readonly int DeleteParameterId = 2507; + } + + public static class RecurringOrdersTable + { + public static readonly int TablePid = 2400; + } + + public static class OrdersTable + { + public static readonly int TablePid = 2000; + + public static readonly int NameParameterId = 2002; + + public static readonly int BookServicesStatusParameterId = 2005; + + public static readonly int DeleteParameterId = 2006; + + public static readonly int BookServicesStatusIdx = 4; + + public static readonly int ResourceOverbookedRetryCounterReadPid = 2021; + + public static readonly int ResourceOverbookedRetryCounterWritePid = 2022; + } + + public static class IntegrationOrdersTable + { + public enum Status + { + Pending = 2 + } + + public static readonly int TablePid = 1200; + + public static readonly int IntegrationIdIdx = 1; + + public static readonly int IntegrationTypeIdx = 2; + + public static readonly int StatusPid = 1203; + + public static readonly int OrderIdPid = 1208; + + public static readonly int OrderIdIdx = 8; + + public static readonly int StatusWritePid = 1303; + + public static readonly int LastProcessedAtIdx = 10; + + public static readonly int LastProcessedAtPid = 1210; + } + + public static class LockRequestsTable + { + public static readonly int TablePid = 5000; + + public static readonly int StatusPid = 5006; + + public static readonly int ResponsePid = 5008; + } + + public static class ExternalServiceConfigurationRequests + { + public static readonly int ExternalServiceConfigurationRequestPid = 5700; + + public static readonly int ExternalServiceConfigurationRequestsTablePid = 5500; + public static readonly int ExternalServiceConfigurationRequestsTableRequestStatusColumnPid = 5505; + public static readonly int ExternalServiceConfigurationRequestsTableRequestStatusServiceConfigColumnPid = 5504; + } + + public static class DeviceAutomationConfigurationTable + { + public static readonly int TablePid = 2800; + + public static readonly IReadOnlyDictionary DiscreetToIntegrationType = new Dictionary + { + { 0, IntegrationType.None }, + { 1, IntegrationType.Plasma }, + { 2, IntegrationType.Feenix }, + }; + } + + public static class PlasmaNewsInclusionConfigurationTable + { + public static readonly int TablePid = 4300; + } + + public static class PlasmaNewsRecordingConfigurationTable + { + public static readonly int TablePid = 4500; + } + + public static class ServiceResourceAllocationWindowTable + { + public static readonly int TablePid = 4000; + + public static readonly int ServicePid = 4002; + public static readonly int StartPid = 4003; + public static readonly int EndPid = 4004; + } + + public static class AutoHideMessiOrdersConfigurationTable + { + public static readonly int TablePid = 4400; + public static readonly int OrderDescriptionIdx = 1; + public static readonly int StateIdx = 2; + public static readonly int IntegrationIdx = 3; + public static readonly int RegexCheckIdx = 4; + + + public static readonly IReadOnlyDictionary DiscreetToIntegrationType = new Dictionary + { + { 0, IntegrationType.None }, + { 1, IntegrationType.Ceiton }, + { 2, IntegrationType.Plasma }, + { 3, IntegrationType.Feenix }, + { 4, IntegrationType.Eurovision }, + { 5, IntegrationType.PebbleBeach }, + }; + } + + public class EvsMessiNewsTargetsTable + { + public static readonly int TablePid = 4600; + + public class Pid + { + public static readonly int Instance = 4601; + + public static readonly int RecordingFileDestinationPath = 4602; + + public static readonly int Target = 4603; + + public static readonly int DefaultState = 4604; + } + + public class Idx + { + public static readonly int Instance = 0; + + public static readonly int RecordingFileDestinationPath = 1; + + public static readonly int Target = 2; + + public static readonly int DefaultState = 3; + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ProfileParameterGuids.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ProfileParameterGuids.cs new file mode 100644 index 0000000..a176a14 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ProfileParameterGuids.cs @@ -0,0 +1,300 @@ +using System.CodeDom; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System; + using System.Collections.Generic; + using System.Linq; + + public static class ProfileParameterGuids + { + public static readonly Guid _DemodulatingConfiguration = new Guid("efd5d280-3997-4cb9-8bbd-28e18d7917b9"); + + public static readonly Guid _ServiceConfiguration = new Guid("9083c73c-7eb3-4fc9-85ea-02fea98312a9"); + + public static readonly Guid _Dummy = new Guid("68daab6a-9a7e-47fe-af62-ebd65311fcc4"); + + public static readonly Guid _Matrix = new Guid("bce4b6a3-4045-4ec0-88d3-ba61c15f8038"); + + public static readonly Guid _LnbFrequency = new Guid("5d1c933c-20ed-48b5-85b8-cb61d9b176e7"); + + public static readonly Guid _OrbitalPosition = new Guid("a9810b80-c127-47a1-9e08-777dbb758ea1"); + + public static readonly Guid _TvChannel = new Guid("26560675-38a6-4dba-af61-e23d75b3af1d"); + + public static readonly Guid _FeedType = new Guid("07278965-6138-46de-b1d6-1f02861c240d"); + + public static readonly Guid _IntegrationType = new Guid("ce84fa08-ae71-48e2-8731-f6e56428ae79"); + + public static readonly Guid AreenaCopy = new Guid("798393c6-4ddf-48c2-92ae-668433de3428"); + + public static readonly Guid AreenaDestinationLocation = new Guid("96cc6585-2b3a-4129-a7d3-85c58b61b5de"); + + public static readonly Guid AudioDeembeddingRequired = new Guid("1d51086a-ca66-4e1d-b84f-6fd05a24ee68"); + + public static readonly Guid AudioEmbeddingRequired = new Guid("a2726fd1-cc4b-4b23-b464-3684a0db4dd6"); + + public static readonly Guid AudioShufflingRequired = new Guid("01682ff9-2cc4-4cd5-8252-d5956424479a"); + + public static readonly Guid AudioDolbyDecodingRequired = new Guid("35215bb4-0faa-423f-beed-58ada9b604b3"); + + public static readonly Guid AudioChannel1 = new Guid(Strings.AudioChannel1String); + + public static readonly Guid AudioChannel2 = new Guid(Strings.AudioChannel2String); + + public static readonly Guid AudioChannel3 = new Guid(Strings.AudioChannel3String); + + public static readonly Guid AudioChannel4 = new Guid(Strings.AudioChannel4String); + + public static readonly Guid AudioChannel5 = new Guid(Strings.AudioChannel5String); + + public static readonly Guid AudioChannel6 = new Guid(Strings.AudioChannel6String); + + public static readonly Guid AudioChannel7 = new Guid(Strings.AudioChannel7String); + + public static readonly Guid AudioChannel8 = new Guid(Strings.AudioChannel8String); + + public static readonly Guid AudioChannel9 = new Guid(Strings.AudioChannel9String); + + public static readonly Guid AudioChannel10 = new Guid(Strings.AudioChannel10String); + + public static readonly Guid AudioChannel11 = new Guid(Strings.AudioChannel11String); + + public static readonly Guid AudioChannel12 = new Guid(Strings.AudioChannel12String); + + public static readonly Guid AudioChannel13 = new Guid(Strings.AudioChannel13String); + + public static readonly Guid AudioChannel14 = new Guid(Strings.AudioChannel14String); + + public static readonly Guid AudioChannel15 = new Guid(Strings.AudioChannel15String); + + public static readonly Guid AudioChannel16 = new Guid(Strings.AudioChannel16String); + + public static readonly Guid AudioChannel1Description = new Guid("fab7b647-df5f-43ac-9396-511fc6ba9f81"); + + public static readonly Guid AudioChannel2Description = new Guid("f08209ca-898b-40d3-835d-e5bca4420960"); + + public static readonly Guid AudioChannel3Description = new Guid("c4dc3e48-1d7e-48f0-832e-af4eecf716d4"); + + public static readonly Guid AudioChannel4Description = new Guid("8b2499e6-653b-409c-8c6c-ed9d56f989fe"); + + public static readonly Guid AudioChannel5Description = new Guid("19e761d7-31d1-48fe-8265-9b24f386eafd"); + + public static readonly Guid AudioChannel6Description = new Guid("cf014313-b2d3-46a3-8cc3-c7bb57946c5c"); + + public static readonly Guid AudioChannel7Description = new Guid("4a7c08cf-67a1-4e37-85fd-89bfe39331a8"); + + public static readonly Guid AudioChannel8Description = new Guid("0e478f07-4c48-4cb2-bd44-615cc197141a"); + + public static readonly Guid AudioChannel9Description = new Guid("145eda52-eb24-49bd-87b5-31edf8e1002f"); + + public static readonly Guid AudioChannel10Description = new Guid("868a72c4-7ed5-4d81-b8fd-c4e803681100"); + + public static readonly Guid AudioChannel11Description = new Guid("5b65ad74-d72b-42be-b1d6-87319580df88"); + + public static readonly Guid AudioChannel12Description = new Guid("bd8065e8-72d7-4907-a910-9f47ad48e79f"); + + public static readonly Guid AudioChannel13Description = new Guid("f114e37c-3627-4dda-8bd2-b0ce466c446b"); + + public static readonly Guid AudioChannel14Description = new Guid("3887c50c-c1fc-45aa-97bc-c24eeca812a4"); + + public static readonly Guid AudioChannel15Description = new Guid("45f43ff0-9c3b-4dd1-a50a-34faac268612"); + + public static readonly Guid AudioChannel16Description = new Guid("f28b5c26-639c-4881-80d1-dc1d6a95c422"); + + public static readonly Guid AudioReturnChannel = new Guid("b765fd4c-92ee-48f1-b858-4d04e3172dd9"); + + public static readonly Guid DownlinkFrequency = new Guid(Strings.DownlinkFrequencyString); + + public static readonly Guid Encoding = new Guid(Strings.EncodingString); + + public static readonly Guid EncryptionKey = new Guid(Strings.EncryptionKeyString); + + public static readonly Guid Fec = new Guid(Strings.FecString); + + public static readonly Guid FastRerun = new Guid("9100b6ea-5b40-4fce-8066-532bea045f65"); + + public static readonly Guid FeedName = new Guid("50e277dc-e0b5-4ba8-8384-d7b1764a3815"); + + public static readonly Guid FixedTieLineSource = new Guid("bfe1faa3-62a1-44d6-9db1-6ff7ac07605f"); + + public static readonly Guid Polarization = new Guid(Strings.PolarizationString); + + public static readonly Guid RollOff = new Guid(Strings.RollOffString); + + public static readonly Guid ResourceInputConnectionsAsi = new Guid("58a7e9e4-6a39-42c9-b275-92f9dc7f9003"); + + public static readonly Guid ResourceInputConnectionsLband = new Guid("5c8ea48d-fafb-4fae-9f43-8ce2e9347d90"); + + public static readonly Guid ResourceInputConnectionsSdi = new Guid("3fab320b-6059-47ee-aad3-bf98fbba9f06"); + + public static readonly Guid ResourceOutputConnectionsAsi = new Guid("3c08c3a7-d1fb-46f2-877b-8927345cf931"); + + public static readonly Guid ResourceOutputConnectionsLband = new Guid("a12733e0-1ba5-48b8-a253-1f353eaeae79"); + + public static readonly Guid ResourceOutputConnectionsSdi = new Guid("1f5d4759-1d66-4cbe-a4c0-6bb6fb6937d6"); + + public static readonly Guid ResourceInputConnectionsNdi = new Guid("5b669aef-6fd9-4bdb-867c-f3997571735c"); + + public static readonly Guid ResourceOutputConnectionsNdi = new Guid("65f63694-b861-4d95-879e-0d0f2f655472"); + + public static readonly Guid RemoteGraphics = new Guid("7504c7e2-4c65-4230-8302-41e4fc90d210"); + + public static readonly Guid SubtitleProxy = new Guid("7610d0f7-e068-4cd9-a014-0308b277d4f2"); + + public static readonly Guid SymbolRate = new Guid(Strings.SymbolRateString); + + public static readonly Guid ModulationStandard = new Guid(Strings.ModulationStandardString); + + public static readonly Guid Modulation = new Guid(Strings.ModulationString); + + public static readonly Guid EncryptionType = new Guid(Strings.EncryptionTypeString); + + public static readonly Guid VideoFormat = new Guid(Strings.VideoFormatString); + + public static readonly Guid RecordingVideoFormat = new Guid("105baed9-4031-4d7c-a436-d26fe608af7b"); + + public static readonly Guid ExternalCompaniesDestinationLocation = new Guid("62e5716c-85d8-4d01-a308-b87cc461b1b3"); + + public static readonly Guid EbuDestinationLocation = new Guid("b4213f38-3bb7-48a4-a61c-3ec0b609785e"); + + public static readonly Guid YleHelsinkiDestinationLocation = new Guid("603c52e0-ca2b-4171-bba9-9469250031d4"); + + public static readonly Guid YleMediapolisDestinationLocation = new Guid("ea655627-a17d-442a-9e51-5ddebee9755f"); + + public static readonly Guid FixedLineExternalCompaniesSourceLocation = new Guid("f0c352c7-5fa6-4338-a201-94c18fdb8d4e"); + + public static readonly Guid FixedLineHelsinkiCityConnectionsSourceLocation = new Guid("b1224510-bfbf-4506-9120-1eb33ad353d4"); + + public static readonly Guid FixedLineYleHelsinkiSourceLocation = new Guid("b9565c0d-a26f-4fa9-985a-cc162e8524d7"); + + public static readonly Guid FixedLineEbuSourceLocation = new Guid("b6877c1e-99c3-4971-a4da-7c47bcf274e3"); + + public static readonly Guid FixedLineLySourcePlasmaUserCode = new Guid("7bab8775-841d-4b14-ae83-e665d4768b47"); + + public static readonly Guid Channel = new Guid("af8e34b9-6a5b-4126-b65e-ec670e4099bd"); + + public static readonly Guid ServiceSelection = new Guid(Strings.ServiceSelectionString); + + public static readonly Guid OtherSatelliteName = new Guid("1d95c7e7-06be-4459-a5ef-a9975958ba3a"); + + public static readonly IReadOnlyCollection AllAudioProcessingRequiredGuids = new[] { AudioDeembeddingRequired, AudioDolbyDecodingRequired, AudioEmbeddingRequired, AudioShufflingRequired }; + + public static readonly IReadOnlyCollection AllAudioChannelConfigurationGuids = new[] { AudioDeembeddingRequired, AudioEmbeddingRequired, AudioShufflingRequired, AudioDolbyDecodingRequired, AudioChannel1, AudioChannel1Description, AudioChannel2, AudioChannel2Description, AudioChannel3, AudioChannel3Description, AudioChannel4, AudioChannel4Description, AudioChannel5, AudioChannel5Description, AudioChannel6, AudioChannel6Description, AudioChannel7, AudioChannel7Description, AudioChannel8, AudioChannel8Description, AudioChannel9, AudioChannel9Description, AudioChannel10, AudioChannel10Description, AudioChannel11, AudioChannel11Description, AudioChannel12, AudioChannel12Description, AudioChannel13, AudioChannel13Description, AudioChannel14, AudioChannel14Description, AudioChannel15, AudioChannel15Description, AudioChannel16, AudioChannel16Description }; + + public static readonly IReadOnlyCollection AllProcessingParameterGuids = new[] { ProfileParameterGuids.VideoFormat, ProfileParameterGuids.RemoteGraphics }.Concat(AllAudioProcessingRequiredGuids).ToArray(); + + public static readonly IReadOnlyCollection AllResourceInputConnectionGuids = new[] { ResourceInputConnectionsSdi, ResourceInputConnectionsLband, ResourceInputConnectionsAsi }; + + public static readonly IReadOnlyCollection AllResourceOutputConnectionGuids = new[] { ResourceOutputConnectionsSdi, ResourceOutputConnectionsLband, ResourceOutputConnectionsAsi }; + + public static readonly Guid InputVideoFormat = Guid.Parse("79a7d1f5-d750-400f-b5b9-b5e6d198ad25"); + + public static readonly Guid OutputVideoFormat = Guid.Parse("209d06c7-3b7a-49ae-a11f-b6d9f5920fca"); + + public static readonly Guid InputAudioChannel1 = Guid.Parse("b60f8740-f593-431b-8043-474ccb8f9566"); + + public static readonly Guid InputAudioChannel2 = Guid.Parse("1fe71070-44d5-4ad0-95db-103413935506"); + + public static readonly Guid InputAudioChannel3 = Guid.Parse("00d823aa-4363-4d49-9eb6-fa2a2712bf9c"); + + public static readonly Guid InputAudioChannel4 = Guid.Parse("bc63cd0f-1886-45ff-a675-659a2f840166"); + + public static readonly Guid InputAudioChannel5 = Guid.Parse("7d8a7d82-a328-4f5c-9c4d-a1f634fdefc5"); + + public static readonly Guid InputAudioChannel6 = Guid.Parse("81352369-5ece-4c1e-98d6-bd908589e2c4"); + + public static readonly Guid InputAudioChannel7 = Guid.Parse("cb840609-c68c-4636-9225-b3667685e29c"); + + public static readonly Guid InputAudioChannel8 = Guid.Parse("11ea232f-511e-463a-927a-d4ed4fac52b6"); + + public static readonly Guid InputAudioChannel9 = Guid.Parse("96837519-a1be-4415-aef9-ec7c148a8ce0"); + + public static readonly Guid InputAudioChannel10 = Guid.Parse("6701766b-60d4-499c-8e84-ee91f2afbc65"); + + public static readonly Guid InputAudioChannel11 = Guid.Parse("e39f61ce-515f-4134-b308-32fb6c3df9c0"); + + public static readonly Guid InputAudioChannel12 = Guid.Parse("b7e5efb5-8c48-4670-9d3b-c8315beeb0f8"); + + public static readonly Guid InputAudioChannel13 = Guid.Parse("4da8b4de-178c-4bbe-b48c-69f25dba46c9"); + + public static readonly Guid InputAudioChannel14 = Guid.Parse("c1f16b91-a429-4e09-b315-34900b6a0906"); + + public static readonly Guid InputAudioChannel15 = Guid.Parse("b305ea6d-9028-44e3-8b72-e394ade2ac0c"); + + public static readonly Guid InputAudioChannel16 = Guid.Parse("01133e53-fa18-48d8-bb3e-073326618f3c"); + + public static readonly Guid OutputAudioChannel1 = Guid.Parse("c18bcf3e-7985-45f4-b968-56826861b761"); + + public static readonly Guid OutputAudioChannel2 = Guid.Parse("3c8bc1f0-8509-4ca8-91a9-e3528cd69bc6"); + + public static readonly Guid OutputAudioChannel3 = Guid.Parse("edbc7e6d-0823-41b4-a0ac-89e0b0bb70a4"); + + public static readonly Guid OutputAudioChannel4 = Guid.Parse("9031245f-6c36-4437-a22d-b2b65fdedb17"); + + public static readonly Guid OutputAudioChannel5 = Guid.Parse("26f31192-01ab-45a1-b214-a56dab65072f"); + + public static readonly Guid OutputAudioChannel6 = Guid.Parse("f6e684f5-3627-4fb8-9406-2e6898655440"); + + public static readonly Guid OutputAudioChannel7 = Guid.Parse("447bb387-397d-4565-88ff-972488e1feba"); + + public static readonly Guid OutputAudioChannel8 = Guid.Parse("cdfb4027-3ebb-4167-bb87-b94e732f1461"); + + public static readonly Guid OutputAudioChannel9 = Guid.Parse("0f5ecba8-3c17-4831-b7f0-cca2a80e001f"); + + public static readonly Guid OutputAudioChannel10 = Guid.Parse("fee87c0a-bb43-4819-ad66-1d366f7435ed"); + + public static readonly Guid OutputAudioChannel11 = Guid.Parse("de03ea6a-029e-4bf2-ad57-646a14417c36"); + + public static readonly Guid OutputAudioChannel12 = Guid.Parse("9f964476-2a3b-4c49-8e75-deadfc91bc04"); + + public static readonly Guid OutputAudioChannel13 = Guid.Parse("65929b68-e642-4ed6-a669-27455690137e"); + + public static readonly Guid OutputAudioChannel14 = Guid.Parse("8de81be4-8daf-4e30-9a5f-2ae6fd1a22dd"); + + public static readonly Guid OutputAudioChannel15 = Guid.Parse("a4e3c96b-7c15-43a8-944d-61ddcc7c2905"); + + public static readonly Guid OutputAudioChannel16 = Guid.Parse("517be756-d2d3-4ce1-b9e7-cee150264c0c"); + + public static readonly Guid _Direction = Guid.Parse("4313870b-6eb5-4f7f-bdc3-32c2a439f0f2"); + + public static bool IsAudioChannelProfileParameter(Guid id) + { + return AllAudioChannelConfigurationGuids.Except(AllAudioProcessingRequiredGuids).Contains(id); + } + + public static class Strings + { +#pragma warning disable S2339 // Public constant members should not be used + public const string AudioChannel1String = "d4f1e0fe-1a72-4ec3-9fd8-aefd4785ebdf"; + public const string AudioChannel2String = "bce7eff1-a884-47af-a182-559e0cfa4379"; + public const string AudioChannel3String = "471d52de-b90c-4d8d-9cb5-b11916a06d08"; + public const string AudioChannel4String = "5f014774-c3ce-492e-96c3-cd7402dbe171"; + public const string AudioChannel5String = "fad366e6-2f29-466b-a286-434446cf6437"; + public const string AudioChannel6String = "5c68fb8a-5c8f-4970-aeb4-b04b5f465724"; + public const string AudioChannel7String = "83b3d476-39dd-4660-854f-27bbe6436914"; + public const string AudioChannel8String = "e9aeb156-a027-4898-b41e-6af88169a3ff"; + public const string AudioChannel9String = "5eadca8d-f96a-464d-81a4-139dc6da0fba"; + public const string AudioChannel10String = "7178133a-d8a8-485d-99fa-b909ef73d848"; + public const string AudioChannel11String = "052babfe-b396-4d3f-a305-21442b3e0fd1"; + public const string AudioChannel12String = "acb1bef4-f80b-424b-abd1-a51a05586a6d"; + public const string AudioChannel13String = "fa83f575-0935-4952-b561-ce349c7e59fb"; + public const string AudioChannel14String = "f60e0b3e-840a-47f1-b521-9e1dbdc28562"; + public const string AudioChannel15String = "2712a2f9-273a-439f-b85a-5101789782cf"; + public const string AudioChannel16String = "cc76cdc0-925c-472f-985f-c0c5e477639c"; + public const string DownlinkFrequencyString = "d045fe27-2163-4e9b-b4e6-41ec3eac2a5d"; + public const string EncodingString = "3efcc36d-2cb9-4f22-a1e1-fae50def51ca"; + public const string EncryptionKeyString = "09995fd9-9526-485c-99cb-1d9eb6178195"; + public const string EncryptionTypeString = "27465703-cd3c-40a7-81e4-cf72119a1e3b"; + public const string FecString = "3f6fb925-e996-496c-8760-34436590c47e"; + public const string PolarizationString = "3f5f30c2-a4b1-4ab6-be06-ecec2e35cd5d"; + public const string RollOffString = "a28cf11f-ccfe-4a76-99cd-cac5ee402a9a"; + public const string SymbolRateString = "9a752cb7-77f2-4f75-8b9a-9a290eaf81b5"; + public const string ModulationString = "ea300fb7-527f-4b14-aff9-7985875b82e3"; + public const string ModulationStandardString = "ed8446e9-e373-419d-9b9f-8a1c94ec8ae7"; + public const string ServiceSelectionString = "0e4008ca-5dd8-40f5-b141-cd8b631444ee"; + public const string VideoFormatString = "8dc6df35-c574-4412-bf52-de7e3c78201c"; +#pragma warning restore S2339 // Public constant members should not be used + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ResourcePoolGuids.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ResourcePoolGuids.cs new file mode 100644 index 0000000..8ce8f86 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ResourcePoolGuids.cs @@ -0,0 +1,45 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System; + + public static class ResourcePoolGuids + { + public static readonly Guid DestinationEbu = new Guid("6ab7ce1e-a9f4-4dbb-b2c8-65bd4d4a231c"); + + public static readonly Guid DestinationExternalCompanies = new Guid("0143d004-2bce-4b72-a7e3-70659268ae34"); + + public static readonly Guid DestinationHelsinkiCityConnections = new Guid("71759196-ecf7-4d6d-b4fb-53ae12a4f004"); + + public static readonly Guid DestinationYleHelsinkiDestination = new Guid("e1259322-8700-43ed-816c-eb394e0d2fe6"); + + public static readonly Guid DestinationYleMediapolisDestination = new Guid("440ab68a-5075-4706-b5d1-d973363fe3ae"); + + public static readonly Guid DestinationAreenaDestination = new Guid("fbeb2303-96b2-4cc9-a8d9-2d3f68aae36a"); + + public static readonly Guid ReceptionFixedLineEbu = new Guid("1113dbb1-8650-467f-a12e-a6d20901be13"); + + public static readonly Guid ReceptionFixedLineExternalCompanies = new Guid("9749edba-0a99-4230-a496-02d1f828c791"); + + public static readonly Guid ReceptionFixedLineHelsinkiCityConnections = new Guid("3141e408-5218-47cd-af38-373d6ef19aa5"); + + public static readonly Guid ReceptionFixedLineLySource = new Guid("290880f1-2ced-496e-ab38-cec9ef99eeeb"); + + public static readonly Guid ReceptionFixedLineYleMediapolis = new Guid("84eea6ba-35f8-4640-9e29-3bd18c0973a4"); + + public static readonly Guid ReceptionIpRtmpDecoding = new Guid("c5ef6606-3932-40f8-a6c4-f2785a625446"); + + public static readonly Guid ReceptionIpEbuFlexDecoding = new Guid("028ff600-ad9d-453f-8e8a-74e2d8a01eef"); + + public static readonly Guid ReceptionIpSkypeDecoding = new Guid("08b218fa-7c94-4d4f-8feb-4e8f750dddd2"); + + public static readonly Guid ReceptionIpSrtDecoding = new Guid("7780ddaf-1c6d-4011-8fcb-f146f25bf3fd"); + + public static readonly Guid ReceptionMicrowave = new Guid("654d7e9f-f1af-436c-bbbc-faf6e6b0be7f"); + + public static readonly Guid ReceptionSatelliteDecoding = new Guid("f9994872-60da-4990-96f3-dd7ef83b37b0"); + + public static readonly Guid ReceptionFixedLineYleHelsinki = new Guid("264be909-230e-4128-a8e7-37e9365e9211"); + + public static readonly Guid ReceptionLiveUMediapolisSource = new Guid("bacd8e96-c2a3-4979-8980-fc37abe3487e"); + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ResourcePropertyNames.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ResourcePropertyNames.cs new file mode 100644 index 0000000..b8bbb51 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ResourcePropertyNames.cs @@ -0,0 +1,51 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class ResourcePropertyNames + { + public static readonly string Matrix = "Matrix"; + + public static readonly string _Matrix = "_Matrix"; + + public static readonly string IsSpecificTieLine = "IsSpecificTieLine"; + + public static readonly string LnbFrequency = "LnbFrequency"; + + public static readonly string RequiresSpecificTieLine = "RequiresSpecificTieLine"; + + public static readonly string RequiresFixedNewsRecordingService = "RequiresFixedNewsRecordingService"; + + public static readonly string OnlyMessiNewsRecordingAllowedPropertyName = "OnlyMessiNewsRecordingAllowed"; + + public static readonly string LinkedIrdPropertyName = "LinkedIRD"; + + public static readonly string FixedTieLineSource = "FixedTieLineSource"; + + public static readonly string Priority = "Priority"; + + public static readonly string ResourceSelectionAllowed = "ResourceSelectionAllowed"; + + public static readonly string IsManualResourcePropertyName = "IsManualResource"; + + public static readonly string IsAutomated = "IsAutomated"; + + public static readonly string PrioritizedDestinationResource = "PrioritizedDestinationResource"; + + public static readonly string PrioritizedMessiLiveRecordingResource = "PrioritizedMessiLiveRecordingResource"; + + public static readonly string PrioritizedTieLine = "PrioritizedTieLine"; + + public static readonly string RequiresIpDecodingOutput = "RequiresIpDecodingOutput"; + + public static readonly string IpRxServerIp = "IpRxServerIp"; + + public static readonly string IpRxServerUrl = "IpRxServerUrl"; + + public static readonly string IpRxPort = "IpRxPort"; + + public static readonly string IpRxStreamKey = "IpRxStreamKey"; + + public static readonly string MapDemodulationStandardToMatchingValue = "MapDemodulationStandardToMatchingValue"; + + public static readonly string OtherSatelliteNameRequired = "OtherSatelliteNameRequired"; + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/Scripts.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/Scripts.cs new file mode 100644 index 0000000..655d9ee --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/Scripts.cs @@ -0,0 +1,149 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System.ComponentModel; + + public enum Scripts + { + None, + [Description("Live Order Form")] + LiveOrderForm, + [Description("Update Service")] + UpdateService, + [Description("Add Service")] + AddService, + [Description("Add Event")] + AddEvent, + [Description("Add Event From Template")] + AddEventFromTemplate, + [Description("Add Note")] + AddNote, + [Description("Add or Update Non-Live Order")] + AddOrUpdateNonLiveOrder, + [Description("Assign Ticket To Me")] + AssignTicketToMe, + [Description("Book Multiple Orders")] + BookMultipleOrders, + [Description("Cancel Multiple Orders")] + CancelMultipleOrders, + [Description("Confirm Orders")] + ConfirmOrders, + [Description("Delete Event")] + DeleteEvent, + [Description("Delete Non-Live Order")] + DeleteNonLiveOrder, + [Description("Duplicate Non-Live Order")] + DuplicateNonLiveOrder, + [Description("Aggregate Metrics")] + AggregateMetrics, + [Description("Assign Recording Resources")] + AssignRecordingResources, + [Description("Create Invoice Report")] + CreateInvoiceReport, + [Description("Debug")] + Debug, + [Description("Clear Expired Services")] + ClearExpiredServices, + [Description("Configure Contract Manager")] + ConfigureContractManager, + [Description("CustomerUI Launcher")] + CustomerUiLauncher, + [Description("Delete Integration Orders")] + DeleteIntegrationOrders, + [Description("Delete Unused Reservations")] + DeleteUnusedReservations, + [Description("Edit Order Template")] + EditOrderTemplate, + [Description("Execute Feenix Stop Command")] + ExecuteFeenixStopCommand, + [Description("Force Delete Order")] + ForceDeleteOrder, + [Description("Handle Event Action")] + HandleEventAction, + [Description("Handle Integration Update")] + HandleIntegrationUpdate, + [Description("Handle Non-Live Folder Deletion")] + HandleNonLiveFolderDeletion, + [Description("Handle Order Action")] + HandleOrderAction, + [Description("Handle Recurring Order Action")] + HandleRecurringOrderAction, + [Description("Handle Order Start Failure")] + HandleOrderStartFailure, + [Description("Handle Service Action")] + HandleServiceAction, + [Description("Handle Service Start Failure")] + HandleServiceStartFailure, + [Description("Local Backup")] + LocalBackup, + [Description("Merge Events")] + MergeEvents, + [Description("Migrate Resources In Bulk YLE")] + MigrateResourcesInBulkYLE, + [Description("Migrate Resources YLE")] + MigrateResourcesYLE, + [Description("Non-Live Local Backup")] + NonLiveLocalBackup, + [Description("Non-Live Order And Notes Cleanup")] + NonLiveOrderAndNotesCleanup, + [Description("Non-Live User Tasks Bulk Update")] + NonLiveUserTasksBulkUpdate, + [Description("Ericsson RX8200 Decoding PLS")] + Ericsson_RX8200_Decoding, + [Description("Ericsson RX8200 Demodulating PLS")] + Ericsson_RX8200_Demodulating, + [Description("Novelsat NS2000 Demodulating PLS")] + Novelsat_NS2000_Demodulating, + [Description("Poll Ceiton Resources")] + PollCeitonResources, + [Description("Release Recording Resources")] + ReleaseRecordingResources, + [Description("Reprocess Orders")] + ReprocessOrders, + [Description("Run Log Collector")] + RunLogCollector, + [Description("Send Non-Live Deletion Reminders")] + SendNonLiveDeletionReminders, + [Description("Send Order Debug Report")] + SendOrderDebugReport, + [Description("Set Element Custom Property")] + SetElementCustomProperty, + [Description("Show Ceiton Details")] + ShowCeitonDetails, + [Description("Show EBU Details")] + ShowEBUDetails, + [Description("Show Feenix Details")] + ShowFeenixDetails, + [Description("Show Order History")] + ShowOrderHistory, + [Description("Show Pebble Beach Details")] + ShowPebbleBeachDetails, + [Description("Show Plasma Details")] + ShowPlasmaDetails, + [Description("Stop Order")] + StopOrder, + [Description("Unassign Ticket")] + UnassignTicket, + [Description("Update Event")] + UpdateEvent, + [Description("Update Non-Live User Task")] + UpdateNonLiveUserTask, + [Description("Update Note")] + UpdateNote, + [Description("Update Order Status")] + UpdateOrderStatus, + [Description("Update Orders after UserTask Status Change")] + UpdateOrdersAfterUserTaskStatusChange, + [Description("Update Service Status")] + UpdateServiceStatus, + [Description("Update Ticket Status")] + UpdateTicketStatus, + [Description("Update Visibility Rights")] + UpdateVisibilityRights, + [Description("View Ticket")] + ViewTicket, + [Description("Trigger Pebble Beach Integration Update")] + TriggerPebbleBeachIntegrationUpdate, + [Description("Update Comments")] + UpdateComments, + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ServiceDefinitionGuids.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ServiceDefinitionGuids.cs new file mode 100644 index 0000000..efda461 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ServiceDefinitionGuids.cs @@ -0,0 +1,76 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System; + using System.Collections.Generic; + + public static class ServiceDefinitionGuids + { + public static readonly Guid RecordingMessiLive = Guid.Parse("60d9ab48-06bb-49df-9066-d253171af5da"); + + public static readonly Guid RecordingMessiLiveBackup = Guid.Parse("f7be12d5-2bce-4c2b-a4f1-951e0cd7f444"); + + public static readonly Guid RecordingMessiNews = Guid.Parse("4910989f-2c21-455f-b5c4-ff2e7aa2d23a"); + + public static readonly Guid YleHelsinkiDestination = Guid.Parse("6e8b2a02-7121-41d5-bc11-d7200ce1d69b"); + + public static readonly Guid YleVaasaDestinationServiceDefinitionId = Guid.Parse("5e080002-11a7-4aef-a495-e52d2a1a9d46"); + + public static readonly Guid YleMediapolisDestinationServiceDefinitionId = Guid.Parse("e7128afc-c5d3-4ceb-bc2b-00c24b5ecd7b"); + + public static readonly Guid HelsinkiCityConnectionsDestinationServiceDefinitionId = Guid.Parse("7a1a7e8d-b5b2-46c8-b40f-5fcdf56f8622"); + + public static readonly Guid AreenaDestinationServiceDefinitionId = Guid.Parse("35672072-95c7-406a-a56b-59e885a6d2dc"); + + public static readonly Guid EbuDestinationServiceDefinitionId = Guid.Parse("bb43b568-745e-49cf-ae9f-0cb856f31a41"); + + public static readonly Guid OtherDestinationServiceDefinitionId = Guid.Parse("c9969ee2-6744-4fb2-9656-554eec969b86"); + + public static readonly Guid ExternalCompaniesDestinationServiceDefinitionId = Guid.Parse("7dc30fe6-7d6f-40a7-ba33-fcb88fc22abc"); + + public static readonly Guid SatelliteTransmissionServiceDefinitionId = Guid.Parse("5fad39cb-6521-4208-b49b-0cfd063807b5"); + + public static readonly Guid FiberFullCapacityTransmissionServiceDefinitionId = Guid.Parse("f637fa34-a271-4253-94d8-62a379753ac2"); + + public static readonly Guid FixedLineLy = Guid.Parse("ff913685-f764-4cf1-8ca9-7c9c751e4778"); + + public static readonly Guid LiveUMediapolisRxServiceDefinitionId = Guid.Parse("142c5ab9-25f2-45c4-8390-755024bfdb17"); + + public static readonly Guid LiveUPasilaRxServiceDefinitionId = Guid.Parse("508564f6-01ea-4973-b441-8d61ea54e1ef"); + + public static readonly Guid SatelliteReceptionServiceDefinitionId = Guid.Parse("aecb710b-558e-46b9-8a5e-86886f7baa2f"); + + public static readonly Guid FiberFullCapacityReceptionServiceDefinitionId = Guid.Parse("e7d1e9bf-c158-4671-b51f-a2a6cecdd0c4"); + + public static readonly Guid FixedLineEbuReceptionServiceDefinitionId = Guid.Parse("74e0b355-3f0c-437e-b605-98762bdf3f6d"); + + public static readonly Guid FixedLineYleHelsinkiReceptionServiceDefinitionId = Guid.Parse("eb5023f0-c782-45e9-8652-e50d3b8cc6b4"); + + public static readonly Guid FixedLineAtvuReception = Guid.Parse("1555ec44-0ced-4d8d-adf5-7fdebb6d5700"); + + public static readonly Guid RoutingServiceDefinitionId = Guid.Parse("956d6249-21cd-461e-b3a2-2b04b30d9c67"); + + public static readonly Guid GraphicsProcessing = Guid.Parse("7d1af087-ae03-4ac8-9193-21947cecb85d"); + + public static readonly Guid VideoProcessing = Guid.Parse("d013dcc8-3951-4246-a7b2-c6fbc3d4bcd6"); + + public static readonly Guid AudioProcessing = Guid.Parse("eb543606-1b4f-48b6-92c2-27d197afb77b"); + + public static readonly Guid IpReceptionEbuFlex = Guid.Parse("e0bd4107-88d8-4f36-8aaf-025ecd9a8138"); + + public static readonly Guid IpReceptionRtmp = Guid.Parse("1775b440-4043-4ddf-9cb2-46810fe85783"); + + public static readonly Guid IpReceptionSrt = Guid.Parse("bd018cf4-38f3-4395-a5e3-e65c4ecc75ab"); + + public static readonly Guid VizremFarm = Guid.Parse("62f6c491-013a-4156-95c2-20fc749f4cc1"); + + public static readonly Guid VizremStudioHelsinki = Guid.Parse("795dff72-f74b-464a-92c0-8d94bf8e4caa"); + + public static readonly Guid VizremStudioMediapolis = Guid.Parse("c142bada-50d9-48b6-b138-90e252ad88cf"); + + public static readonly Guid St26NdiRouter = Guid.Parse("b1cb45db-8e0a-4a25-9ac7-630efff83249"); + + public static List AllVizremServiceDefinitions => new List { VizremFarm, VizremStudioHelsinki, VizremStudioMediapolis, St26NdiRouter }; + + public static List AllProcessingServiceDefinitions => new List { VideoProcessing, AudioProcessing, GraphicsProcessing }; + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ServiceDefinitionPropertyNames.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ServiceDefinitionPropertyNames.cs new file mode 100644 index 0000000..29f7af8 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ServiceDefinitionPropertyNames.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class ServiceDefinitionPropertyNames + { + public const string DiagramHashCode = "Diagram Hash Code"; + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ServicePropertyNames.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ServicePropertyNames.cs new file mode 100644 index 0000000..a4df2b4 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/ServicePropertyNames.cs @@ -0,0 +1,100 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System; + using System.Collections.Generic; + + /// + /// A static class containing all the names of custom properties on service reservations as defined in the Booking + /// Managers. + /// + public static class ServicePropertyNames + { +#pragma warning disable S2339 // Public constant members should not be used + public const string Status = "Status"; + + public const string VirtualPlatformPropertyName = "Virtual Platform"; + + public const string ShortDescription = "Short Description"; + + public const string ReportedIssuePropertyName = "Reported_Issue"; + + public const string ServiceLevelPropertyName = "ServiceLevel"; + + public const string IsGlobalEventLevelReceptionPropertyName = "IsGlobalEventLevelReception"; + + public const string IntegrationTypePropertyName = "Integration"; + + public const string IntegrationIsMasterPropertyName = "IntegrationIsMaster"; + + public const string LinkedServiceIdPropertyName = "LinkedServiceId"; + + public const string EurovisionIdPropertyName = "EurovisionId"; + + public const string EurovisionTransmissionNumberPropertyName = "EurovisionTransmissionNumber"; + + public const string EurovisionBookingDetailsPropertyName = "EurovisionBookingDetails"; + + public const string CommentsPropertyName = "Comments"; + + public const string OrderIdsPropertyName = "OrderIds"; + + public const string ContactInformationNamePropertyName = "ContactInformationName"; + + public const string ContactInformationTelephoneNumberPropertyName = "ContactInformationTelephoneNumber"; + + public const string LiveUDeviceNamePropertyName = "LiveUDeviceName"; + + public const string VidigoStreamSourceLinkPropertyName = "VidigoStreamSourceLink"; + + public const string RecordingConfigurationPropertyName = "RecordingConfiguration"; + + public const string BackupServicePropertyName = "UI_Backup"; + + public const string CommentaryAudioPropertyName = "UI_Comm_Audio"; + + public const string NameOfServiceToTransmitPropertyName = "NameOfServiceToTransmit"; + + public const string OrderNamePropertyName = "OrderName"; + + public const string AudioReturnInfoPropertyName = "AudioReturnInfo"; + + public const string PlasmaIdsForArchivingPropertyName = "Plasma ID for Archive"; + + public const string MessiLiveDescription = "MessiLiveDescription"; + + public const string LateChange = "LateChange"; + + public const string FileName = "FileName"; + + public const string Channel = "Channel"; + + public const string McrDestination = "MCRDestination"; + + public const string McrDescription = "MCRDescription"; + + public const string MCRStatus = "MCRStatus"; + + public const string Automated = "Automated"; + + public const string AllUserTasksCompleted = "AllUserTasksCompleted"; + + public const string EvsIdPropertyName = "EvsId"; + + public const string ProfileConfigurationFailReason = "ProfileConfigurationFailReason"; + + + public static readonly IEnumerable UiProperties = new List + { + BackupServicePropertyName, + CommentaryAudioPropertyName, + McrDestination, + McrDescription, + MessiLiveDescription, + ShortDescription, + FileName, + AllUserTasksCompleted, + }; + +#pragma warning restore S2339 // Public constant members should not be used + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/SrmConfiguration.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/SrmConfiguration.cs new file mode 100644 index 0000000..8a8235d --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/SrmConfiguration.cs @@ -0,0 +1,310 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System; + + public static class SrmConfiguration + { + // Booking Manager names + public static readonly string OrderBookingManagerElementName = "Order Booking Manager"; + + // Resource Pool names + public static readonly string AreenaDestinationResourcePool = "Destination.Areena Destination"; + + public static readonly string MessiNewsRecordingResourcePool = "Recording.Messi News.Recording"; + + public static readonly string MatrixInputSdiResourcePool = "Routing.Matrix Input SDI"; + + public static readonly string ReceptionSatelliteResourcePool = "Reception.Satellite.Satellite"; + + public static readonly string ReceptionSatelliteDecodingResourcePool = "Reception.Satellite.Decoding"; + + public static readonly string ReceptionSatelliteDemodulatingResourcePool = "Reception.Satellite.Demodulating"; + + public static readonly string TransmissionSatelliteResourcePool = "Transmission.Satellite.Satellite"; + + // Profile Parameter names + public static readonly string FeenixSourceProfileParameterName = "Feenix Source"; + + public static readonly string ResourceInputConnectionsSdiProfileParameterName = "ResourceInputConnections_SDI"; + + public static readonly string SubtitleProxyProfileParameterName = "Subtitle Proxy"; + + public static readonly string SubtitleProxyFormatProfileParameterName = "Subtitle Proxy Format"; + + public static readonly string FastRerunCopyProfileParameterName = "Fast Rerun"; + + public static readonly string FastAreenaCopyProfileParameterName = "Areena Copy"; + + public static readonly string YleHelsinkiDestinationLocationProfileParameterName = "YLE Helsinki Destination Location"; + + public static readonly string YleMediapolisDestinationLocationProfileParameterName = "YLE Mediapolis Destination Location"; + + public static readonly string RecordingTvChannelProfileParameterName = "_TV Channel"; + + public static readonly string PlasmaUserCodeProfileParameterName = "Plasma User Code"; + + public static readonly string FixedLineYleMediapolisSourceLocationProfileParameterName = "Fixed Line YLE Mediapolis Source Location"; + + public static readonly string AudioChannel1ProfileParameterName = "Audio Channel 1"; + + public static readonly string AudioChannel2ProfileParameterName = "Audio Channel 2"; + + public static readonly string AudioChannel3ProfileParameterName = "Audio Channel 3"; + + public static readonly string AudioChannel4ProfileParameterName = "Audio Channel 4"; + + public static readonly string AudioChannel5ProfileParameterName = "Audio Channel 5"; + + public static readonly string AudioChannel6ProfileParameterName = "Audio Channel 6"; + + public static readonly string AudioChannel7ProfileParameterName = "Audio Channel 7"; + + public static readonly string AudioChannel8ProfileParameterName = "Audio Channel 8"; + + public static readonly string AudioChannel9ProfileParameterName = "Audio Channel 9"; + + public static readonly string AudioChannel10ProfileParameterName = "Audio Channel 10"; + + public static readonly string AudioChannel11ProfileParameterName = "Audio Channel 11"; + + public static readonly string AudioChannel12ProfileParameterName = "Audio Channel 12"; + + public static readonly string AudioChannel13ProfileParameterName = "Audio Channel 13"; + + public static readonly string AudioChannel14ProfileParameterName = "Audio Channel 14"; + + public static readonly string AudioChannel15ProfileParameterName = "Audio Channel 15"; + + public static readonly string AudioChannel16ProfileParameterName = "Audio Channel 16"; + + public static readonly string AudioChannel1DescriptionProfileParameterName = "Audio Channel 1 Description"; + + public static readonly string AudioChannel2DescriptionProfileParameterName = "Audio Channel 2 Description"; + + public static readonly string AudioChannel3DescriptionProfileParameterName = "Audio Channel 3 Description"; + + public static readonly string AudioChannel4DescriptionProfileParameterName = "Audio Channel 4 Description"; + + public static readonly string AudioChannel5DescriptionProfileParameterName = "Audio Channel 5 Description"; + + public static readonly string AudioChannel6DescriptionProfileParameterName = "Audio Channel 6 Description"; + + public static readonly string AudioChannel7DescriptionProfileParameterName = "Audio Channel 7 Description"; + + public static readonly string AudioChannel8DescriptionProfileParameterName = "Audio Channel 8 Description"; + + public static readonly string AudioChannel9DescriptionProfileParameterName = "Audio Channel 9 Description"; + + public static readonly string AudioChannel10DescriptionProfileParameterName = "Audio Channel 10 Description"; + + public static readonly string AudioChannel11DescriptionProfileParameterName = "Audio Channel 11 Description"; + + public static readonly string AudioChannel12DescriptionProfileParameterName = "Audio Channel 12 Description"; + + public static readonly string AudioChannel13DescriptionProfileParameterName = "Audio Channel 13 Description"; + + public static readonly string AudioChannel14DescriptionProfileParameterName = "Audio Channel 14 Description"; + + public static readonly string AudioChannel15DescriptionProfileParameterName = "Audio Channel 15 Description"; + + public static readonly string AudioChannel16DescriptionProfileParameterName = "Audio Channel 16 Description"; + + public static readonly string AudioEmbeddingRequiredProfileParameterName = "Audio Embedding Required"; + + public static readonly string AudioDeembeddingRequiredProfileParameterName = "Audio Deembedding Required"; + + public static readonly string AudioDolbyDecodingProfileParameterName = "Audio Dolby Decoding Required"; + + public static readonly string AudioShufflingRequiredProfileParameterName = "Audio Shuffling Required"; + + public static readonly string FeedTypeProfileParameterName = "_Feed Type"; + + public static readonly string[] AudioProfileParameterNames = new [] + { + // Audio Channels + AudioChannel1ProfileParameterName, + AudioChannel2ProfileParameterName, + AudioChannel3ProfileParameterName, + AudioChannel4ProfileParameterName, + AudioChannel5ProfileParameterName, + AudioChannel6ProfileParameterName, + AudioChannel7ProfileParameterName, + AudioChannel8ProfileParameterName, + AudioChannel9ProfileParameterName, + AudioChannel10ProfileParameterName, + AudioChannel11ProfileParameterName, + AudioChannel12ProfileParameterName, + AudioChannel13ProfileParameterName, + AudioChannel14ProfileParameterName, + AudioChannel15ProfileParameterName, + AudioChannel16ProfileParameterName, + // Audio Channel Descriptions + AudioChannel1DescriptionProfileParameterName, + AudioChannel2DescriptionProfileParameterName, + AudioChannel3DescriptionProfileParameterName, + AudioChannel4DescriptionProfileParameterName, + AudioChannel5DescriptionProfileParameterName, + AudioChannel6DescriptionProfileParameterName, + AudioChannel7DescriptionProfileParameterName, + AudioChannel8DescriptionProfileParameterName, + AudioChannel9DescriptionProfileParameterName, + AudioChannel10DescriptionProfileParameterName, + AudioChannel11DescriptionProfileParameterName, + AudioChannel12DescriptionProfileParameterName, + AudioChannel13DescriptionProfileParameterName, + AudioChannel14DescriptionProfileParameterName, + AudioChannel15DescriptionProfileParameterName, + AudioChannel16DescriptionProfileParameterName, + // Audio Config + AudioEmbeddingRequiredProfileParameterName, + AudioDeembeddingRequiredProfileParameterName, + AudioDolbyDecodingProfileParameterName, + AudioShufflingRequiredProfileParameterName + }; + + public static readonly string[] AudioChannelsProfileParameterNames = new[] + { + // Audio Channels + AudioChannel1ProfileParameterName, + AudioChannel2ProfileParameterName, + AudioChannel3ProfileParameterName, + AudioChannel4ProfileParameterName, + AudioChannel5ProfileParameterName, + AudioChannel6ProfileParameterName, + AudioChannel7ProfileParameterName, + AudioChannel8ProfileParameterName, + AudioChannel9ProfileParameterName, + AudioChannel10ProfileParameterName, + AudioChannel11ProfileParameterName, + AudioChannel12ProfileParameterName, + AudioChannel13ProfileParameterName, + AudioChannel14ProfileParameterName, + AudioChannel15ProfileParameterName, + AudioChannel16ProfileParameterName, + // Audio Channel Descriptions + AudioChannel1DescriptionProfileParameterName, + AudioChannel2DescriptionProfileParameterName, + AudioChannel3DescriptionProfileParameterName, + AudioChannel4DescriptionProfileParameterName, + AudioChannel5DescriptionProfileParameterName, + AudioChannel6DescriptionProfileParameterName, + AudioChannel7DescriptionProfileParameterName, + AudioChannel8DescriptionProfileParameterName, + AudioChannel9DescriptionProfileParameterName, + AudioChannel10DescriptionProfileParameterName, + AudioChannel11DescriptionProfileParameterName, + AudioChannel12DescriptionProfileParameterName, + AudioChannel13DescriptionProfileParameterName, + AudioChannel14DescriptionProfileParameterName, + AudioChannel15DescriptionProfileParameterName, + AudioChannel16DescriptionProfileParameterName + }; + + public static readonly string[] AudioConfigProfileParameterNames = new[] + { + // Audio Config + AudioEmbeddingRequiredProfileParameterName, + AudioDeembeddingRequiredProfileParameterName, + AudioDolbyDecodingProfileParameterName, + AudioShufflingRequiredProfileParameterName + }; + + public static readonly string VideoFormatProfileParameterName = "Video Format"; + + public static readonly string DownlinkFrequencyProfileParameterName = "Downlink Frequency"; + + public static readonly string UplinkFrequencyProfileParameterName = "Uplink Frequency"; + + public static readonly string FecProfileParameterName = "FEC"; + + public static readonly string ModulationProfileParameterName = "Modulation"; + + public static readonly string ModulationStandardProfileParameterName = "Modulation Standard"; + + public static readonly string PolarizationProfileParameterName = "Polarization"; + + public static readonly string SymbolRateProfileParameterName = "Symbol Rate"; + + public static readonly string EncodingProfileParameterName = "Encoding"; + + public static readonly string EncryptionKeyProfileParameterName = "Encryption Key"; + + public static readonly string EncryptionTypeProfileParameterName = "Encryption Type"; + + public static readonly string ServiceSelectionProfileParameterName = "Service Selection"; + + public static readonly string FixedLineEbuSourceLocationProfileParameterName = "Fixed Line EBU Source Location"; + + public static readonly string EbuDestinationLocationProfileParameterName = "EBU Destination Location"; + + // Profile Parameter values + public static readonly string DestinationLocationPlayoutProfileParameterValue = "Lähetysyksikkö"; + + public static readonly string DestinationLocationDummyPlayoutProfileParameterValue = "Lähetysyksikkö [Plasma]"; + + public static readonly string AudioChannelInternationalProfileParameterValue = "International Mix"; + + public static readonly string AudioChannelFinnishProfileParameterValue = "Fin Mix"; + + public static readonly string AudioChannelSwedishProfileParameterValue = "Swe Mix"; + + public static readonly string EncryptionTypeFreeProfileParameterValue = "FREE"; + + public static readonly string RecordingTvChannelNoneProfileParameterValue = "None"; + + public static readonly string RecordingTvChannelTv1ProfileParameterValue = "TV 1"; + + public static readonly string RecordingTvChannelTv2ProfileParameterValue = "TV 2"; + + public static readonly string RecordingTvChannelTvTeemaFemProfileParameterValue = "TV TEEMA/FEM"; + + public static readonly string FixedLineEbuSourceLocationAcesEbuProfileParameterValue = "ACES EBU"; + + public static readonly string FixedLineEbuSourceLocationNordicRingProfileParameterValue = "Nordic Ring"; + + public static readonly string FixedLineYleMediapolisSourceLocationMediapolisStudioProfileParameterValue = "Mediapolis Studio"; + + public static readonly string YleMediapolisDestinationLocationMediapolisLtProfileParameterValue = "Mediapolis LT"; + + // Function Definition ids + public static readonly Guid SourceParentSystemFunctionDefinitionId = Guid.Parse("c7e8648e-7522-4724-99a8-74e48a45f380"); + + // Service Definition ids + // Receptions + public static readonly Guid FixedLineLyServiceDefinitionId = Guid.Parse("ff913685-f764-4cf1-8ca9-7c9c751e4778"); + + public static readonly Guid FixedLineMediapolisServiceDefinitionId = Guid.Parse("338527f4-3b09-46b6-bfb7-89d4ca1cb4cf"); + + public static readonly Guid SatelliteReceptionServiceDefinitionId = Guid.Parse("aecb710b-558e-46b9-8a5e-86886f7baa2f"); + + public static readonly Guid FiberFullCapacityReceptionServiceDefinitionId = Guid.Parse("e7d1e9bf-c158-4671-b51f-a2a6cecdd0c4"); + + public static readonly Guid FixedLineEbuReceptionServiceDefinitionId = Guid.Parse("74e0b355-3f0c-437e-b605-98762bdf3f6d"); + + // Transmissions + public static readonly Guid SatelliteTransmissionServiceDefinitionId = Guid.Parse("5fad39cb-6521-4208-b49b-0cfd063807b5"); + + public static readonly Guid FiberFullCapacityTransmissionServiceDefinitionId = Guid.Parse("f637fa34-a271-4253-94d8-62a379753ac2"); + + // Destinations + public static readonly Guid YleHelsinkiDestinationServiceDefinitionId = Guid.Parse("6e8b2a02-7121-41d5-bc11-d7200ce1d69b"); + + public static readonly Guid AreenaDestinationServiceDefinitionId = Guid.Parse("35672072-95c7-406a-a56b-59e885a6d2dc"); + + public static readonly Guid EbuDestinationServiceDefinitionId = Guid.Parse("bb43b568-745e-49cf-ae9f-0cb856f31a41"); + + public static readonly Guid MediapolisDestinationServiceDefinitionId = Guid.Parse("e7128afc-c5d3-4ceb-bc2b-00c24b5ecd7b"); + + // Recordings + public static readonly Guid RecordingMessiLiveServiceDefinitionId = Guid.Parse("60d9ab48-06bb-49df-9066-d253171af5da"); + + public static readonly Guid RecordingMessiLiveBackupServiceDefinitionId = Guid.Parse("f7be12d5-2bce-4c2b-a4f1-951e0cd7f444"); + + public static readonly Guid RecordingMessiNewsServiceDefinitionId = Guid.Parse("4910989f-2c21-455f-b5c4-ff2e7aa2d23a"); + + public static string BooleanToProfileParameterValue(bool value) + { + return value ? "Yes" : "No"; + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/SrmConfigurationManager.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/SrmConfigurationManager.cs new file mode 100644 index 0000000..69a5d4c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/SrmConfigurationManager.cs @@ -0,0 +1,58 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + using System.Collections.Generic; + using System.Linq; + + using Skyline.DataMiner.Library.Solutions.SRM; + using Skyline.DataMiner.Net.Messages.SLDataGateway; + using Skyline.DataMiner.Net.ServiceManager.Objects; + + public static class SrmConfigurationManager + { + /// + /// Sets the SwapResource property on all nodes of all service definitions. + /// + /// This is a method to facilitate SRM configuration. The SwapResource property should be registered on Cube for this method to work. + public static void AddSwapResourcePropertyToEachNodeOfEachServiceDefinition() + { + var serviceManagerHelper = SrmManagers.ServiceManager; + + var serviceDefinitions = serviceManagerHelper.GetServiceDefinitions(ServiceDefinitionExposers.IsTemplate.Equal(true)); + foreach (var def in serviceDefinitions) + { + foreach (Node node in def.Diagram.Nodes) + { + if (!node.Properties.Any(p => p.Name == "SwapResource")) + { + node.Properties.Add(new Property("SwapResource", "{\"Enabled\":true}")); + } + } + } + + serviceManagerHelper.SetServiceDefinitions(serviceDefinitions, false, true); + } + + /// + /// Sets the RemoveResource property on all nodes of all service definitions. + /// + /// This is a method to facilitate SRM configuration. The RemoveResource property should be registered on Cube for this method to work. + public static void AddRemoveResourcePropertyToEachNodeOfEachServiceDefinition() + { + var serviceManagerHelper = SrmManagers.ServiceManager; + + var serviceDefinitions = serviceManagerHelper.GetServiceDefinitions(ServiceDefinitionExposers.IsTemplate.Equal(true)); + foreach (var def in serviceDefinitions) + { + foreach (Node node in def.Diagram.Nodes) + { + if (!node.Properties.Any(p => p.Name == "RemoveResource")) + { + node.Properties.Add(new Property("RemoveResource", "{\"Enabled\":true}")); + } + } + } + + serviceManagerHelper.SetServiceDefinitions(serviceDefinitions, false, true); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/SystemFunctionGuids.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/SystemFunctionGuids.cs new file mode 100644 index 0000000..126166b --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Configuration/SystemFunctionGuids.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Configuration +{ + public static class SystemFunctionGuids + { + public static readonly Guid Destination = new Guid("6918e61e-975b-4c82-9740-77f043943300"); + + public static readonly Guid VideoProcessing = new Guid("db640afb-2022-4731-a5dc-06ea31f44b62"); + + public static readonly Guid Recording = new Guid("89378eee-a8b7-433c-afea-7ec68d5df029"); + + public static readonly Guid AudioProcessing = new Guid("5b50d8af-8ccf-4aa9-87da-5e3f223639f0"); + + public static readonly Guid GraphicsProcessing = new Guid("03834a2b-3f70-4f2a-8c0d-a0eb9b42cd8c"); + + public static readonly Guid Routing = new Guid("78738536-7c34-40eb-9b13-44a8ed4c5fec"); + + public static readonly Guid Source = new Guid("c7e8648e-7522-4724-99a8-74e48a45f380"); + + public static readonly Guid Transmission = new Guid("147f77f6-74d6-4802-8603-5042a6e0ad5d"); + + public static readonly Guid VizremFarm = new Guid("c8f0bfd2-c0e0-4235-ad76-00930e111cd5"); + + public static readonly Guid VizremConverter = new Guid("72fdfb96-b134-4493-896c-030857947a68"); + + public static readonly Guid VizremSt26 = new Guid("65f23f55-81d9-4090-b848-bbc3cff3aac8"); + + public static readonly Guid VizremStudio = new Guid("6f0727a9-f2fc-48e0-aeea-4dd710c298c1"); + + public static List All() + { + return typeof(SystemFunctionGuids).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).Select(p => (Guid)p.GetValue(null)).ToList(); + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/Company.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/Company.cs new file mode 100644 index 0000000..dd82580 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/Company.cs @@ -0,0 +1,27 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + + public class Company + { + /// + /// Gets or sets the name of the company. + /// + public string Name { get; set; } + + /// + /// Gets or sets the description of the company. + /// + public string Description { get; set; } + + /// + /// Gets or sets the ID of the View associated with this company. + /// + public int SecurityViewId { get; set; } + + /// + /// Gets or sets the linked companies. + /// + public string LinkedCompanies { get; set; } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/Contract.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/Contract.cs new file mode 100644 index 0000000..6a3d724 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/Contract.cs @@ -0,0 +1,219 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Profile; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.ServiceDefinition; + using System; + using System.Collections.Generic; + using System.Linq; + + [Flags] + public enum GlobalEventLevelReceptionConfigurations + { + None = 0, + GlobalEventLevelReceptionUsageAllowed = 1, + PromoteGlobalEventLevelReceptionAllowed = 2, + } + + public class Contract + { + public Contract() + { + ServiceFilters = new ServiceFilter[0]; + } + + public string ID { get; set; } + + public string Name { get; set; } + + public string Description { get; set; } + + /// + /// Gets or sets the company linked to this contract. + /// + public string Company { get; set; } + + /// + /// Gets or sets the id of the view that is associated with the company linked to this contract. + /// + public int CompanySecurityViewId { get; set; } + + /// + /// Gets or sets the list of companies that are linked to the company of this contract. + /// + public Company[] LinkedCompanies { get; set; } + + /// + /// Gets or sets the start time for this contract. + /// + public DateTime Start { get; set; } + + /// + /// Gets or sets the end time for this contract. + /// + public DateTime End { get; set; } + + /// + /// Gets or sets the status for this contract. + /// + public ContractStatus Status { get; set; } + + /// + /// Gets or sets the type of this contract. + /// + public ContractType Type { get; set; } + + /// + /// Gets or sets the event id of the event linked to this contract. + /// + public string LinkedEventId { get; set; } + + /// + /// Gets or sets if all services that are not listed in the ServiceFilters are fully allowed for this contract. + /// + public bool AllowUnfilteredServices { get; set; } + + /// + /// Gets or sets the list of services that are allowed for this contract with additional filters on specific profile parameters. + /// + public ServiceFilter[] ServiceFilters { get; set; } + + /// + /// Contains the configuration of global event level receptions. + /// + public GlobalEventLevelReceptionConfigurations ContractGlobalEventLevelReceptionConfiguration { get; set; } + + /// + /// Verifies if the service using the provided service definition is allowed for the provided user. + /// + /// The service definition. + /// The user. + /// A boolean indicating if the service is allowed. + public bool IsServiceAllowed(ServiceDefinition serviceDefinition, UserInfo user) + { + if (serviceDefinition.IsIntegrationOnly) return false; + if (serviceDefinition.IsMcrOnly && !user.IsMcrUser) return false; + + return IsServiceAllowed(serviceDefinition.Name); + } + + /// + /// Verifies if audio processing is allowed for this contract. + /// + /// A boolean indicating if the audio processing is allowed. + public bool IsAudioProcessingAllowed() + { + return IsServiceAllowed("_Audio Processing"); + } + + /// + /// Verifies if video processing is allowed for this contract. + /// + /// A boolean indicating if the video processing is allowed. + public bool IsVideoProcessingAllowed() + { + return IsServiceAllowed("_Video Processing"); + } + + /// + /// Filters the provided service definitions and returns those that are allowed for the provided user. + /// + /// A list of allowed service definitions. + public List FilterServiceDefinitions(IReadOnlyList serviceDefinitions, UserInfo user) + { + if (Status != ContractStatus.Open) return new List(); + return serviceDefinitions.Where(x => IsServiceAllowed(x, user)).ToList(); + } + + /// + /// Verifies if the provided profile parameter is allowed to configure in this contract. + /// + /// The service definition. + /// The profile parameter. + /// The user. + /// A boolean indicating if this contract allows configuration of this profile parameter. + public bool IsProfileParameterAllowed(ServiceDefinition serviceDefinition, ProfileParameter profileParameter, UserInfo user) + { + // TODO check if this if-clause can be removed, it causes profile parameters to be invisible in LOF for integration orders (e.g.: Areena destination in Feenix order) + //if (!IsServiceAllowed(serviceDefinition, user)) return false; + + var serviceFilter = ServiceFilters.FirstOrDefault(f => f.ServiceDefinitionName == serviceDefinition.Name); + if (serviceFilter == null) return AllowUnfilteredServices; + + var profileParameterFilter = serviceFilter.ProfileParameterFilters.FirstOrDefault(p => p.ProfileParameterName == profileParameter.Name); + if (profileParameterFilter == null) return serviceFilter.AllowUnfilteredProfileParameters; + + return true; + } + + /// + /// Filters the allowed discreet values for the provided profile parameter. + /// + /// The service definition. + /// The profile parameter. + /// The user. + /// A list of allowed profile parameter values. + public List FilterProfileParameterValues(ServiceDefinition serviceDefinition, ProfileParameter profileParameter, UserInfo user) + { + var serviceFilter = ServiceFilters.FirstOrDefault(f => f.ServiceDefinitionName == serviceDefinition.Name); + if (serviceFilter == null) + { + return FilterValuesWithoutServiceFilter(profileParameter); + } + + var profileParameterFilter = serviceFilter.ProfileParameterFilters.FirstOrDefault(p => p.ProfileParameterName == profileParameter.Name); + if (profileParameterFilter == null) + { + return FilterValuesWithoutProfileParameterFilter(serviceFilter, profileParameter); + } + else + { + return FilterValues(profileParameterFilter, profileParameter, user); + } + } + + private List FilterValuesWithoutServiceFilter(ProfileParameter profileParameter) + { + return AllowUnfilteredServices ? profileParameter.Discreets.Select(d => d.DisplayValue).ToList() : new List(); + } + + private static List FilterValuesWithoutProfileParameterFilter(ServiceFilter serviceFilter, ProfileParameter profileParameter) + { + return serviceFilter.AllowUnfilteredProfileParameters + ? profileParameter.Discreets.Select(d => d.DisplayValue).ToList() + : new List(); + } + + private static List FilterValues(ProfileParameterFilter profileParameterFilter, ProfileParameter profileParameter, UserInfo user) + { + var allowedProfileParameterValues = new List(); + if (profileParameterFilter.AllowUnfilteredProfileParameterValues) allowedProfileParameterValues.AddRange(profileParameter.Discreets.Select(d => d.DisplayValue)); + + foreach (var profileparameterValueFilter in profileParameterFilter.ProfileParameterValueFilters) + { + if (!user.IsMcrUser && profileparameterValueFilter.IsMcrOnly) + { + allowedProfileParameterValues.Remove(profileparameterValueFilter.Value); + continue; + } + + if (!allowedProfileParameterValues.Contains(profileparameterValueFilter.Value)) allowedProfileParameterValues.Add(profileparameterValueFilter.Value); + } + + return allowedProfileParameterValues; + } + + private bool IsServiceAllowed(string serviceDefinitionName) + { + if (Status != ContractStatus.Open) return false; + + ServiceFilter serviceFilter = null; + if (ServiceFilters != null) serviceFilter = ServiceFilters.FirstOrDefault(f => f.ServiceDefinitionName == serviceDefinitionName); + + if (serviceFilter == null) return AllowUnfilteredServices; + + // TODO: simultaneous and fixed price check are not yet included + + return true; + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ContractManager.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ContractManager.cs new file mode 100644 index 0000000..2232acb --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ContractManager.cs @@ -0,0 +1,646 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Skyline.DataMiner.Automation; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions.Contracts; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using Skyline.DataMiner.Library.Automation; + using Skyline.DataMiner.Library.Exceptions; + + public class ContractManager : IContractManager + { + private readonly Helpers helpers; + private const int externalRequestParameterId = 50; + private const int externalRequestTableParameterId = 10000; + private const int externalRequestTableStatusParameterId = 10002; + private const int externalRequestTableResponseParameterId = 10004; + private const int externalRequestTableRemoveEntryParameterId = 10005; + + private const int OrderTemplatesTableTemplateColumnPid = 15004; + private const int EventTemplatesTableTemplateColumnPid = 16004; + + private const int CompaniesTableKeyIndex = 0; + private const int CompaniesTableSecurityViewIdIndex = 2; + + public const string DataminerUserLoginName = "DataMiner Agent"; + + /// + /// Initializes a new instance of the ContractManager class. + /// + /// Thrown when the provided Engine is null. + /// Thrown when no Finnish Broadcasting Company Contract Manager element running the production version of the protocol was found on the DMS. + /// Thrown when the found Finnish Broadcasting Company Contract Manager element is not running. + public ContractManager(Helpers helpers) + { + this.helpers = helpers ?? throw new ArgumentNullException(nameof(helpers)); + + Element = helpers.Engine.FindElementsByProtocol("Finnish Broadcasting Company Contract Manager", "Production").FirstOrDefault(); + if (Element == null) throw new ElementNotFoundException("Unable to find a Contract Manager element"); + + if (!Element.IsActive) throw new ElementNotStartedException("The Contract Manager element is not running"); + } + + public UserInfo GetUserInfo(Order order, string userLoginName) + { + return GetUserInfo(userLoginName, order?.Event); + } + + /// + /// Gets the User Info from the contract manager. + /// + /// + /// + /// + /// + /// + public UserInfo GetUserInfo(string userLoginName, Event @event = null) + { + switch (userLoginName) + { + case DataminerUserLoginName when @event == null: + throw new ArgumentNullException(nameof(@event), "Event cannot be null when userLoginName is " + DataminerUserLoginName); + case DataminerUserLoginName: + return GetUserInfoForCompany(@event); + default: + return GetUserInfoForUser(userLoginName, @event); + } + } + + /// + /// Gets the UserInfo for the given user login name. This method is used for NonLive Orders. + /// + /// + /// + public UserInfo GetBaseUserInfo(string userLoginName) + { + helpers.LogMethodStart(nameof(ContractManager), nameof(GetBaseUserInfo), out var stopwatch); + + var response = RequestUserContractDetails(helpers.Engine.UserLoginName); + var contract = response.Contracts.FirstOrDefault(c => c.Type == ContractType.BaseContract); + + if (contract == null) + { + helpers.Log(nameof(ContractManager), nameof(GetBaseUserInfo), "No base contract found for user " + userLoginName); + helpers.LogMethodCompleted(nameof(ContractManager), nameof(GetBaseUserInfo), null, stopwatch); + return null; + } + + User currentUser = null; + if (response.AllUsers != null && response.AllUsers.Any()) + { + currentUser = response.AllUsers.SingleOrDefault(u => u.Name == userLoginName); + } + + var userInfo = new UserInfo(contract, response.UserGroups, response.Contracts, response.AllUserGroups, response.McrSecurityViewId, response.AllContracts, currentUser); + + helpers.LogMethodCompleted(nameof(ContractManager), nameof(GetBaseUserInfo), null, stopwatch); + + return userInfo; + } + + /// + /// Requests the contract details for the company linked to the given event and filters them based on the event start and end times. + /// + /// Event for which the company contacts should be retrieved. + /// Response containing the contracts that are available for the given event. + public ExternalCompanyResponse RequestCompanyContractDetails(Event @event) + { + var contractDetails = RequestCompanyContractDetails(@event.Company); + + if (contractDetails == null) return null; + + // Filter active contracts + if (contractDetails.Contracts != null) + { + contractDetails.Contracts = contractDetails.Contracts.Where(x => x.Name.Equals(@event.Contract) && x.Start < @event.Start && x.End > @event.End).ToArray(); + } + + return contractDetails; + } + + /// + /// Requests the contract details for the given company. + /// + /// Company for which the company contracts should be retrieved. + /// Response containing the contracts for the given company. + public ExternalCompanyResponse RequestCompanyContractDetails(string company) + { + Guid id = Guid.NewGuid(); + ExternalCompanyRequest request = new ExternalCompanyRequest { ID = id.ToString(), Company = company }; + string response = SendRequest(id, request.Serialize()); + + return ExternalCompanyResponse.Deserialize(response); + } + + public ExternalUserResponse RequestUserContractDetails(string userName) + { + Guid id = Guid.NewGuid(); + ExternalUserRequest request = new ExternalUserRequest { ID = id.ToString(), Username = userName }; + string response = SendRequest(id, request.Serialize()); + + ExternalUserResponse contractDetails = ExternalUserResponse.Deserialize(response); + + if (contractDetails == null) return null; + + // Filter applicable contracts + if (contractDetails.Contracts != null) + { + contractDetails.Contracts = contractDetails.Contracts.Where(x => x.Type == ContractType.BaseContract).ToArray(); + } + + return contractDetails; + } + + public bool TryGetOrderTemplate(string templateName, out OrderTemplate template) + { + if (String.IsNullOrWhiteSpace(templateName)) throw new ArgumentException("templateName"); + + template = null; + + var orderTemplatesTable = Element.GetTable(helpers.Engine, 15000); + foreach (object[] orderTemplateRow in orderTemplatesTable.Values) + { + string orderTemplateName = Convert.ToString(orderTemplateRow[1]); + if (templateName == orderTemplateName) + { + string serializedOrderTemplate = Convert.ToString(orderTemplateRow[3]); + template = OrderTemplate.Deserialize(serializedOrderTemplate); + if (template != null) return true; + } + } + + return false; + } + + public List GetOrderTemplates(IEnumerable templateNames) + { + if (templateNames is null) throw new ArgumentNullException(nameof(templateNames)); + if (!templateNames.Any()) return new List(); + + helpers.LogMethodStart(nameof(ContractManager), nameof(GetOrderTemplates), out var stopwatch); + + var templates = new List(); + + var orderTemplatesTable = Element.GetTable(helpers.Engine, 15000); + foreach (var orderTemplateRow in orderTemplatesTable.Values) + { + string orderTemplateName = Convert.ToString(orderTemplateRow[1]); + + if (templateNames.Contains(orderTemplateName)) + { + string serializedOrderTemplate = Convert.ToString(orderTemplateRow[3]); + var template = OrderTemplate.Deserialize(serializedOrderTemplate); + if (template != null) + { + templates.Add(template); + } + } + } + + var notFoundTemplateNames = templateNames.Except(templates.Select(t => t.Name)); + + Log(nameof(GetOrderTemplates), $"Could not find order templates '{string.Join(", ", notFoundTemplateNames)}'"); + + helpers.LogMethodCompleted(nameof(ContractManager), nameof(GetOrderTemplates), null, stopwatch); + + return templates; + } + + public bool TryGetOrderTemplate(Guid templateId, out OrderTemplate template) + { + template = null; + + string serializedOrderTemplate = Convert.ToString(Element.GetParameterByPrimaryKey(OrderTemplatesTableTemplateColumnPid, templateId.ToString())); + if (string.IsNullOrWhiteSpace(serializedOrderTemplate)) return false; + + template = OrderTemplate.Deserialize(serializedOrderTemplate); + + return template != null; + } + + public bool TryAddOrderTemplate(string templateName, string[] userGroups, Order order, out Guid templateId, bool isTemplateForRecurringOrder = false) + { + if (string.IsNullOrWhiteSpace(templateName)) throw new ArgumentException(nameof(templateName)); + if (userGroups == null) throw new ArgumentNullException(nameof(userGroups)); + if (order == null) throw new ArgumentNullException(nameof(order)); + + var template = OrderTemplate.FromOrder(helpers, order, templateName, isTemplateForRecurringOrder); + templateId = template.Id; + + Guid requestId = Guid.NewGuid(); + ExternalOrderTemplateRequest request = new ExternalOrderTemplateRequest { ID = requestId.ToString(), TemplateId = template.Id.ToString(), OrderTemplateName = templateName, UserGroups = userGroups, Template = template.Serialize(), Action = TemplateAction.Add }; + string response = SendRequest(requestId, request.Serialize(helpers) ?? throw new InvalidOperationException("Failed to serialize request")); + + return !String.IsNullOrWhiteSpace(response) && response.Equals("OK", StringComparison.InvariantCultureIgnoreCase); + } + + public bool TryEditOrderTemplate(Guid templateId, string templateName, string[] userGroups, Order order, bool isPartOfEventTemplate, bool isTemplateForRecurringOrder = false) + { + if (string.IsNullOrWhiteSpace(templateName)) throw new ArgumentException(nameof(templateName)); + if (userGroups == null) throw new ArgumentNullException(nameof(userGroups)); + if (order == null) throw new ArgumentNullException(nameof(order)); + if (templateId == Guid.Empty) throw new ArgumentException(nameof(templateId)); + + var template = OrderTemplate.FromOrder(helpers, order, templateName, isTemplateForRecurringOrder); + template.Id = templateId; // override OrderTemplate ID with existing template ID + template.IsPartOfEventTemplate = isPartOfEventTemplate; + + return TryEditOrderTemplate(template, userGroups); + } + + public bool TryEditOrderTemplate(OrderTemplate template, string[] userGroups) + { + if (template == null) throw new ArgumentNullException(nameof(template)); + if (userGroups == null) throw new ArgumentNullException(nameof(userGroups)); + + var requestId = Guid.NewGuid(); + var request = new ExternalOrderTemplateRequest + { + ID = requestId.ToString(), + TemplateId = template.Id.ToString(), + OrderTemplateName = template.Name, + Template = template.Serialize(), + UserGroups = userGroups, + Action = TemplateAction.Edit + }; + + string response = SendRequest(requestId, request.Serialize(helpers) ?? throw new InvalidOperationException("Failed to serialize request")); + + return !string.IsNullOrWhiteSpace(response) && response.Equals("OK", StringComparison.InvariantCultureIgnoreCase); + } + + public bool TryDeleteOrderTemplate(Guid templateId) + { + if (templateId == Guid.Empty) throw new ArgumentException(nameof(templateId)); + + try + { + Guid id = Guid.NewGuid(); + var request = new ExternalOrderTemplateRequest { ID = id.ToString(), TemplateId = templateId.ToString(), Action = TemplateAction.Delete }; + string response = SendRequest(id, request.Serialize(helpers) ?? throw new InvalidOperationException("Failed to serialize request")); + + return !String.IsNullOrWhiteSpace(response) && response.Equals("OK", StringComparison.InvariantCultureIgnoreCase); + } + catch (Exception ex) + { + Log(nameof(TryDeleteOrderTemplate), $"Exception while deleting order template {templateId}: {ex}"); + return false; + } + } + + public bool TryDeleteOrderTemplate(string templateName) + { + if (templateName == null) throw new ArgumentException("templateName"); + + try + { + Guid id = Guid.NewGuid(); + ExternalOrderTemplateRequest request = new ExternalOrderTemplateRequest { ID = id.ToString(), OrderTemplateName = templateName, Action = TemplateAction.Delete }; + string response = SendRequest(id, request.Serialize(helpers) ?? throw new InvalidOperationException("Failed to serialize request")); + + return !String.IsNullOrWhiteSpace(response) && response.Equals("OK", StringComparison.InvariantCultureIgnoreCase); + } + catch (Exception ex) + { + Log(nameof(TryDeleteOrderTemplate), $"Exception while deleting order template {templateName}: {ex}"); + return false; + } + } + + public bool TryGetEventTemplate(string templateName, out EventTemplate template) + { + if (String.IsNullOrWhiteSpace(templateName)) throw new ArgumentException("templateName"); + + Guid id = Guid.NewGuid(); + ExternalEventTemplateRequest request = new ExternalEventTemplateRequest { ID = id.ToString(), EventTemplateName = templateName, Action = TemplateAction.Get }; + string response = SendRequest(id, request.Serialize()); + + template = EventTemplate.Deserialize(response); + return template != null; + } + + public bool TryAddEventTemplate(string templateName, string[] userGroups, Event @event, IEnumerable orders) + { + if (String.IsNullOrWhiteSpace(templateName)) throw new ArgumentException("templateName"); + if (userGroups == null) throw new ArgumentNullException(nameof(userGroups)); + if (@event == null) throw new ArgumentNullException(nameof(@event)); + if (orders == null) throw new ArgumentNullException(nameof(orders)); + + // Generate Event Order Templates + List orderTemplates = new List(); + List> orderTemplateStartTimes = new List>(); + foreach(Order order in orders) + { + string orderTemplateName = DetermineUniqueOrderTemplateName(order.Name); + OrderTemplate orderTemplate = OrderTemplate.FromOrder(helpers, order, orderTemplateName); + orderTemplate.IsPartOfEventTemplate = true; + + orderTemplates.Add(orderTemplate); + + orderTemplateStartTimes.Add(new Tuple(orderTemplate.Id, order.Start.RoundToMinutes())); + } + + if (!CouldTemplatesBeSaved(orderTemplates)) throw new InvalidOperationException($"All linked order templates should be of the same type (vizrem or normal live)"); + + // Generate Event Template + EventTemplate eventTemplate = EventTemplate.FromEvent(@event, orderTemplateStartTimes, templateName); + eventTemplate.EventSubType = orderTemplates.Any(o => o.SubType == OrderSubType.Vizrem) ? EventSubType.Vizrem : EventSubType.Normal; + + // Send request + Guid id = Guid.NewGuid(); + ExternalEventTemplateRequest request = new ExternalEventTemplateRequest + { + ID = id.ToString(), + TemplateId = eventTemplate.Id.ToString(), + EventTemplateName = templateName, + UserGroups = userGroups, + Template = eventTemplate.Serialize(), + OrderTemplates = orderTemplates.Select(o => new EventOrderTemplate { TemplateId = o.Id.ToString(), Name = o.Name, Template = o.Serialize()}).ToArray(), + Action = TemplateAction.Add + }; + + string response = SendRequest(id, request.Serialize()); + return !String.IsNullOrWhiteSpace(response) && response.Equals("OK", StringComparison.InvariantCultureIgnoreCase); + } + + private string DetermineUniqueOrderTemplateName(string name) + { + string templateName = name; + int index = 0; + var allOrderTemplates = GetAllOrderTemplateNamesAndIds().Keys; + while (allOrderTemplates.Contains(templateName)) + { + index++; + templateName = $"{name}_{index}"; + } + + return templateName; + } + + public bool TryEditEventTemplate(Event @event, EventTemplate templateToEdit, string templateName, string[] userGroups, IReadOnlyList linkedOrderTemplatesToKeep, IReadOnlyList newOrderTemplates, Dictionary newOrderTemplateOffsets) + { + ArgumentNullCheck.ThrowIfNull(@event, nameof(@event)); + ArgumentNullCheck.ThrowIfNull(templateToEdit, nameof(templateToEdit)); + ArgumentNullCheck.ThrowIfNull(userGroups, nameof(userGroups)); + ArgumentNullCheck.ThrowIfNull(linkedOrderTemplatesToKeep, nameof(linkedOrderTemplatesToKeep)); + ArgumentNullCheck.ThrowIfNull(newOrderTemplates, nameof(newOrderTemplates)); + ArgumentNullCheck.ThrowIfNull(newOrderTemplateOffsets, nameof(newOrderTemplateOffsets)); + ArgumentNullCheck.ThrowIfNullOrWhiteSpace(templateName, nameof(templateName)); + + var allTemplatesToAddOrUpdate = linkedOrderTemplatesToKeep.Concat(newOrderTemplates).ToList(); + + if (!CouldTemplatesBeSaved(allTemplatesToAddOrUpdate)) throw new InvalidOperationException($"All linked order templates should be of the same type (vizrem or normal live)"); + + List eventOrderTemplates = new List(); + foreach(OrderTemplate orderTemplate in linkedOrderTemplatesToKeep) + { + eventOrderTemplates.Add(new EventOrderTemplate { TemplateId = orderTemplate.Id.ToString(), Name = orderTemplate.Name, Template = orderTemplate.Serialize() }); + } + + // Add new Order Templates + foreach(OrderTemplate orderTemplate in newOrderTemplates) + { + orderTemplate.IsPartOfEventTemplate = true; + eventOrderTemplates.Add(new EventOrderTemplate { TemplateId = orderTemplate.Id.ToString(), Name = orderTemplate.Name, Template = orderTemplate.Serialize() }); + } + + // Generate Event Template + EventTemplate eventTemplate = EventTemplate.FromEvent(@event, new List>(), templateName); + eventTemplate.EventSubType = allTemplatesToAddOrUpdate.Any(o => o.SubType == OrderSubType.Vizrem) ? EventSubType.Vizrem : EventSubType.Normal; + eventTemplate.OrderOffsets = templateToEdit.OrderOffsets; + eventTemplate.Id = templateToEdit.Id; + + // Remove OrderOffsets for Order Templates that will be removed + var existingOrderOffsetGuids = eventTemplate.OrderOffsets.Keys.ToList(); + var orderOffsetGuidsToKeep = linkedOrderTemplatesToKeep.Select(x => x.Id).ToList(); + foreach (Guid orderOffsetGuid in existingOrderOffsetGuids) + { + if (!orderOffsetGuidsToKeep.Contains(orderOffsetGuid)) eventTemplate.OrderOffsets.Remove(orderOffsetGuid); + } + + // Add OrderOffsets for Order Templates that will be added + foreach (var kvp in newOrderTemplateOffsets) + { + eventTemplate.OrderOffsets.Add(kvp.Key, kvp.Value); + } + + // Send request + Guid requestId = Guid.NewGuid(); + ExternalEventTemplateRequest request = new ExternalEventTemplateRequest + { + ID = requestId.ToString(), + TemplateId = eventTemplate.Id.ToString(), + EventTemplateName = templateName, + UserGroups = userGroups, + OrderTemplates = eventOrderTemplates.ToArray(), + Action = TemplateAction.Edit, + Template = eventTemplate.Serialize() + }; + + string response = SendRequest(requestId, request.Serialize()); + + return !String.IsNullOrWhiteSpace(response) && response.Equals("OK", StringComparison.InvariantCultureIgnoreCase); + } + + private static bool CouldTemplatesBeSaved(List orderTemplatesToSave) + { + if (orderTemplatesToSave.All(o => o.SubType == OrderSubType.Vizrem)) + { + return true; + } + else if (orderTemplatesToSave.All(o => o.SubType == OrderSubType.Normal)) + { + return true; + } + + return false; + } + + /// + /// This method does not use the Contract Manager requests. + /// It immediately updates the template in the Event Templates table. + /// + /// Eventtemplate to update. + /// True if update was successful. + public bool TryEditEventTemplate(EventTemplate template) + { + if (!GetAllEventTemplates().Contains(template.Name)) return false; + if (!Element.GetTablePrimaryKeys(16000).Contains(template.Id.ToString())) return false; + + try + { + Element.SetParameterByPrimaryKey(EventTemplatesTableTemplateColumnPid, template.Id.ToString(), JsonConvert.SerializeObject(template)); + } + catch (Exception) + { + return false; + } + + return true; + } + + public bool TryDeleteEventTemplate(string templateName) + { + if (templateName == null) throw new ArgumentException("templateName"); + + Guid id = Guid.NewGuid(); + ExternalEventTemplateRequest request = new ExternalEventTemplateRequest { ID = id.ToString(), EventTemplateName = templateName, Action = TemplateAction.Delete }; + string response = SendRequest(id, request.Serialize()); + + return !String.IsNullOrWhiteSpace(response) && response.Equals("OK", StringComparison.InvariantCultureIgnoreCase); + } + + public List GetLinkedOrderTemplates(Guid eventTemplateId) + { + if (eventTemplateId == Guid.Empty) throw new ArgumentException("eventTemplateId"); + + string[] orderTemplateNames = Convert.ToString(Element.GetParameterByPrimaryKey(16003, eventTemplateId.ToString())).Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + var orderTemplatesTable = Element.GetTable(helpers.Engine, 15000); + + List orderTemplates = new List(); + foreach (object[] orderTemplateRow in orderTemplatesTable.Values) + { + string orderTemplateName = Convert.ToString(orderTemplateRow[1]); + if (orderTemplateNames.Contains(orderTemplateName)) + { + string serializedOrderTemplate = Convert.ToString(orderTemplateRow[3]); + OrderTemplate orderTemplate = OrderTemplate.Deserialize(serializedOrderTemplate); + if (orderTemplate != null) orderTemplates.Add(orderTemplate); + } + } + + return orderTemplates; + } + + /// + /// Returns all Companies defined in the Contract Manager element. + /// + /// All Companies from the Companies table in the Contract Manager Element. + public string[] GetAllCompanies() + { + return Element.GetTablePrimaryKeys(1000); + } + + /// + /// Returns all Companies defined in the Contract Manager element together with their security view id. + /// + /// All Companies from the Companies table in the Contract Manager Element with their security view id. + public Dictionary GetAllCompanySecurityViewIds() + { + object[] companyTableColumns = Element.GetColumns(1000, new int[] { CompaniesTableKeyIndex, CompaniesTableSecurityViewIdIndex }); + object[] primaryKeyColumn = (object[])companyTableColumns[0]; + object[] securityViewIdColumn = (object[])companyTableColumns[1]; + + Dictionary allCompanies = new Dictionary(); /* Key = Company Name, Value = Security View Id */ + for (int i = 0; i < primaryKeyColumn.Length; i++) + { + string primaryKey = Convert.ToString(primaryKeyColumn[i]); + if (!allCompanies.ContainsKey(primaryKey)) + { + allCompanies.Add(primaryKey, Convert.ToInt16(securityViewIdColumn[i])); + } + } + + return allCompanies; + } + + /// + /// Returns all Order Templates defined in the Contract Manager element. + /// + /// The names of all saved Order Templates. + public Dictionary GetAllOrderTemplateNamesAndIds() + { + var names = Element.GetTableDisplayKeys(15000); + var ids = Element.GetTablePrimaryKeys(15000); + + return names.ToDictionary(name => name, name => ids[Array.FindIndex(names, n => n == name)]); + } + + /// + /// Returns all Event Templates defined in the Contract Manager element. + /// + /// The names of all saved Event Templates. + public string[] GetAllEventTemplates() + { + return Element.GetTableDisplayKeys(16000); + } + + /// + /// Returns all of the user groups known to the Contract Manager element. + /// + /// The names of all use groups known in the Contract Manager element. + public string[] GetAllUserGroups() + { + return Element.GetTableDisplayKeys(3000); + } + + private UserInfo GetUserInfoForUser(string userLoginName, Event @event = null) + { + ExternalResponse response = RequestUserContractDetails(userLoginName); + + if (response == null) throw new InvalidContractResponseException(); + if (response.UserGroups == null || !response.UserGroups.Any()) throw new NoUserGroupsException(userLoginName); + if (response.Contracts == null || !response.Contracts.Any()) throw new NoContractsException(userLoginName); + + Contract contract; + + var userCompanies = response.Contracts.Select(c => c.Company).ToList(); + + if (@event != null && userCompanies.Contains(@event.Company)) + { + // If current user is part of the selected company in the event, use the contract defined in the event + contract = response.Contracts.FirstOrDefault(c => c.Name == @event.Contract) ?? throw new ContractNotFoundException(@event.Contract, @event); + } + else + { + // if Event is null or user is not part of the selected company in the event, use the user company base contract + contract = response.Contracts.FirstOrDefault(c => c.Type == ContractType.BaseContract) ?? throw new ContractNotFoundException(ContractType.BaseContract); + } + + User currentUser = null; + if (response.AllUsers != null && response.AllUsers.Any()) + { + currentUser = response.AllUsers.SingleOrDefault(u => u.Name == userLoginName); + } + + return new UserInfo(contract, response.UserGroups, response.Contracts, response.AllUserGroups, response.McrSecurityViewId, response.AllContracts, currentUser); + } + + private UserInfo GetUserInfoForCompany(Event @event) + { + if (@event == null) throw new ArgumentNullException(nameof(@event)); + + ExternalResponse response = RequestCompanyContractDetails(@event); + + if (response == null) throw new InvalidContractResponseException(); + if (response.UserGroups == null || !response.UserGroups.Any()) throw new NoUserGroupsException(@event.Company); + if (response.Contracts == null || !response.Contracts.Any()) throw new NoContractsException(@event.Company); + + var contract = response.Contracts.FirstOrDefault(c => c.Name == @event.Contract) ?? throw new ContractNotFoundException(@event.Contract); + + return new UserInfo(contract, response.UserGroups, response.Contracts, response.AllUserGroups, response.McrSecurityViewId, response.AllContracts); + } + + private string SendRequest(Guid id, string request) + { + if (string.IsNullOrWhiteSpace(request)) throw new ArgumentException($"'{nameof(request)}' cannot be null or whitespace.", nameof(request)); + + return ElementAPI.SendRequestAndGetResponse(helpers, Element, externalRequestParameterId, externalRequestTableParameterId, externalRequestTableStatusParameterId, externalRequestTableResponseParameterId, externalRequestTableRemoveEntryParameterId, id, request, 5, 20); + } + + /// + /// Gets the ContractManager element that this class instance interacts with. + /// + public Element Element { get; private set; } + + private void Log(string nameOfMethod, string message) + { + helpers.Log(nameof(ContractManager), nameOfMethod, message); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/Enums.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/Enums.cs new file mode 100644 index 0000000..39010f2 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/Enums.cs @@ -0,0 +1,56 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + public enum ContractStatus + { + Closed = 0, + + Open = 1 + } + + public enum ContractType + { + Other = 0, + + BaseContract = 1 + } + + public enum SimultaneousServices + { + Unlimited = 0, + + One = 1, + + Two = 2, + + Three = 3, + + Four = 4, + + Five = 5, + + Six = 6, + + Seven = 7, + + Eight = 8, + + Nine = 9, + + Ten = 10 + } + + public enum SignalSourceType + { + Main, + + Backup + } + + public enum TemplateAction + { + Add = 0, + Edit = 1, + Delete = 2, + Get = 3 + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalCompanyRequest.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalCompanyRequest.cs new file mode 100644 index 0000000..b39dbd2 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalCompanyRequest.cs @@ -0,0 +1,37 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + + using Newtonsoft.Json; + + public class ExternalCompanyRequest + { + public string ID { get; set; } + + public string Company { get; set; } + + public static ExternalCompanyRequest Deserialize(string serializedRequest) + { + try + { + return JsonConvert.DeserializeObject(serializedRequest); + } + catch (Exception) + { + return null; + } + } + + public string Serialize() + { + try + { + return JsonConvert.SerializeObject(this, Formatting.None); + } + catch (Exception) + { + return null; + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalCompanyResponse.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalCompanyResponse.cs new file mode 100644 index 0000000..4f05224 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalCompanyResponse.cs @@ -0,0 +1,41 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + + using Newtonsoft.Json; + + public class ExternalCompanyResponse : ExternalResponse + { + /// + /// Company for which the contract information was requested. + /// + public string Company { get; set; } + + /// + /// Gets or sets the ID of the View associated with this company. + /// + public int SecurityViewId { get; set; } + + /// + /// Contains the companies that should be able to get visibility rights to the items of this company. + /// + public Company[] LinkedCompanies { get; set; } + + public static ExternalCompanyResponse Deserialize(string serializedRequest) + { + try + { + return JsonConvert.DeserializeObject(serializedRequest); + } + catch (Exception) + { + return null; + } + } + + public override string ToString() + { + return "ExternalCompanyResponse: " + JsonConvert.SerializeObject(this, Formatting.None); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalEventTemplateRequest.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalEventTemplateRequest.cs new file mode 100644 index 0000000..aff6d71 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalEventTemplateRequest.cs @@ -0,0 +1,83 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using Newtonsoft.Json; + using System; + + public class ExternalEventTemplateRequest + { + /// + /// Id of the request + /// + [JsonProperty(Required = Required.Always)] + public string ID { get; set; } + + public string TemplateId { get; set; } + + /// + /// required when adding, editing or retrieving an Event Template + /// + [JsonProperty(Required = Required.Always)] // A non-null value is required for successfull parsing in the contract manager. + public string EventTemplateName { get; set; } = "random value for successfull parsing"; + + /// + /// Only required when adding a new Template + /// + public string[] UserGroups { get; set; } + + /// + /// Only required when adding a new template or editing an existing one + /// + public string Template { get; set; } + + /// + /// Always optional + /// + public EventOrderTemplate[] OrderTemplates { get; set; } = new EventOrderTemplate[0]; + + [JsonProperty(Required = Required.Always)] + public TemplateAction Action { get; set; } + + public static ExternalEventTemplateRequest Deserialize(string serializedRequest) + { + try + { + return JsonConvert.DeserializeObject(serializedRequest); + } + catch (Exception) + { + return null; + } + } + + public string Serialize() + { + try + { + return JsonConvert.SerializeObject(this, Formatting.None); + } + catch (Exception) + { + return null; + } + } + } + + public class EventOrderTemplate + { + public EventOrderTemplate() + { + TemplateId = default(string); + Name = default(string); + Template = default(string); + } + + [JsonProperty(Required = Required.Always)] + public string TemplateId { get; set; } + + [JsonProperty(Required = Required.Always)] + public string Name { get; set; } + + [JsonProperty(Required = Required.Always)] + public string Template { get; set; } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalOrderTemplateRequest.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalOrderTemplateRequest.cs new file mode 100644 index 0000000..dca844a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalOrderTemplateRequest.cs @@ -0,0 +1,58 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + using Newtonsoft.Json; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + + public class ExternalOrderTemplateRequest + { + [JsonProperty(Required = Required.Always)] + public string ID { get; set; } + + public string TemplateId { get; set; } + + /// + /// required when adding, editing or retrieving an Order Template + /// + [JsonProperty(Required = Required.Always)] // A non-null value is required for successfull parsing in the contract manager. + public string OrderTemplateName { get; set; } = "random value for successfull parsing"; + + /// + /// Only required when adding a new Template + /// + public string[] UserGroups { get; set; } + + /// + /// Only required when adding a new template or editing an existing one + /// + public string Template { get; set; } + + [JsonProperty(Required = Required.Always)] + public TemplateAction Action { get; set; } + + public static ExternalOrderTemplateRequest Deserialize(string serializedRequest) + { + try + { + return JsonConvert.DeserializeObject(serializedRequest); + } + catch (Exception) + { + return null; + } + } + + public string Serialize(Helpers helpers) + { + try + { + return JsonConvert.SerializeObject(this, Formatting.None); + } + catch (Exception ex) + { + helpers.Log(nameof(ExternalOrderTemplateRequest), nameof(Serialize), $"Exception while serializing: {ex}"); + return null; + } + } + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalResponse.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalResponse.cs new file mode 100644 index 0000000..8dc81a3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalResponse.cs @@ -0,0 +1,58 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + using System.Collections.Generic; + using System.Linq; + + public abstract class ExternalResponse + { + protected ExternalResponse() + { + ID = String.Empty; + UserGroups = new UserGroup[0]; + Contracts = new Contract[0]; + AllUsers = new User[0]; + AllUserGroups = new UserGroup[0]; + } + + /// + /// Unique Id of the response. This matches the Id of the request. + /// + public string ID { get; set; } + + /// + /// All user groups for the requested Company or User. + /// + public UserGroup[] UserGroups { get; set; } + + /// + /// All contracts for the requested Company or User. + /// + public Contract[] Contracts { get; set; } + + /// + /// A list containing all Users from the Contract Manager. Used to send emails when certain triggers trigger. + /// + public User[] AllUsers { get; set; } + + /// + /// A list containing all User Groups from the Contract Manager. Used as dropdown options in Customer UI for MCR user. + /// + public UserGroup[] AllUserGroups { get; set; } + + public Contract[] AllContracts { get; set; } + + /// + /// Gets or sets the ID of the View that is associated with MCR users. + /// + public int McrSecurityViewId { get; set; } + + public IEnumerable AllMcrUsers + { + get + { + return AllUsers.Where(user => AllUserGroups.Any(userGroup => user.UsergroupIds.Contains(userGroup.ID) && userGroup.IsMcr)); + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalUserRequest.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalUserRequest.cs new file mode 100644 index 0000000..c783a4c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalUserRequest.cs @@ -0,0 +1,37 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + + using Newtonsoft.Json; + + public class ExternalUserRequest + { + public string ID { get; set; } + + public string Username { get; set; } + + public static ExternalUserRequest Deserialize(string serializedRequest) + { + try + { + return JsonConvert.DeserializeObject(serializedRequest); + } + catch (Exception) + { + return null; + } + } + + public string Serialize() + { + try + { + return JsonConvert.SerializeObject(this, Formatting.None); + } + catch (Exception) + { + return null; + } + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalUserResponse.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalUserResponse.cs new file mode 100644 index 0000000..96fb4a3 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ExternalUserResponse.cs @@ -0,0 +1,28 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + + using Newtonsoft.Json; + + public class ExternalUserResponse : ExternalResponse + { + public string Username { get; set; } + + public static ExternalUserResponse Deserialize(string serializedRequest) + { + try + { + return JsonConvert.DeserializeObject(serializedRequest); + } + catch (Exception) + { + return null; + } + } + + public override string ToString() + { + return "ExternalUserResponse: " + JsonConvert.SerializeObject(this, Formatting.None); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/IContractManager.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/IContractManager.cs new file mode 100644 index 0000000..3c7fef9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/IContractManager.cs @@ -0,0 +1,22 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Event; + using System.Collections.Generic; + + public interface IContractManager + { + UserInfo GetUserInfo(string userLoginName, Event @event = null); + + UserInfo GetBaseUserInfo(string userLoginName); + + ExternalCompanyResponse RequestCompanyContractDetails(Event @event); + + ExternalCompanyResponse RequestCompanyContractDetails(string company); + + ExternalUserResponse RequestUserContractDetails(string userName); + + string[] GetAllCompanies(); + + Dictionary GetAllCompanySecurityViewIds(); + } +} diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ProfileParameterFilter.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ProfileParameterFilter.cs new file mode 100644 index 0000000..60f5475 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ProfileParameterFilter.cs @@ -0,0 +1,29 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + + public class ProfileParameterFilter + { + public ProfileParameterFilter() + { + ProfileParameterName = String.Empty; + AllowUnfilteredProfileParameterValues = false; + ProfileParameterValueFilters = new ProfileParameterValueFilter[0]; + } + + /// + /// Gets or sets the name of the profile parameter. + /// + public string ProfileParameterName { get; set; } + + /// + /// Gets or sets if all profile parameter values that are not listed in the ProfileParameterValueFilters are fully allowed. + /// + public bool AllowUnfilteredProfileParameterValues { get; set; } + + /// + /// Gets or sets the list of profile parameter values that are allowed for this profile parameter. + /// + public ProfileParameterValueFilter[] ProfileParameterValueFilters { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ProfileParameterValueFilter.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ProfileParameterValueFilter.cs new file mode 100644 index 0000000..da9e94a --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ProfileParameterValueFilter.cs @@ -0,0 +1,23 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + + public class ProfileParameterValueFilter + { + public ProfileParameterValueFilter() + { + Value = String.Empty; + IsMcrOnly = false; + } + + /// + /// Gets or sets the value for this profile parameter. + /// + public string Value { get; set; } + + /// + /// Gets or sets if this profile parameter value is only allowed for MCR users. + /// + public bool IsMcrOnly { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ServiceFilter.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ServiceFilter.cs new file mode 100644 index 0000000..9c36d2c --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/ServiceFilter.cs @@ -0,0 +1,41 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + + public class ServiceFilter + { + public ServiceFilter() + { + ServiceDefinitionName = String.Empty; + SimultaneousServices = SimultaneousServices.Unlimited; + IsPartOfFixedPrice = true; + AllowUnfilteredProfileParameters = false; + ProfileParameterFilters = new ProfileParameterFilter[0]; + } + + /// + /// Gets or sets the name of the service definition. + /// + public string ServiceDefinitionName { get; set; } + + /// + /// Gets or sets how many simultaneous services can be created using this service definition. + /// + public SimultaneousServices SimultaneousServices { get; set; } + + /// + /// Gets or sets if this service is part of a fixed price. + /// + public bool IsPartOfFixedPrice { get; set; } + + /// + /// Gets or sets if all profile parameters that are not listed in the ProfileParameterFilters are fully allowed. + /// + public bool AllowUnfilteredProfileParameters { get; set; } + + /// + /// Gets or sets the list of profile parameters that are allowed for this service with additional filters on specific values. + /// + public ProfileParameterFilter[] ProfileParameterFilters { get; set; } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/User.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/User.cs new file mode 100644 index 0000000..9925d59 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/User.cs @@ -0,0 +1,54 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using System; + + [Flags] + public enum Notifications : uint + { + None = 0, + LiveOrderConfirmationByOperatorNotificationRequired = 1, + LiveOrderRejectionByOperatorNotificationRequired = 2, + LiveOrderCompletionByDataminerNotificationRequired = 4, + LiveOrderCompletionWithErrorsByDataminerNotificationRequired = 8, + LiveOrderCancellationByOperatorNotificationRequired = 16, + LiveOrderCancellationByCustomerNotificationRequired = 32, + LiveOrderCancellationByIntegrationNotificationRequired = 64, + LiveOrderServicesBookedNotificationRequired = 128, + LiveOrderServicesBookedByIntegrationNotificationRequired = 256, + NonLiveOrderReassignedByOperatorNotificationRequired = 512, + NonLiveOrderRejectedByOperatorNotificationRequired = 1024, + NonLiveOrderCompletedByDataMinerNotificationRequired = 2048, + NonLiveOrderCancellationByOperatorNotificationRequired = 4096, + NonLiveOrderWorkInProgressByDataMinerNotificationRequired = 8192, + NonLiveOrderEditedByDataMinerNotificationRequired = 16384, + NonLiveOrderCreationByDataMinerNotificationRequired = 32768, + NonLiveOrderIplayFolderCreationByOperatorNotificationRequired = 65536, + UnableToBookRecurringVizremOrder = 131072, + } + + public class User + { + public string ID { get; set; } + + public string Name { get; set; } + + public string Email { get; set; } + + public string Phone { get; set; } + + public string[] UsergroupIds { get; set; } + + public Notifications Notifications { get; set; } + + public override bool Equals(object obj) + { + if (!(obj is User other)) return false; + return ID == other.ID; + } + + public override int GetHashCode() + { + return ID.GetHashCode(); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/UserGroup.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/UserGroup.cs new file mode 100644 index 0000000..80981f5 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/UserGroup.cs @@ -0,0 +1,58 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using Newtonsoft.Json; + + public class UserGroup + { + public UserGroup() + { + ID = default(string); + Name = default(string); + Company = default(string); + CompanySecurityViewId = default(int); + IsSport = default(bool); + IsNews = default(bool); + IsMcr = default(bool); + CanConfigureTemplate = default(bool); + OrderTemplates = new string[0]; + EventTemplates = new string[0]; + LinkedCompanies = new Company[0]; + } + + public string ID { get; set; } + + public string Name { get; set; } + + public string Company { get; set; } + + /// + /// Gets or sets the ID of the view associated with the company to which this User Group belongs. + /// 0 if the User Group is not linked to a Company. + /// + public int CompanySecurityViewId { get; set; } + + /// + /// Gets or sets the list of companies that are linked to the company of this contract. + /// + public Company[] LinkedCompanies { get; set; } + + public bool IsSport { get; set; } + + public bool IsNews { get; set; } + + public bool IsMcr { get; set; } + + public bool CanSwapResources { get; set; } + + public bool CanConfigureTemplate { get; set; } + + public string[] OrderTemplates { get; set; } + + public string[] EventTemplates { get; set; } + + public override string ToString() + { + return JsonConvert.SerializeObject(this, Formatting.None); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/UserInfo.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/UserInfo.cs new file mode 100644 index 0000000..3822ab9 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Contracts/UserInfo.cs @@ -0,0 +1,195 @@ +using Newtonsoft.Json; + +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts +{ + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UserTasks; + using System.Collections.Generic; + using System.Linq; + + public class UserInfo + { + public UserInfo() + { + + } + + public UserInfo(Contract contract, UserGroup[] userGroups, Contract[] allUserContracts, UserGroup[] allUserGroups, int mcrViewId, Contract[] allContracts, User user = null) + { + Contract = contract; + AllUserContracts = allUserContracts ?? new Contract[0]; + UserGroups = userGroups ?? new UserGroup[0]; + AllUserGroups = allUserGroups ?? new UserGroup[0]; + McrSecurityViewId = mcrViewId; + AllContracts = allContracts ?? new Contract[0]; + User = user; + } + + /// + /// Contains the specific contract selected in the event or the base contract in case not event has been created. + /// + public Contract Contract { get; private set; } + + /// + /// Contains all contracts for this user. + /// + public Contract[] AllUserContracts { get; set; } = new Contract[0]; + + /// + /// Contains the user groups this user is part of. + /// + public UserGroup[] UserGroups { get; private set; } = new UserGroup[0]; + + /// + /// Contains all user groups on the DMS. + /// + public UserGroup[] AllUserGroups { get; private set; } = new UserGroup[0]; + + /// + /// Contains all contracts on the DMS. + /// + public Contract[] AllContracts { get; set; } = new Contract[0]; + + /// + /// Contains the user that is currently retrieving the userinfo. + /// + public User User { get; set; } + + /// + /// Gets or sets the ID of the View that is associated with MCR users. + /// + public int McrSecurityViewId { get; set; } + + public bool IsMcrUser + { + get + { + return UserGroups != null && UserGroups.Any(x => x.IsMcr); + } + } + + public bool CanSwapResources + { + get + { + return IsMcrUser || (UserGroups != null && UserGroups.Any(x => x.CanSwapResources)); + } + } + + public bool IsSportUser + { + get + { + return UserGroups != null && UserGroups.Any(x => x.IsSport); + } + } + + public bool IsNewsUser + { + get + { + return UserGroups != null && UserGroups.Any(x => x.IsNews); + } + } + + public bool IsInternalUser + { + get + { + return UserGroups != null && UserGroups.Any(x => x.Company.Equals("YLE")); + } + } + + public bool CanConfigureTemplate + { + get + { + return UserGroups != null && UserGroups.Any(x => x.CanConfigureTemplate); + } + } + + public string[] GetOrderTemplates() + { + if (UserGroups == null) + { + return new string[0]; + } + else + { + HashSet distinctTemplateNames = new HashSet(); + foreach (var usergroup in UserGroups) + { + foreach (string templateName in usergroup.OrderTemplates) + { + distinctTemplateNames.Add(templateName); + } + } + + return distinctTemplateNames.ToArray(); + } + } + + public string[] GetEventTemplates() + { + if (UserGroups == null) + { + return new string[0]; + } + else + { + HashSet distinctTemplateNames = new HashSet(); + foreach (var usergroup in UserGroups) + { + foreach (string templateName in usergroup.EventTemplates) + { + distinctTemplateNames.Add(templateName); + } + } + + return distinctTemplateNames.ToArray(); + } + } + + /// + /// Contains the companies this user is part of. + /// + [JsonIgnore] + public IEnumerable AllUserCompanies + { + get + { + if (UserGroups == null) return new List(); + + List allUserCompanies = new List(); + foreach (var userGroup in UserGroups) + { + if (userGroup != null && !string.IsNullOrWhiteSpace(userGroup.Company) && !userGroup.Company.Equals("-1")) allUserCompanies.Add(userGroup.Company); + } + + return allUserCompanies; + } + } + + [JsonIgnore] + public IEnumerable AllCompanies + { + get + { + return AllUserGroups.Select(x => x.Company); + } + } + + [JsonIgnore] + public bool CanPromoteToSharedSource + { + get + { + return AllUserContracts.Any(x => x != null && x.ContractGlobalEventLevelReceptionConfiguration.HasFlag(GlobalEventLevelReceptionConfigurations.PromoteGlobalEventLevelReceptionAllowed)); + } + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this, Formatting.None); + } + } +} \ No newline at end of file diff --git a/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Controllers/EurovisionController.cs b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Controllers/EurovisionController.cs new file mode 100644 index 0000000..9332349 --- /dev/null +++ b/DMApp.AutomationTests/TestFiles/Solutions/HugeSolution/Library_1/Controllers/EurovisionController.cs @@ -0,0 +1,787 @@ +namespace Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Controllers +{ + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Utilities; + using System; + using System.Collections.Generic; + using System.Text; + using Skyline.DataMiner.Automation; + using Service = Service.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Contracts; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Service; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Order; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Eurovision; + using System.Linq; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Integrations.Eurovision; + using Newtonsoft.Json; + using Type = Integrations.Eurovision.Type; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.UI.Service.Eurovision; + using Skyline.DataMiner.DeveloperCommunityLibrary.YLE.Exceptions; + using Newtonsoft.Json.Bson; + + public class EurovisionController + { + private readonly Helpers helpers; + private readonly DisplayedService service; + private readonly EurovisionSection section; + private readonly NormalOrderSection orderSection; + + private IActionableElement ebuElement; + + public EurovisionController(Helpers helpers, Service service, EurovisionSection section, NormalOrderSection orderSection) + { + this.helpers = helpers ?? throw new ArgumentNullException(nameof(helpers)); + this.service = service as DisplayedService ?? throw new ArgumentNullException(nameof(service)); + this.section = section ?? throw new ArgumentNullException(nameof(section)); + this.orderSection = orderSection ?? throw new ArgumentNullException(nameof(orderSection)); + + helpers.Log(nameof(EurovisionController), nameof(EurovisionController), $"Booking Details: {JsonConvert.SerializeObject(service.EurovisionBookingDetails, Formatting.Indented)}"); + + SubscribeToUi(); + InitializeValues(); + } + + public event EventHandler BookEurovisionService; + + public event EventHandler ServiceTimingChanged; + + private void SubscribeToUi() + { + orderSection.GeneralInfoSection.UserGroupChanged += (s, e) => UpdateEurovisionElement(e); + + section.TypeChanged += (o, e) => + { + service.EurovisionBookingDetails.Type = e; + BookingDetails_TypeChanged(e); + }; + + section.BookButtonClicked += (o, e) => BookEurovisionService?.Invoke(this, new EventArgs()); + + section.SynopsisIdChanged += (o, e) => service.EurovisionTransmissionNumber = e; + + SubscribeToNewsEventSection(); + SubscribeToProgramEventSection(); + SubscribeToSatelliteCapacitySection(); + SubscribeToOssTransmissionSection(); + SubscribeToUnilateralTransmissionSection(); + } + + private void SubscribeToNewsEventSection() + { + // Eurovision News Event events - General + section.NewsEventSection.EventChanged += (s, e) => NewsEvent_EventChanged(e); + section.NewsEventSection.DestinationOrganizationChanged += (s, e) => service.EurovisionBookingDetails.DestinationOrganizationCode = e?.Code ?? String.Empty; + section.NewsEventSection.DestinationCityChanged += (s, e) => service.EurovisionBookingDetails.DestinationCityCode = e?.Code ?? String.Empty; + section.NewsEventSection.FeedpointChanged += (s, e) => OriginFeedpointChanged(e); + section.NewsEventSection.FacilityChanged += (s, e) => service.EurovisionBookingDetails.FacilityProductId = e?.ProductId ?? String.Empty; + section.NewsEventSection.ContactChanged += (s, e) => service.EurovisionBookingDetails.Contact = e; + section.NewsEventSection.DescriptionChanged += (s, e) => service.EurovisionBookingDetails.Description = e; + section.NewsEventSection.NoteChanged += (s, e) => service.EurovisionBookingDetails.Note = e; + section.NewsEventSection.ContractChanged += (s, e) => service.EurovisionBookingDetails.ContractCode = e?.Code ?? String.Empty; + + // Eurovision News Event events - Video Section + SubscribeToVideoSection(section.NewsEventSection.VideoSection); + + // Eurovision News Event events - Audio Section + SubscribeToAudioSection(section.NewsEventSection.AudioSection); + } + + private void SubscribeToProgramEventSection() + { + section.ProgramEventSection.EventChanged += (s, e) => ProgramEvent_EventChanged(e); + section.ProgramEventSection.DestinationOrganizationChanged += (s, e) => service.EurovisionBookingDetails.DestinationOrganizationCode = e?.Code ?? String.Empty; + section.ProgramEventSection.DestinationCityChanged += (s, e) => service.EurovisionBookingDetails.DestinationCityCode = e?.Code ?? String.Empty; + section.ProgramEventSection.ParticipationChanged += (s, e) => ProgramEvent_ParticipationChanged(e); + section.ProgramEventSection.ContactChanged += (s, e) => service.EurovisionBookingDetails.Contact = e; + section.ProgramEventSection.NoteChanged += (s, e) => service.EurovisionBookingDetails.Note = e; + section.ProgramEventSection.ContractChanged += (s, e) => service.EurovisionBookingDetails.ContractCode = e?.Code ?? String.Empty; + } + + private void SubscribeToSatelliteCapacitySection() + { + // Eurovision Satellite Capacity events - General + section.SatelliteCapacitySection.SatelliteChanged += (s, e) => SatelliteCapacity_SatelliteChanged(e); + section.SatelliteCapacitySection.UplinkChanged += (s, e) => SatelliteCapacity_UplinkChanged(e); + section.SatelliteCapacitySection.OriginChanged += (s, e) => OriginOrganizationChanged(e); + section.SatelliteCapacitySection.OriginCityChanged += (s, e) => OriginFeedpointChanged(e); + section.SatelliteCapacitySection.ContractChanged += (s, e) => service.EurovisionBookingDetails.ContractCode = e?.Code ?? String.Empty; + section.SatelliteCapacitySection.NoteChanged += (s, e) => service.EurovisionBookingDetails.Note = e.Value; + section.SatelliteCapacitySection.LineUpChanged += (s, e) => service.EurovisionBookingDetails.LineUp = e.Value; + section.SatelliteCapacitySection.ContactFirstNameChanged += (s, e) => + { + service.EurovisionBookingDetails.ContactFirstName = e.Value; + service.EurovisionBookingDetails.Contact = $"{e.Value} {service.EurovisionBookingDetails.ContactLastName}"; + }; + + section.SatelliteCapacitySection.ContactLastNameChanged += (s, e) => + { + service.EurovisionBookingDetails.ContactLastName = e.Value; + service.EurovisionBookingDetails.Contact = $"{service.EurovisionBookingDetails.ContactFirstName} {e.Value}"; + }; + + section.SatelliteCapacitySection.EmailChanged += (s, e) => service.EurovisionBookingDetails.Email = e.Value; + section.SatelliteCapacitySection.PhoneChanged += (s, e) => service.EurovisionBookingDetails.Phone = e.Value; + + // Eurovision News Event events - Video Section + SubscribeToVideoSection(section.SatelliteCapacitySection.VideoSection); + + // Eurovision News Event events - Audio Section + SubscribeToAudioSection(section.SatelliteCapacitySection.AudioSection); + } + + private void SubscribeToOssTransmissionSection() + { + // Eurovision OSS Transmission events - General + section.OssTransmissionSection.OriginOrganizationChanged += (s, e) => OriginOrganizationChanged(e); + section.OssTransmissionSection.OriginCityChanged += (s, e) => OriginFeedpointChanged(e); + section.OssTransmissionSection.FacilityChanged += (s, e) => service.EurovisionBookingDetails.FacilityProductId = e?.ProductId ?? String.Empty; + section.OssTransmissionSection.DestinationOrganizationChanged += (s, e) => DestinationOrganizationChanged(e); + section.OssTransmissionSection.DestinationCityChanged += (s, e) => DestinationCityChanged(e); + section.OssTransmissionSection.ContactChanged += (s, e) => service.EurovisionBookingDetails.Contact = e; + section.OssTransmissionSection.ContractChanged += (s, e) => service.EurovisionBookingDetails.ContractCode = e?.Code ?? String.Empty; + section.OssTransmissionSection.NoteChanged += (s, e) => service.EurovisionBookingDetails.Note = e; + + // Eurovision OSS Transmission events - Video Section + SubscribeToVideoSection(section.OssTransmissionSection.VideoSection); + + // Eurovision OSS Transmission events - Audio Section + SubscribeToAudioSection(section.OssTransmissionSection.AudioSection); + } + + private void SubscribeToUnilateralTransmissionSection() + { + // Eurovision Unilateral Transmission events - General + section.UnilateralTransmissionSection.OriginOrganizationChanged += (s, e) => OriginOrganizationChanged(e); + section.UnilateralTransmissionSection.OriginCityChanged += (s, e) => OriginFeedpointChanged(e); + section.UnilateralTransmissionSection.DestinationOrganizationChanged += (s, e) => DestinationOrganizationChanged(e); + section.UnilateralTransmissionSection.DestinationCityChanged += (s, e) => DestinationCityChanged(e); + section.UnilateralTransmissionSection.ContactChanged += (s, e) => service.EurovisionBookingDetails.Contact = e; + section.UnilateralTransmissionSection.ContractChanged += (s, e) => service.EurovisionBookingDetails.ContractCode = e?.Code ?? String.Empty; + section.UnilateralTransmissionSection.NoteChanged += (s, e) => service.EurovisionBookingDetails.Note = e; + + // Eurovision Unilateral Transmission events - Video Section + SubscribeToVideoSection(section.UnilateralTransmissionSection.VideoSection); + + // Eurovision Unilateral Transmission events - Audio Section + SubscribeToAudioSection(section.UnilateralTransmissionSection.AudioSection); + } + + private void SubscribeToVideoSection(VideoSection videoSection) + { + videoSection.VideoDefinitionChanged += (s, e) => VideoDefinitionChanged(e); + videoSection.VideoResolutionChanged += (s, e) => service.EurovisionBookingDetails.VideoResolutionCode = e?.Code ?? String.Empty; + videoSection.VideoAspectRatioChanged += (s, e) => service.EurovisionBookingDetails.VideoAspectRatioCode = e?.Code ?? String.Empty; + videoSection.VideoBitrateChanged += (s, e) => service.EurovisionBookingDetails.VideoBitrateCode = e?.Code ?? String.Empty; + videoSection.VideoFrameRateChanged += (s, e) => service.EurovisionBookingDetails.VideoFrameRateCode = e?.Code ?? String.Empty; + videoSection.VideoBandwidthChanged += (s, e) => service.EurovisionBookingDetails.VideoBandwidthCode = e?.Code ?? String.Empty; + } + + private void SubscribeToAudioSection(AudioSection audioSection) + { + SubscribeToAudioPair1(audioSection); + SubscribeToAudioPair2(audioSection); + SubscribeToAudioPair3(audioSection); + SubscribeToAudioPair4(audioSection); + } + + private void SubscribeToAudioPair1(AudioSection audioSection) + { + audioSection.AudioChannel1Changed += (s, e) => + { + service.EurovisionBookingDetails.AudioChannel1.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + if (audioSection.AreAudioChannels1And2Stereo) service.EurovisionBookingDetails.AudioChannel2.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + }; + + audioSection.AudioChannel1OtherTextChanged += (s, e) => + { + service.EurovisionBookingDetails.AudioChannel1.AudioChannelOtherText = e; + if (audioSection.AreAudioChannels1And2Stereo) service.EurovisionBookingDetails.AudioChannel2.AudioChannelOtherText = e; + }; + + audioSection.AudioChannel2Changed += (s, e) => service.EurovisionBookingDetails.AudioChannel2.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + + audioSection.AudioChannel2OtherTextChanged += (s, e) => service.EurovisionBookingDetails.AudioChannel2.AudioChannelOtherText = e; + + audioSection.IsAudioChannel1And2StereoChanged += (s, e) => + { + if (!e) return; + service.EurovisionBookingDetails.AudioChannel2.AudioChannelCode = service.EurovisionBookingDetails.AudioChannel1.AudioChannelCode; + service.EurovisionBookingDetails.AudioChannel2.AudioChannelOtherText = service.EurovisionBookingDetails.AudioChannel1.AudioChannelOtherText; + }; + } + + private void SubscribeToAudioPair2(AudioSection audioSection) + { + audioSection.AudioChannel3Changed += (s, e) => + { + service.EurovisionBookingDetails.AudioChannel3.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + if (audioSection.AreAudioChannels3And4Stereo) service.EurovisionBookingDetails.AudioChannel4.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + }; + + audioSection.AudioChannel3OtherTextChanged += (s, e) => + { + service.EurovisionBookingDetails.AudioChannel3.AudioChannelOtherText = e; + if (audioSection.AreAudioChannels3And4Stereo) service.EurovisionBookingDetails.AudioChannel4.AudioChannelOtherText = e; + }; + + audioSection.AudioChannel4Changed += (s, e) => service.EurovisionBookingDetails.AudioChannel4.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + + audioSection.AudioChannel4OtherTextChanged += (s, e) => service.EurovisionBookingDetails.AudioChannel4.AudioChannelOtherText = e; + + audioSection.IsAudioChannel3And4StereoChanged += (s, e) => + { + if (!e) return; + service.EurovisionBookingDetails.AudioChannel4.AudioChannelCode = service.EurovisionBookingDetails.AudioChannel3.AudioChannelCode; + service.EurovisionBookingDetails.AudioChannel4.AudioChannelOtherText = service.EurovisionBookingDetails.AudioChannel3.AudioChannelOtherText; + }; + } + + private void SubscribeToAudioPair3(AudioSection audioSection) + { + audioSection.AudioChannel5Changed += (s, e) => + { + service.EurovisionBookingDetails.AudioChannel5.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + if (audioSection.AreAudioChannels5And6Stereo) service.EurovisionBookingDetails.AudioChannel6.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + }; + + audioSection.AudioChannel5OtherTextChanged += (s, e) => + { + service.EurovisionBookingDetails.AudioChannel5.AudioChannelOtherText = e; + if (audioSection.AreAudioChannels5And6Stereo) service.EurovisionBookingDetails.AudioChannel6.AudioChannelOtherText = e; + }; + + audioSection.AudioChannel6Changed += (s, e) => service.EurovisionBookingDetails.AudioChannel6.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + + audioSection.AudioChannel6OtherTextChanged += (s, e) => service.EurovisionBookingDetails.AudioChannel6.AudioChannelOtherText = e; + + audioSection.IsAudioChannel5And6StereoChanged += (s, e) => + { + if (!e) return; + service.EurovisionBookingDetails.AudioChannel6.AudioChannelCode = service.EurovisionBookingDetails.AudioChannel5.AudioChannelCode; + service.EurovisionBookingDetails.AudioChannel6.AudioChannelOtherText = service.EurovisionBookingDetails.AudioChannel5.AudioChannelOtherText; + }; + } + + private void SubscribeToAudioPair4(AudioSection audioSection) + { + audioSection.AudioChannel7Changed += (s, e) => + { + service.EurovisionBookingDetails.AudioChannel7.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + if (audioSection.AreAudioChannels7And8Stereo) service.EurovisionBookingDetails.AudioChannel8.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + }; + + audioSection.AudioChannel7OtherTextChanged += (s, e) => + { + service.EurovisionBookingDetails.AudioChannel7.AudioChannelOtherText = e; + if (audioSection.AreAudioChannels7And8Stereo) service.EurovisionBookingDetails.AudioChannel8.AudioChannelOtherText = e; + }; + + audioSection.AudioChannel8Changed += (s, e) => service.EurovisionBookingDetails.AudioChannel8.AudioChannelCode = e?.Code ?? AudioChannel.DefaultCode; + + audioSection.AudioChannel8OtherTextChanged += (s, e) => service.EurovisionBookingDetails.AudioChannel8.AudioChannelOtherText = e; + + audioSection.IsAudioChannel7And8StereoChanged += (s, e) => + { + if (!e) return; + service.EurovisionBookingDetails.AudioChannel8.AudioChannelCode = service.EurovisionBookingDetails.AudioChannel7.AudioChannelCode; + service.EurovisionBookingDetails.AudioChannel8.AudioChannelOtherText = service.EurovisionBookingDetails.AudioChannel7.AudioChannelOtherText; + }; + } + + private void InitializeValues() + { + UpdateEurovisionElement(orderSection.GeneralInfoSection.UserGroup); + } + + private void UpdateEurovisionElement(string userGroup) + { + helpers.Log(nameof(EurovisionController), nameof(UpdateEurovisionElement), $"Retrieving EBU element for UserGroup {userGroup}"); + + string ebuElementName = helpers.OrderManagerElement.GetEurovisionElementName(userGroup); + ebuElement = String.IsNullOrWhiteSpace(ebuElementName) ? null : helpers.Engine.FindElement(ebuElementName); + + helpers.Log(nameof(EurovisionController), nameof(UpdateEurovisionElement), $"Retrieved element: {ebuElement?.Name}"); + + if (ebuElement == null) + { + service.EurovisionBookingDetails.Contracts = new List(); + service.EurovisionBookingDetails.Events = new List(); + service.EurovisionBookingDetails.Organizations = new List(); + service.EurovisionBookingDetails.Cities = new List(); + service.EurovisionBookingDetails.Audios = new List