using System.Collections.Generic; using System.Dynamic; using System.Threading; using System.Threading.Tasks; using Elsa.Models; using Elsa.Scripting.Liquid.Helpers; using Elsa.Scripting.Liquid.Messages; using Elsa.Services.Models; using Fluid; using Fluid.Values; using MediatR; using Newtonsoft.Json.Linq; namespace Elsa.Scripting.Liquid.Handlers { public class ConfigureLiquidEngine : INotificationHandler { public Task Handle(EvaluatingLiquidExpression notification, CancellationToken cancellationToken) { var context = notification.TemplateContext; var options = context.Options; options.MemberAccessStrategy.Register(); options.MemberAccessStrategy.Register(); options.MemberAccessStrategy.Register(o => FluidValue.Create(o.Value, options)); options.MemberAccessStrategy.Register(); options.MemberAccessStrategy.Register((x, name) => x.GetValueAsync(name)); options.MemberAccessStrategy.Register("Input", x => ToFluidValue(x.Input, options)); options.MemberAccessStrategy.Register("CorrelationId", x => ToFluidValue(x.CorrelationId, options)); options.MemberAccessStrategy.Register("Variables", x => new LiquidPropertyAccessor(name => ToFluidValue(x.WorkflowExecutionContext.GetMergedVariables(), name, options))); options.MemberAccessStrategy.Register("Activities", x => new LiquidPropertyAccessor(name => ToFluidValue(GetActivityModelAsync(x, name), options)!)); options.MemberAccessStrategy.Register("Output", GetActivityOutput); options.MemberAccessStrategy.Register, object>((x, name) => x.GetValueAsync(name)); options.MemberAccessStrategy.Register((x, name) => ((IDictionary) x)[name]); options.MemberAccessStrategy.Register((source, name) => source[name]); return Task.CompletedTask; } private Task ToFluidValue(object? input, TemplateOptions options) => Task.FromResult(FluidValue.Create(input, options)); private Task ToFluidValue(Variables dictionary, string key, TemplateOptions options) => Task.FromResult(!dictionary.Has(key) ? default : FluidValue.Create(dictionary.Get(key), options)); private LiquidActivityModel GetActivityModelAsync(ActivityExecutionContext context, string name) => new(context, name); private Task GetActivityOutput(LiquidActivityModel activityModel) { var output = activityModel.ActivityExecutionContext.GetOutputFrom(activityModel.ActivityName); return Task.FromResult(output); } } }