thygesteffensen / PowerAutomateMockUp

Skeleton to run Power Automate Flows from their JSON descriptions.
MIT License
7 stars 1 forks source link

Add scope relevant storage to store stuff like this, which cannot interfere with... #22

Closed github-actions[bot] closed 3 years ago

github-actions[bot] commented 3 years ago

Add scope relevant storage to store stuff like this, which cannot interfere with the state.

https://github.com/thygesteffensen/PowerAutomateMockUp/blob/a9d1da4826a9f3f0237f46125e03dc1b85e6ab7d/PowerAutomateMockUp/FlowParser/ActionExecutors/Implementations/ForEachActionExecutor.cs#L74

using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Parser.ExpressionParser;

namespace Parser.FlowParser.ActionExecutors.Implementations
{
    public class ForEachActionExecutor : DefaultBaseActionExecutor, IScopeActionExecutor
    {
        private readonly IState _state;
        private readonly IScopeDepthManager _scopeDepthManager;
        private readonly ILogger<ForEachActionExecutor> _logger;
        private readonly IExpressionEngine _expressionEngine;

        private JProperty[] _actionDescriptions;
        private string _firstScopeActionName;

        private List<ValueContainer> _items;

        public ForEachActionExecutor(
            IState state,
            IScopeDepthManager scopeDepthManager,
            ILogger<ForEachActionExecutor> logger,
            IExpressionEngine expressionEngine)
        {
            _state = state ?? throw new ArgumentNullException(nameof(state));
            _scopeDepthManager = scopeDepthManager ?? throw new ArgumentNullException(nameof(scopeDepthManager));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _expressionEngine = expressionEngine ?? throw new ArgumentNullException(nameof(expressionEngine));

            _items = new List<ValueContainer>();
        }

        public override Task<ActionResult> Execute()
        {
            _logger.LogInformation("Entered foreach...");

            if (Json == null)
            {
                throw new PowerAutomateMockUpException($"Json cannot be null - cannot execute {ActionName}.");
            }

            var runOn = (Json.SelectToken("$..foreach") ??
                         throw new InvalidOperationException("Json must contain foreach token.")).Value<string>();
            var values = _expressionEngine.ParseToValueContainer(runOn);

            if (values.Type() != ValueContainer.ValueType.Array)
                return Task.FromResult(new ActionResult
                {
                    // TODO: Figure out what happens when you apply for each on non array values
                    ActionStatus = ActionStatus.Failed
                });

            SetupForEach(values);

            UpdateScopeAndSetItemValue();

            return Task.FromResult(new ActionResult {NextAction = _firstScopeActionName});
        }

        private void SetupForEach(ValueContainer values)
        {
            var scopeActionDescriptions = (Json.SelectToken("$.actions") ??
                                           throw new InvalidOperationException("Json must contain actions token."))
                .OfType<JProperty>();
            _actionDescriptions = scopeActionDescriptions as JProperty[] ?? scopeActionDescriptions.ToArray();
            _firstScopeActionName = _actionDescriptions.First(ad =>
                !(ad.Value.SelectToken("$.runAfter") ??
                  throw new InvalidOperationException("Json must contain runAfter token.")).Any()).Name;

            // TODO: Add scope relevant storage to store stuff like this, which cannot interfere with the state.
            _items = values.GetValue<IEnumerable<ValueContainer>>().ToList();
        }

        private void UpdateScopeAndSetItemValue()
        {
            _scopeDepthManager.Push(ActionName, _actionDescriptions, this);

            _state.AddOutputs($"item_{ActionName}", _items.First());
            _items = _items.Skip(1).ToList();
        }

        public Task<ActionResult> ExitScope(ActionStatus scopeStatus)
        {
            if (_items.Count > 0)
            {
                _logger.LogInformation("Continuing foreach.");

                UpdateScopeAndSetItemValue();

                return Task.FromResult(new ActionResult {NextAction = _firstScopeActionName});
            }
            else
            {
                _logger.LogInformation("Exited foreach...");
                return Task.FromResult(new ActionResult());
            }
        }
    }
}
 No newline at end of file
ndex cb6075b..5b0329a 100644
++ b/PowerAutomateMockUp/FlowParser/ActionExecutors/Implementations/ScopeActionExecutor.cs

db7b0f694d564305a5908c63d833eafce55f31e0

thygesteffensen commented 3 years ago

:tada: This issue has been resolved in version 1.0.0-alpha.29 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

thygesteffensen commented 3 years ago

:tada: This issue has been resolved in version 1.0.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket: