diff --git a/src/Moryx/Workflows/Implementation/Workplan.cs b/src/Moryx/Workflows/Implementation/Workplan.cs index 15aa6650c..a95699a76 100644 --- a/src/Moryx/Workflows/Implementation/Workplan.cs +++ b/src/Moryx/Workflows/Implementation/Workplan.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Runtime.Serialization; - +using System.Linq; +using System.ComponentModel; + namespace Moryx.Workplans { /// @@ -92,5 +94,99 @@ public static Workplan Restore(List connectors, List { return new Workplan(connectors, steps); } - } + + /// + /// Compare two workplans + /// + /// + /// + public override bool Equals(object obj) + { + + if (!(obj is Workplan)) + { + return false; + } + Workplan newPlan = (Workplan)obj; + + var start = this.Connectors.First(x => x.Name.Equals("Start")); + var end = this.Connectors.First(x => x.Name.Equals("End")); + var failed = this.Connectors.First(x => x.Name.Equals("Failed")); + + var newStart = newPlan.Connectors.First(x => x.Name.Equals("Start")); + var newEnd = newPlan.Connectors.First(x => x.Name.Equals("End")); + var newFailed = newPlan.Connectors.First(x => x.Name.Equals("Failed")); + + var step = this.Steps.First(x => x.Inputs.Any(y => y.Equals(start))); + var newStep = newPlan.Steps.First(x => x.Inputs.Any(y => y.Equals(newStart))); + + List needToCheck = new List(); + List newNeedToCheck = new List(); + + List check = new List(); + + needToCheck.Add(step); + newNeedToCheck.Add(newStep); + + while (needToCheck.Count != 0 && newNeedToCheck.Count != 0) + { + + + for (int a = 0; a < step.Outputs.Length; a++) + { + + var connector = step.Outputs[a]; + var newConnector = newStep.Outputs[a]; + + bool isNotEndConnector = (connector != end && newConnector != newEnd); + bool isNotFailedConnector = (connector != failed && newConnector != newFailed); + + if (isNotEndConnector && isNotFailedConnector) + { + var follower = this.Steps.FirstOrDefault(x => x.Inputs.Any(y => y.Equals(connector))); + var newFollower = newPlan.Steps.FirstOrDefault(x => x.Inputs.Any(y => y.Equals(newConnector))); + + bool isAlreadyChecked = (check.Contains(follower) || check.Contains(newFollower)); + + if (!(isAlreadyChecked)) + { + needToCheck.Add(follower); + newNeedToCheck.Add(newFollower); + } + } + else if (connector.Classification != newConnector.Classification) + { + return false; + } + } + + + + bool isSameStep = (step.GetType() == newStep.GetType()); + if (isSameStep) + { + needToCheck.Remove(step); + newNeedToCheck.Remove(newStep); + + check.Add(step); + + if (needToCheck.Count != 0 && newNeedToCheck.Count != 0) + { + step = needToCheck[0]; + newStep = newNeedToCheck[0]; + } + } + else + { + return false; + } + } + + return true; + } + + + + } } + diff --git a/src/Tests/Moryx.Tests/Moryx.Tests.csproj b/src/Tests/Moryx.Tests/Moryx.Tests.csproj index 1ff29d6a4..d7ba8634a 100644 --- a/src/Tests/Moryx.Tests/Moryx.Tests.csproj +++ b/src/Tests/Moryx.Tests/Moryx.Tests.csproj @@ -14,6 +14,7 @@ + diff --git a/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingActivity.cs b/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingActivity.cs new file mode 100644 index 000000000..2c0f056dc --- /dev/null +++ b/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingActivity.cs @@ -0,0 +1,34 @@ +using Moryx.AbstractionLayer; +using Moryx.AbstractionLayer.Capabilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Moryx.Tests.Workplans.Dummies +{ + [ActivityResults(typeof(DefaultActivityResult))] + public class AssemblingActivity : Activity + { + + + public override ProcessRequirement ProcessRequirement => ProcessRequirement.NotRequired; + + public override ICapabilities RequiredCapabilities => new AssemblingCapabilities(); + + protected override ActivityResult CreateResult(long resultNumber) + { + return ActivityResult.Create((DefaultActivityResult)resultNumber); + } + + protected override ActivityResult CreateFailureResult() + { + return ActivityResult.Create(DefaultActivityResult.Failed); + } + + + + + } +} diff --git a/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingCapabilities.cs b/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingCapabilities.cs new file mode 100644 index 000000000..9127e8f0d --- /dev/null +++ b/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingCapabilities.cs @@ -0,0 +1,23 @@ +using Moryx.AbstractionLayer.Capabilities; + +namespace Moryx.Tests.Workplans.Dummies +{ + + public class AssemblingCapabilities : CapabilitiesBase + { + public int Value { get; set; } + + protected override bool ProvidedBy(ICapabilities provided) + { + var providedAssembling = provided as AssemblingCapabilities; + if (providedAssembling == null) + return false; + + if (providedAssembling.Value < Value) // Provided must be greater or equal + return false; + + return true; + } + } + +} \ No newline at end of file diff --git a/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingParameters.cs b/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingParameters.cs new file mode 100644 index 000000000..18738be1f --- /dev/null +++ b/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingParameters.cs @@ -0,0 +1,17 @@ +using Moryx.AbstractionLayer; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Moryx.Tests.Workplans.Dummies +{ + public class AssemblingParameters : Parameters + { + protected override void Populate(IProcess process, Parameters instance) + { + + } + } +} diff --git a/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingTask.cs b/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingTask.cs new file mode 100644 index 000000000..68acdaf26 --- /dev/null +++ b/src/Tests/Moryx.Tests/Workplans/Dummies/AssemblingTask.cs @@ -0,0 +1,16 @@ +using Moryx.AbstractionLayer; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace Moryx.Tests.Workplans.Dummies +{ + [Display(Name = "Assembling Task", Description = "Task which does something with a product")] + public class AssemblingTask : TaskStep + { + } +} diff --git a/src/Tests/Moryx.Tests/Workplans/Dummies/ColorizingTask.cs b/src/Tests/Moryx.Tests/Workplans/Dummies/ColorizingTask.cs new file mode 100644 index 000000000..3bd3cf207 --- /dev/null +++ b/src/Tests/Moryx.Tests/Workplans/Dummies/ColorizingTask.cs @@ -0,0 +1,16 @@ +using Moryx.AbstractionLayer; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace Moryx.Tests.Workplans.Dummies +{ + [Display(Name = "PackagingTask", Description = "Task which does something with a product")] + public class ColorizingTask : TaskStep + { + } +} \ No newline at end of file diff --git a/src/Tests/Moryx.Tests/Workplans/Dummies/PackagingTask.cs b/src/Tests/Moryx.Tests/Workplans/Dummies/PackagingTask.cs new file mode 100644 index 000000000..19f6ff315 --- /dev/null +++ b/src/Tests/Moryx.Tests/Workplans/Dummies/PackagingTask.cs @@ -0,0 +1,16 @@ +using Moryx.AbstractionLayer; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace Moryx.Tests.Workplans.Dummies +{ + [Display(Name = "PackagingTask", Description = "Task which does something with a product")] + public class PackagingTask : TaskStep + { + } +} diff --git a/src/Tests/Moryx.Tests/Workplans/EqualTest.cs b/src/Tests/Moryx.Tests/Workplans/EqualTest.cs new file mode 100644 index 000000000..621b55572 --- /dev/null +++ b/src/Tests/Moryx.Tests/Workplans/EqualTest.cs @@ -0,0 +1,127 @@ +using Moryx.Workplans; +using Moryx.AbstractionLayer; +using NUnit.Framework; +using Moryx.Tests.Workplans.Dummies; + +namespace Moryx.Tests.Workplans +{ + + [TestFixture] + public class EqualTest + { + private Workplan firstWorkplan; + private Workplan secondWorkplan; + private Workplan thirdWorkplan; + private Workplan fourthWorkplan; + private Workplan fifthWorkplan; + private Workplan sixthWorkplan; + + public Workplan CreateFirstWorkplan() + { + var plan = new Workplan(); + + var start = plan.AddConnector("Start", NodeClassification.Start); + var end = plan.AddConnector("End", NodeClassification.End); + var failed = plan.AddConnector("Failed", NodeClassification.Failed); + + var input = start; + var outputA = plan.AddConnector("A"); + var outputB = plan.AddConnector("B"); + + plan.AddStep(new AssemblingTask(), new AssemblingParameters(), input, outputA, outputB, failed); + + input = outputA; + plan.AddStep(new PackagingTask(), new AssemblingParameters(), input, end, end, failed); + + input = outputB; + plan.AddStep(new ColorizingTask(), new AssemblingParameters(), input, end, failed, failed); + return plan; + } + + public Workplan CreateSecondWorkplan() + { + var plan = new Workplan(); + + var start = plan.AddConnector("Start", NodeClassification.Start); + var end = plan.AddConnector("End", NodeClassification.End); + var failed = plan.AddConnector("Failed", NodeClassification.Failed); + + var input = start; + var outptuA = input; + var outputB = plan.AddConnector("A"); + + plan.AddStep(new AssemblingTask(), new AssemblingParameters(), input, outptuA, outputB, failed); + + input = outputB; + plan.AddStep(new PackagingTask(), new AssemblingParameters(), input, outputB, end, failed); + + return plan; + } + + public Workplan CreateThirdWorkplan() + { + var plan = new Workplan(); + + var start = plan.AddConnector("Start", NodeClassification.Start); + var end = plan.AddConnector("End", NodeClassification.End); + var failed = plan.AddConnector("Failed", NodeClassification.Failed); + + var outputA = plan.AddConnector("A"); + var outputB = plan.AddConnector("B"); + + plan.AddStep(new AssemblingTask(), new AssemblingParameters(), start, outputA, outputB, failed); + + var input = outputA; + + plan.AddStep(new PackagingTask(), new AssemblingParameters(), input, start, end, failed); + + input = outputB; + + plan.AddStep(new ColorizingTask(), new AssemblingParameters(), input, outputA, end, failed); + + return plan; + } + + [SetUp] + public void SetUp() + { + firstWorkplan = CreateFirstWorkplan(); + secondWorkplan = CreateFirstWorkplan(); + + thirdWorkplan = CreateSecondWorkplan(); + fourthWorkplan = CreateSecondWorkplan(); + + fifthWorkplan = CreateThirdWorkplan(); + sixthWorkplan = CreateThirdWorkplan(); + } + + [Test] + public void TestEqualWorkplans() + { + bool result = firstWorkplan.Equals(secondWorkplan); + Assert.That(result, Is.True); + } + + [Test] + public void TestEqualWorkplansSimpleLoop() + { + bool result = thirdWorkplan.Equals(fourthWorkplan); + Assert.That(result, Is.True); + } + + [Test] + public void TestEqualWorkplansDoubleLoop() + { + bool result = fifthWorkplan.Equals(sixthWorkplan); + Assert.That(result, Is.True); + } + + [Test] + public void TestUnequalWorkplans() + { + bool r = thirdWorkplan.Equals(fifthWorkplan); + Assert.That(r, Is.False); + } + } + +}