From 5703584ea2b19994c9bcccd5f8d67c7524276c1f Mon Sep 17 00:00:00 2001 From: MariusVuscanNx <96233009+MariusVuscanNx@users.noreply.github.com> Date: Thu, 25 May 2023 23:55:17 +0300 Subject: [PATCH] Added modes to the switch activities (#4067) --- .../Flowchart/Activities/FlowSwitch.cs | 30 ++++++++++++++----- .../Elsa.Workflows.Core/Activities/Switch.cs | 29 ++++++++++++++---- .../Elsa.Workflows.Core/Models/SwitchMode.cs | 15 ++++++++++ 3 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 src/modules/Elsa.Workflows.Core/Models/SwitchMode.cs diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowSwitch.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowSwitch.cs index 2c7cc628e..85b16d486 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowSwitch.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowSwitch.cs @@ -1,5 +1,3 @@ -using System.Runtime.CompilerServices; -using System.Text.Json.Serialization; using Elsa.Expressions; using Elsa.Expressions.Contracts; using Elsa.Expressions.Models; @@ -9,6 +7,8 @@ using Elsa.Workflows.Core.Activities.Flowchart.Models; using Elsa.Workflows.Core.Attributes; using Elsa.Workflows.Core.Models; using JetBrains.Annotations; +using System.Runtime.CompilerServices; +using System.Text.Json.Serialization; namespace Elsa.Workflows.Core.Activities.Flowchart.Activities; @@ -33,17 +33,29 @@ public class FlowSwitch : Activity [Input(UIHint = "flow-switch-editor")] public ICollection Cases { get; set; } = new List(); + /// + /// The switch mode determines whether the first match should be scheduled, or all matches. + /// + [Input(Description = "The switch mode determines whether the first match should be scheduled, or all matches.")] + public Input Mode { get; set; } = new(SwitchMode.MatchFirst); + /// protected override async ValueTask ExecuteAsync(ActivityExecutionContext context) { - var matchingCase = await FindMatchingCaseAsync(context.ExpressionExecutionContext); - var outcome = matchingCase?.Label ?? "Default"; + var matchingCases = await FindMatchingCasesAsync(context.ExpressionExecutionContext); + var hasAnyMatches = matchingCases.Any(); - await context.CompleteActivityAsync(new Outcomes(outcome)); + var mode = context.Get(Mode); + var results = mode == SwitchMode.MatchFirst ? hasAnyMatches ? new[] { matchingCases.First() } : Array.Empty() : matchingCases.ToArray(); + + var outcomes = hasAnyMatches ? results.Select(r => r.Label).ToArray() : new[] { "Default" }; + + await context.CompleteActivityAsync(new Outcomes(outcomes)); } - private async Task FindMatchingCaseAsync(ExpressionExecutionContext context) + private async Task> FindMatchingCasesAsync(ExpressionExecutionContext context) { + var matchingCases = new List(); var expressionEvaluator = context.GetRequiredService(); foreach (var switchCase in Cases) @@ -51,10 +63,12 @@ public class FlowSwitch : Activity var result = await expressionEvaluator.EvaluateAsync(switchCase.Condition, context); if (result == true) - return switchCase; + { + matchingCases.Add(switchCase); + } } - return null; + return matchingCases; } } diff --git a/src/modules/Elsa.Workflows.Core/Activities/Switch.cs b/src/modules/Elsa.Workflows.Core/Activities/Switch.cs index 0fde014f2..f776f814f 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Switch.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Switch.cs @@ -50,6 +50,12 @@ public class Switch : Activity )] public ICollection Cases { get; set; } = new List(); + /// + /// The switch mode determines whether the first match should be scheduled, or all matches. + /// + [Input(Description = "The switch mode determines whether the first match should be scheduled, or all matches.")] + public Input Mode { get; set; } = new(SwitchMode.MatchFirst); + /// /// The default activity to schedule when no case matches. /// @@ -59,19 +65,28 @@ public class Switch : Activity protected override async ValueTask ExecuteAsync(ActivityExecutionContext context) { context.Set(Output, Expression); - var matchingCase = await FindMatchingCaseAsync(context.ExpressionExecutionContext); + var matchingCases = await FindMatchingCasesAsync(context.ExpressionExecutionContext); + var hasAnyMatches = matchingCases.Any(); - if (matchingCase != null) + var mode = context.Get(Mode); + var results = mode == SwitchMode.MatchFirst ? hasAnyMatches ? new[] { matchingCases.First() } : Array.Empty() : matchingCases.ToArray(); + + if (hasAnyMatches) { - await context.ScheduleActivityAsync(matchingCase.Activity, OnChildActivityCompletedAsync); + foreach (var result in results) + { + await context.ScheduleActivityAsync(result.Activity, OnChildActivityCompletedAsync); + } + return; } await context.ScheduleActivityAsync(Default, OnChildActivityCompletedAsync); } - private async Task FindMatchingCaseAsync(ExpressionExecutionContext context) + private async Task> FindMatchingCasesAsync(ExpressionExecutionContext context) { + var matchingCases = new List(); var expressionEvaluator = context.GetRequiredService(); foreach (var switchCase in Cases) @@ -79,10 +94,12 @@ public class Switch : Activity var result = await expressionEvaluator.EvaluateAsync(switchCase.Condition, context); if (result == true) - return switchCase; + { + matchingCases.Add(switchCase); + } } - return null; + return matchingCases; } private async ValueTask OnChildActivityCompletedAsync(ActivityExecutionContext context, ActivityExecutionContext childContext) diff --git a/src/modules/Elsa.Workflows.Core/Models/SwitchMode.cs b/src/modules/Elsa.Workflows.Core/Models/SwitchMode.cs new file mode 100644 index 000000000..f25aa3cf9 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Models/SwitchMode.cs @@ -0,0 +1,15 @@ +namespace Elsa.Workflows.Core.Models +{ + public enum SwitchMode + { + /// + /// Yields the outcome of the first condition evaluating to true. + /// + MatchFirst, + + /// + /// Yields the outcome of all conditions evaluating to true. + /// + MatchAny + } +}