Make consistent singlar/plural names of instances to avoid downstream… (#193)
* Make consistent singlar/plural names of instances to avoid downstream ambiguous reference issues * Reverted ReSettings pluralization * conventional progress * Overhaul to simplify, cleanup, deprecate pr * Update README.md * Reverted RuleActions * Cleanup * Cleanup * Cleanup * Cleanup * Deprecate RuleAction to plural * Reverted some name changes per @abbasc52 * Clarity + VS.NET 2019 compilation fix * Camelcase fixes * Reverted Id properties * Documentation updates Co-authored-by: Alex Reich <Alex_Reich@mechanicsbank.com> Co-authored-by: Alex Reich <alex@alexreich.com> Co-authored-by: Abbas Cyclewala <abcy@microsoft.com>pull/208/head
parent
fe38ed5c9f
commit
34f77ed2ec
|
@ -24,12 +24,12 @@ Breaking Change:
|
|||
- Enabled localParams support for nested Rules
|
||||
- Made certain fields in Rule model optional allowing users to define workflow with minimal fields
|
||||
- Added option to disable Rule in workflow json
|
||||
- Added `GetAllRegisteredWorkflow` to RulesEngine to return all registeredWorkflows
|
||||
- Added `GetAllRegisteredWorkflow` to RulesEngine to return all registered workflows
|
||||
- Runtime errors for expressions will now be logged as errorMessage instead of throwing Exceptions by default
|
||||
- Fixed RuleParameter passed as null
|
||||
|
||||
## [3.0.2]
|
||||
- Fixed LocalParams cache not getting cleaned up when RemoveWorkflow and ClearWorkflows are called
|
||||
- Fixed LocalParams cache not getting cleaned up when RemoveWorkflows and ClearWorkflows are called
|
||||
|
||||
## [3.0.1]
|
||||
- Moved ActionResult and ActionRuleResult under RulesEngine.Models namespace
|
||||
|
|
16
README.md
16
README.md
|
@ -45,9 +45,9 @@ An example rule could be -
|
|||
|
||||
You can inject the rules into the Rules Engine by initiating an instance by using the following code -
|
||||
```c#
|
||||
var rulesEngine = new RulesEngine(workflowRules, logger);
|
||||
var rulesEngine = new RulesEngine(workflow, logger);
|
||||
```
|
||||
Here, *workflowRules* is a list of deserialized object based out of the schema explained above and *logger* is a custom logger instance made out of an [ILogger](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#logger) instance.
|
||||
Here, *workflow* is a list of deserialized object based out of the schema explained above and *logger* is a custom logger instance made out of an [ILogger](https://github.com/microsoft/RulesEngine/wiki/Getting-Started#logger) instance.
|
||||
|
||||
Once done, the Rules Engine needs to execute the rules for a given input. It can be done by calling the method ExecuteAllRulesAsync as shown below -
|
||||
```c#
|
||||
|
@ -73,21 +73,21 @@ rule.SuccessEvent = "Count is within tolerance.";
|
|||
rule.ErrorMessage = "Over expected.";
|
||||
rule.Expression = "count < 3";
|
||||
rule.RuleExpressionType = RuleExpressionType.LambdaExpression;
|
||||
|
||||
rules.Add(rule);
|
||||
|
||||
workflowRule.Rules = rules;
|
||||
Workflow workflow = new Workflow();
|
||||
workflow.WorkflowName = "Example Workflow";
|
||||
workflow.Rules = rules;
|
||||
workflow.Add(workflowRule);
|
||||
|
||||
workFlowRules.Add(workflowRule);
|
||||
|
||||
var bre = new RulesEngine.RulesEngine(workFlowRules.ToArray(), null);
|
||||
var bre = new RulesEngine.RulesEngine(workflow.ToArray(), null);
|
||||
```
|
||||
|
||||
|
||||
### Entity Framework
|
||||
Consuming Entity Framework and populating the Rules Engine is shown in the [EFDemo class](https://github.com/microsoft/RulesEngine/blob/main/demo/DemoApp/EFDemo.cs) with Workflow rules populating the array and passed to the Rules Engine, The Demo App includes an example [RulesEngineDemoContext](https://github.com/microsoft/RulesEngine/blob/main/demo/DemoApp.EFDataExample/RulesEngineDemoContext.cs) using SQLite and could be swapped out for another provider.
|
||||
```c#
|
||||
var wfr = db.WorkflowRules.Include(i => i.Rules).ThenInclude(i => i.Rules).ToArray();
|
||||
var wfr = db.Workflows.Include(i => i.Rules).ThenInclude(i => i.Rules).ToArray();
|
||||
var bre = new RulesEngine.RulesEngine(wfr, null);
|
||||
```
|
||||
*Note: For each level of nested rules expected, a ThenInclude query appended will be needed as shown above.*
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace RulesEngineBenchmark
|
|||
{
|
||||
private readonly RulesEngine.RulesEngine rulesEngine;
|
||||
private readonly object ruleInput;
|
||||
private readonly List<WorkflowRules> workflows;
|
||||
private readonly List<Workflow> workflow;
|
||||
|
||||
private class ListItem
|
||||
{
|
||||
|
@ -34,9 +34,9 @@ namespace RulesEngineBenchmark
|
|||
}
|
||||
|
||||
var fileData = File.ReadAllText(files[0]);
|
||||
workflows = JsonConvert.DeserializeObject<List<WorkflowRules>>(fileData);
|
||||
workflow = JsonConvert.DeserializeObject<List<Workflow>>(fileData);
|
||||
|
||||
rulesEngine = new RulesEngine.RulesEngine(workflows.ToArray(), null, new ReSettings {
|
||||
rulesEngine = new RulesEngine.RulesEngine(workflow.ToArray(), null, new ReSettings {
|
||||
EnableFormattedErrorMessage = false,
|
||||
EnableScopedParams = false
|
||||
});
|
||||
|
@ -69,7 +69,7 @@ namespace RulesEngineBenchmark
|
|||
[Benchmark]
|
||||
public void RuleExecutionDefault()
|
||||
{
|
||||
foreach (var workflow in workflows)
|
||||
foreach (var workflow in workflow)
|
||||
{
|
||||
_ = rulesEngine.ExecuteAllRulesAsync(workflow.WorkflowName, ruleInput).Result;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RulesEngine.Models;
|
||||
|
||||
namespace RulesEngine.Data
|
||||
{
|
||||
public class RulesEngineContext : DbContext
|
||||
{
|
||||
public DbSet<Workflow> Workflows { get; set; }
|
||||
|
||||
public DbSet<Rule> Rules { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<ScopedParam>()
|
||||
.HasKey(k => k.Name);
|
||||
|
||||
modelBuilder.Entity<Workflow>(entity => {
|
||||
entity.HasKey(k => k.WorkflowName);
|
||||
entity.Ignore(b => b.WorkflowRulesToInject);
|
||||
entity.Ignore(b => b.WorkflowsToInject);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Rule>(entity => {
|
||||
entity.HasKey(k => k.RuleName);
|
||||
|
||||
entity.Property(b => b.Properties)
|
||||
.HasConversion(
|
||||
v => JsonSerializer.Serialize(v, null),
|
||||
v => JsonSerializer.Deserialize<Dictionary<string, object>>(v, null));
|
||||
|
||||
entity.Property(p => p.Actions)
|
||||
.HasConversion(
|
||||
v => JsonSerializer.Serialize(v, null),
|
||||
v => JsonSerializer.Deserialize<RuleActions>(v, null));
|
||||
|
||||
entity.Ignore(b => b.WorkflowRulesToInject);
|
||||
entity.Ignore(b => b.WorkflowsToInject);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -2,19 +2,13 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RulesEngine.Data;
|
||||
using RulesEngine.Models;
|
||||
|
||||
namespace DemoApp.EFDataExample
|
||||
{
|
||||
public class RulesEngineDemoContext : DbContext
|
||||
public class RulesEngineDemoContext : RulesEngineContext
|
||||
{
|
||||
public DbSet<WorkflowRules> WorkflowRules { get; set; }
|
||||
public DbSet<ActionInfo> ActionInfos { get; set; }
|
||||
|
||||
public DbSet<RuleActions> RuleActions { get; set; }
|
||||
public DbSet<Rule> Rules { get; set; }
|
||||
public DbSet<ScopedParam> ScopedParams { get; set; }
|
||||
|
||||
public string DbPath { get; private set; }
|
||||
|
||||
public RulesEngineDemoContext()
|
||||
|
@ -26,48 +20,6 @@ namespace DemoApp.EFDataExample
|
|||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||
=> options.UseSqlite($"Data Source={DbPath}");
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<ActionInfo>()
|
||||
.Property(b => b.Context)
|
||||
.HasConversion(
|
||||
v => JsonSerializer.Serialize(v, null),
|
||||
v => JsonSerializer.Deserialize<Dictionary<string, object>>(v, null));
|
||||
|
||||
modelBuilder.Entity<ActionInfo>()
|
||||
.HasKey(k => k.Name);
|
||||
|
||||
modelBuilder.Entity<ScopedParam>()
|
||||
.HasKey(k => k.Name);
|
||||
|
||||
modelBuilder.Entity<WorkflowRules>(entity => {
|
||||
entity.HasKey(k => k.WorkflowName);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RuleActions>(entity => {
|
||||
entity.HasNoKey();
|
||||
entity.HasOne(o => o.OnSuccess).WithMany();
|
||||
entity.HasOne(o => o.OnFailure).WithMany();
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Rule>(entity => {
|
||||
entity.HasKey(k => k.RuleName);
|
||||
|
||||
entity.Property(b => b.Properties)
|
||||
.HasConversion(
|
||||
v => JsonSerializer.Serialize(v, null),
|
||||
v => JsonSerializer.Deserialize<Dictionary<string, object>>(v, null));
|
||||
entity.Ignore(e => e.Actions);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<WorkflowRules>()
|
||||
.Ignore(b => b.WorkflowRulesToInject);
|
||||
|
||||
modelBuilder.Entity<Rule>()
|
||||
.Ignore(b => b.WorkflowRulesToInject);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,13 +1,10 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using RulesEngine.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.IO;
|
||||
using static RulesEngine.Extensions.ListofRuleResultTreeExtension;
|
||||
|
||||
namespace DemoApp
|
||||
|
@ -17,9 +14,9 @@ namespace DemoApp
|
|||
public void Run()
|
||||
{
|
||||
Console.WriteLine($"Running {nameof(BasicDemo)}....");
|
||||
List<WorkflowRules> workFlowRules = new List<WorkflowRules>();
|
||||
WorkflowRules workflowRule = new WorkflowRules();
|
||||
workflowRule.WorkflowName = "Test Workflow Rule 1";
|
||||
List<Workflow> workflows = new List<Workflow>();
|
||||
Workflow workflow = new Workflow();
|
||||
workflow.WorkflowName = "Test Workflow Rule 1";
|
||||
|
||||
List<Rule> rules = new List<Rule>();
|
||||
|
||||
|
@ -32,11 +29,11 @@ namespace DemoApp
|
|||
|
||||
rules.Add(rule);
|
||||
|
||||
workflowRule.Rules = rules;
|
||||
workflow.Rules = rules;
|
||||
|
||||
workFlowRules.Add(workflowRule);
|
||||
workflows.Add(workflow);
|
||||
|
||||
var bre = new RulesEngine.RulesEngine(workFlowRules.ToArray(), null);
|
||||
var bre = new RulesEngine.RulesEngine(workflows.ToArray(), null);
|
||||
|
||||
dynamic datas = new ExpandoObject();
|
||||
datas.count = 1;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<ProjectReference Include="../../src/RulesEngine/RulesEngine.csproj" />
|
||||
<ProjectReference Include="..\DemoApp.EFDataExample\DemoApp.EFDataExample.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -42,16 +42,16 @@ namespace DemoApp
|
|||
throw new Exception("Rules not found.");
|
||||
|
||||
var fileData = File.ReadAllText(files[0]);
|
||||
var workflowRules = JsonConvert.DeserializeObject<List<WorkflowRules>>(fileData);
|
||||
var workflow = JsonConvert.DeserializeObject<List<Workflow>>(fileData);
|
||||
|
||||
RulesEngineDemoContext db = new RulesEngineDemoContext();
|
||||
if (db.Database.EnsureCreated())
|
||||
{
|
||||
db.WorkflowRules.AddRange(workflowRules);
|
||||
db.Workflows.AddRange(workflow);
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
var wfr = db.WorkflowRules.Include(i => i.Rules).ThenInclude(i => i.Rules).ToArray();
|
||||
var wfr = db.Workflows.Include(i => i.Rules).ThenInclude(i => i.Rules).ToArray();
|
||||
|
||||
var bre = new RulesEngine.RulesEngine(wfr, null);
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ namespace DemoApp
|
|||
throw new Exception("Rules not found.");
|
||||
|
||||
var fileData = File.ReadAllText(files[0]);
|
||||
var workflowRules = JsonConvert.DeserializeObject<List<WorkflowRules>>(fileData);
|
||||
var workflow = JsonConvert.DeserializeObject<List<Workflow>>(fileData);
|
||||
|
||||
var bre = new RulesEngine.RulesEngine(workflowRules.ToArray(), null);
|
||||
var bre = new RulesEngine.RulesEngine(workflow.ToArray(), null);
|
||||
|
||||
string discountOffered = "No discount offered.";
|
||||
|
||||
|
|
|
@ -49,10 +49,10 @@ namespace DemoApp
|
|||
}
|
||||
|
||||
var fileData = File.ReadAllText(files[0]);
|
||||
var workflowRules = JsonConvert.DeserializeObject<List<WorkflowRules>>(fileData);
|
||||
var Workflows = JsonConvert.DeserializeObject<List<Workflow>>(fileData);
|
||||
|
||||
var bre = new RulesEngine.RulesEngine(workflowRules.ToArray(), null);
|
||||
foreach (var workflow in workflowRules)
|
||||
var bre = new RulesEngine.RulesEngine(Workflows.ToArray(), null);
|
||||
foreach (var workflow in Workflows)
|
||||
{
|
||||
var resultList = bre.ExecuteAllRulesAsync(workflow.WorkflowName, nestedInput).Result;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace RulesEngine.HelperFunctions
|
|||
public static class Constants
|
||||
{
|
||||
public const string WORKFLOW_NAME_NULL_ERRMSG = "Workflow name can not be null or empty";
|
||||
public const string INJECT_WORKFLOW_RULES_ERRMSG = "Atleast one of Rules or WorkflowRulesToInject must be not empty";
|
||||
public const string INJECT_WORKFLOW_RULES_ERRMSG = "Atleast one of Rules or WorkflowsToInject must be not empty";
|
||||
public const string RULE_CATEGORY_CONFIGURED_ERRMSG = "Rule Category should be configured";
|
||||
public const string RULE_NULL_ERRMSG = "Rules can not be null or zero";
|
||||
public const string NESTED_RULE_NULL_ERRMSG = "Nested rules can not be null";
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace RulesEngine.Interfaces
|
|||
/// <summary>
|
||||
/// Adds new workflows to RulesEngine
|
||||
/// </summary>
|
||||
/// <param name="workflowRules"></param>
|
||||
void AddWorkflow(params WorkflowRules[] workflowRules);
|
||||
/// <param name="workflow"></param>
|
||||
void AddWorkflow(params Workflow[] Workflows);
|
||||
|
||||
/// <summary>
|
||||
/// Removes all registered workflows from RulesEngine
|
||||
|
@ -48,6 +48,6 @@ namespace RulesEngine.Interfaces
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
List<string> GetAllRegisteredWorkflowNames();
|
||||
void AddOrUpdateWorkflow(params WorkflowRules[] workflowRules);
|
||||
void AddOrUpdateWorkflow(params Workflow[] Workflows);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,14 @@ namespace RulesEngine.Models
|
|||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public RuleExpressionType RuleExpressionType { get; set; } = RuleExpressionType.LambdaExpression;
|
||||
public IEnumerable<string> WorkflowRulesToInject { get; set; }
|
||||
|
||||
[Obsolete("WorkflowRulesToInject is deprecated. Use WorkflowsToInject instead.")]
|
||||
public IEnumerable<string> WorkflowRulesToInject {
|
||||
get { return WorkflowsToInject; }
|
||||
set { WorkflowsToInject = value; }
|
||||
}
|
||||
public IEnumerable<string> WorkflowsToInject { get; set; }
|
||||
|
||||
public IEnumerable<Rule> Rules { get; set; }
|
||||
public IEnumerable<ScopedParam> LocalParams { get; set; }
|
||||
public string Expression { get; set; }
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace RulesEngine.Models
|
||||
{
|
||||
[Obsolete("RuleAction class is deprecated. Use RuleActions class instead.")]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class RuleAction : RuleActions
|
||||
{
|
||||
}
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class RuleActions
|
||||
{
|
|
@ -1,25 +1,36 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace RulesEngine.Models
|
||||
{
|
||||
[Obsolete("WorkflowRules class is deprecated. Use Workflow class instead.")]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class WorkflowRules : Workflow {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Workflow rules class for deserialization the json config file
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class WorkflowRules
|
||||
public class Workflow
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the workflow name.
|
||||
/// </summary>
|
||||
public string WorkflowName { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the workflow rules to inject.</summary>
|
||||
/// <value>The workflow rules to inject.</value>
|
||||
public IEnumerable<string> WorkflowRulesToInject { get; set; }
|
||||
/// <summary>Gets or sets the workflow rules to inject.</summary>
|
||||
/// <value>The workflow rules to inject.</value>
|
||||
[Obsolete("WorkflowRulesToInject is deprecated. Use WorkflowsToInject instead.")]
|
||||
public IEnumerable<string> WorkflowRulesToInject {
|
||||
get { return WorkflowsToInject; }
|
||||
set { WorkflowsToInject = value; }
|
||||
}
|
||||
public IEnumerable<string> WorkflowsToInject { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the global params which will be applicable to all rules
|
|
@ -16,20 +16,20 @@ namespace RulesEngine
|
|||
private ConcurrentDictionary<string, (IDictionary<string, RuleFunc<RuleResultTree>>, Int64)> _compileRules = new ConcurrentDictionary<string, (IDictionary<string, RuleFunc<RuleResultTree>>, Int64)>();
|
||||
|
||||
/// <summary>The workflow rules</summary>
|
||||
private ConcurrentDictionary<string, (WorkflowRules, Int64)> _workflowRules = new ConcurrentDictionary<string, (WorkflowRules, Int64)>();
|
||||
private ConcurrentDictionary<string, (Workflow, Int64)> _workflow = new ConcurrentDictionary<string, (Workflow, Int64)>();
|
||||
|
||||
/// <summary>Determines whether [contains workflow rules] [the specified workflow name].</summary>
|
||||
/// <param name="workflowName">Name of the workflow.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [contains workflow rules] [the specified workflow name]; otherwise, <c>false</c>.</returns>
|
||||
public bool ContainsWorkflowRules(string workflowName)
|
||||
public bool ContainsWorkflows(string workflowName)
|
||||
{
|
||||
return _workflowRules.ContainsKey(workflowName);
|
||||
return _workflow.ContainsKey(workflowName);
|
||||
}
|
||||
|
||||
public List<string> GetAllWorkflowNames()
|
||||
{
|
||||
return _workflowRules.Keys.ToList();
|
||||
return _workflow.Keys.ToList();
|
||||
}
|
||||
|
||||
/// <summary>Determines whether [contains compiled rules] [the specified workflow name].</summary>
|
||||
|
@ -44,10 +44,10 @@ namespace RulesEngine
|
|||
/// <summary>Adds the or update workflow rules.</summary>
|
||||
/// <param name="workflowName">Name of the workflow.</param>
|
||||
/// <param name="rules">The rules.</param>
|
||||
public void AddOrUpdateWorkflowRules(string workflowName, WorkflowRules rules)
|
||||
public void AddOrUpdateWorkflows(string workflowName, Workflow rules)
|
||||
{
|
||||
Int64 ticks = DateTime.UtcNow.Ticks;
|
||||
_workflowRules.AddOrUpdate(workflowName, (rules, ticks), (k, v) => (rules, ticks));
|
||||
_workflow.AddOrUpdate(workflowName, (rules, ticks), (k, v) => (rules, ticks));
|
||||
}
|
||||
|
||||
/// <summary>Adds the or update compiled rule.</summary>
|
||||
|
@ -68,9 +68,9 @@ namespace RulesEngine
|
|||
{
|
||||
if (_compileRules.TryGetValue(compiledRuleKey, out (IDictionary<string, RuleFunc<RuleResultTree>> rules, Int64 tick) compiledRulesObj))
|
||||
{
|
||||
if (_workflowRules.TryGetValue(workflowName, out (WorkflowRules rules, Int64 tick) workflowRulesObj))
|
||||
if (_workflow.TryGetValue(workflowName, out (Workflow rules, Int64 tick) WorkflowsObj))
|
||||
{
|
||||
return compiledRulesObj.tick >= workflowRulesObj.tick;
|
||||
return compiledRulesObj.tick >= WorkflowsObj.tick;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,38 +80,38 @@ namespace RulesEngine
|
|||
/// <summary>Clears this instance.</summary>
|
||||
public void Clear()
|
||||
{
|
||||
_workflowRules.Clear();
|
||||
_workflow.Clear();
|
||||
_compileRules.Clear();
|
||||
}
|
||||
|
||||
/// <summary>Gets the work flow rules.</summary>
|
||||
/// <param name="workflowName">Name of the workflow.</param>
|
||||
/// <returns>WorkflowRules.</returns>
|
||||
/// <returns>Workflows.</returns>
|
||||
/// <exception cref="Exception">Could not find injected Workflow: {wfname}</exception>
|
||||
public WorkflowRules GetWorkFlowRules(string workflowName)
|
||||
public Workflow GetWorkflow(string workflowName)
|
||||
{
|
||||
if (_workflowRules.TryGetValue(workflowName, out (WorkflowRules rules, Int64 tick) workflowRulesObj))
|
||||
if (_workflow.TryGetValue(workflowName, out (Workflow rules, Int64 tick) WorkflowsObj))
|
||||
{
|
||||
var workflowRules = workflowRulesObj.rules;
|
||||
if (workflowRules.WorkflowRulesToInject?.Any() == true)
|
||||
var workflow = WorkflowsObj.rules;
|
||||
if (workflow.WorkflowsToInject?.Any() == true)
|
||||
{
|
||||
if (workflowRules.Rules == null)
|
||||
if (workflow.Rules == null)
|
||||
{
|
||||
workflowRules.Rules = new List<Rule>();
|
||||
workflow.Rules = new List<Rule>();
|
||||
}
|
||||
foreach (string wfname in workflowRules.WorkflowRulesToInject)
|
||||
foreach (string wfname in workflow.WorkflowsToInject)
|
||||
{
|
||||
var injectedWorkflow = GetWorkFlowRules(wfname);
|
||||
var injectedWorkflow = GetWorkflow(wfname);
|
||||
if (injectedWorkflow == null)
|
||||
{
|
||||
throw new Exception($"Could not find injected Workflow: {wfname}");
|
||||
}
|
||||
|
||||
workflowRules.Rules.ToList().AddRange(injectedWorkflow.Rules);
|
||||
workflow.Rules.ToList().AddRange(injectedWorkflow.Rules);
|
||||
}
|
||||
}
|
||||
|
||||
return workflowRules;
|
||||
return workflow;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -132,7 +132,7 @@ namespace RulesEngine
|
|||
/// <param name="workflowName">Name of the workflow.</param>
|
||||
public void Remove(string workflowName)
|
||||
{
|
||||
if (_workflowRules.TryRemove(workflowName, out (WorkflowRules, Int64) workflowObj))
|
||||
if (_workflow.TryRemove(workflowName, out (Workflow, Int64) workflowObj))
|
||||
{
|
||||
var compiledKeysToRemove = _compileRules.Keys.Where(key => key.StartsWith(workflowName));
|
||||
foreach (var key in compiledKeysToRemove)
|
||||
|
|
|
@ -39,13 +39,13 @@ namespace RulesEngine
|
|||
#region Constructor
|
||||
public RulesEngine(string[] jsonConfig, ILogger logger = null, ReSettings reSettings = null) : this(logger, reSettings)
|
||||
{
|
||||
var workflowRules = jsonConfig.Select(item => JsonConvert.DeserializeObject<WorkflowRules>(item)).ToArray();
|
||||
AddWorkflow(workflowRules);
|
||||
var workflow = jsonConfig.Select(item => JsonConvert.DeserializeObject<Workflow>(item)).ToArray();
|
||||
AddWorkflow(workflow);
|
||||
}
|
||||
|
||||
public RulesEngine(WorkflowRules[] workflowRules, ILogger logger = null, ReSettings reSettings = null) : this(logger, reSettings)
|
||||
public RulesEngine(Workflow[] Workflows, ILogger logger = null, ReSettings reSettings = null) : this(logger, reSettings)
|
||||
{
|
||||
AddWorkflow(workflowRules);
|
||||
AddWorkflow(Workflows);
|
||||
}
|
||||
|
||||
public RulesEngine(ILogger logger = null, ReSettings reSettings = null)
|
||||
|
@ -157,23 +157,23 @@ namespace RulesEngine
|
|||
/// <summary>
|
||||
/// Adds the workflow if the workflow name is not already added. Ignores the rest.
|
||||
/// </summary>
|
||||
/// <param name="workflowRules">The workflow rules.</param>
|
||||
/// <param name="workflows">The workflow rules.</param>
|
||||
/// <exception cref="RuleValidationException"></exception>
|
||||
public void AddWorkflow(params WorkflowRules[] workflowRules)
|
||||
public void AddWorkflow(params Workflow[] workflows)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var workflowRule in workflowRules)
|
||||
foreach (var workflow in workflows)
|
||||
{
|
||||
var validator = new WorkflowRulesValidator();
|
||||
validator.ValidateAndThrow(workflowRule);
|
||||
if (!_rulesCache.ContainsWorkflowRules(workflowRule.WorkflowName))
|
||||
var validator = new WorkflowsValidator();
|
||||
validator.ValidateAndThrow(workflow);
|
||||
if (!_rulesCache.ContainsWorkflows(workflow.WorkflowName))
|
||||
{
|
||||
_rulesCache.AddOrUpdateWorkflowRules(workflowRule.WorkflowName, workflowRule);
|
||||
_rulesCache.AddOrUpdateWorkflows(workflow.WorkflowName, workflow);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ValidationException($"Cannot add workflow `{workflowRule.WorkflowName}` as it already exists. Use `AddOrUpdateWorkflow` to update existing workflow");
|
||||
throw new ValidationException($"Cannot add workflow `{workflow.WorkflowName}` as it already exists. Use `AddOrUpdateWorkflow` to update existing workflow");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -187,17 +187,17 @@ namespace RulesEngine
|
|||
/// Adds new workflow rules if not previously added.
|
||||
/// Or updates the rules for an existing workflow.
|
||||
/// </summary>
|
||||
/// <param name="workflowRules">The workflow rules.</param>
|
||||
/// <param name="workflows">The workflow rules.</param>
|
||||
/// <exception cref="RuleValidationException"></exception>
|
||||
public void AddOrUpdateWorkflow(params WorkflowRules[] workflowRules)
|
||||
public void AddOrUpdateWorkflow(params Workflow[] workflows)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var workflowRule in workflowRules)
|
||||
foreach (var workflow in workflows)
|
||||
{
|
||||
var validator = new WorkflowRulesValidator();
|
||||
validator.ValidateAndThrow(workflowRule);
|
||||
_rulesCache.AddOrUpdateWorkflowRules(workflowRule.WorkflowName, workflowRule);
|
||||
var validator = new WorkflowsValidator();
|
||||
validator.ValidateAndThrow(workflow);
|
||||
_rulesCache.AddOrUpdateWorkflows(workflow.WorkflowName, workflow);
|
||||
}
|
||||
}
|
||||
catch (ValidationException ex)
|
||||
|
@ -212,7 +212,7 @@ namespace RulesEngine
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the workflows.
|
||||
/// Clears the workflow.
|
||||
/// </summary>
|
||||
public void ClearWorkflows()
|
||||
{
|
||||
|
@ -220,7 +220,7 @@ namespace RulesEngine
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the workflow.
|
||||
/// Removes the workflows.
|
||||
/// </summary>
|
||||
/// <param name="workflowNames">The workflow names.</param>
|
||||
public void RemoveWorkflow(params string[] workflowNames)
|
||||
|
@ -271,13 +271,13 @@ namespace RulesEngine
|
|||
return true;
|
||||
}
|
||||
|
||||
var workflowRules = _rulesCache.GetWorkFlowRules(workflowName);
|
||||
if (workflowRules != null)
|
||||
var workflow = _rulesCache.GetWorkflow(workflowName);
|
||||
if (workflow != null)
|
||||
{
|
||||
var dictFunc = new Dictionary<string, RuleFunc<RuleResultTree>>();
|
||||
foreach (var rule in workflowRules.Rules.Where(c => c.Enabled))
|
||||
foreach (var rule in workflow.Rules.Where(c => c.Enabled))
|
||||
{
|
||||
dictFunc.Add(rule.RuleName, CompileRule(rule, ruleParams, workflowRules.GlobalParams?.ToArray()));
|
||||
dictFunc.Add(rule.RuleName, CompileRule(rule, ruleParams, workflow.GlobalParams?.ToArray()));
|
||||
}
|
||||
|
||||
_rulesCache.AddOrUpdateCompiledRule(compileRulesKey, dictFunc);
|
||||
|
@ -293,7 +293,7 @@ namespace RulesEngine
|
|||
|
||||
private RuleFunc<RuleResultTree> CompileRule(string workflowName, string ruleName, RuleParameter[] ruleParameters)
|
||||
{
|
||||
var workflow = _rulesCache.GetWorkFlowRules(workflowName);
|
||||
var workflow = _rulesCache.GetWorkflow(workflowName);
|
||||
if(workflow == null)
|
||||
{
|
||||
throw new ArgumentException($"Workflow `{workflowName}` is not found");
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace RulesEngine.Validators
|
|||
.WithMessage(Constants.OPERATOR_INCORRECT_ERRMSG);
|
||||
|
||||
When(c => c.Rules?.Any() != true, () => {
|
||||
RuleFor(c => c.WorkflowRulesToInject).NotEmpty().WithMessage(Constants.INJECT_WORKFLOW_RULES_ERRMSG);
|
||||
RuleFor(c => c.WorkflowsToInject).NotEmpty().WithMessage(Constants.INJECT_WORKFLOW_RULES_ERRMSG);
|
||||
})
|
||||
.Otherwise(() => {
|
||||
RuleFor(c => c.Rules).Must(BeValidRulesList);
|
||||
|
|
|
@ -8,13 +8,13 @@ using System.Linq;
|
|||
|
||||
namespace RulesEngine.Validators
|
||||
{
|
||||
internal class WorkflowRulesValidator : AbstractValidator<WorkflowRules>
|
||||
internal class WorkflowsValidator : AbstractValidator<Workflow>
|
||||
{
|
||||
public WorkflowRulesValidator()
|
||||
public WorkflowsValidator()
|
||||
{
|
||||
RuleFor(c => c.WorkflowName).NotEmpty().WithMessage(Constants.WORKFLOW_NAME_NULL_ERRMSG);
|
||||
When(c => c.Rules?.Any() != true, () => {
|
||||
RuleFor(c => c.WorkflowRulesToInject).NotEmpty().WithMessage(Constants.INJECT_WORKFLOW_RULES_ERRMSG);
|
||||
RuleFor(c => c.WorkflowsToInject).NotEmpty().WithMessage(Constants.INJECT_WORKFLOW_RULES_ERRMSG);
|
||||
}).Otherwise(() => {
|
||||
var ruleValidator = new RuleValidator();
|
||||
RuleForEach(c => c.Rules).SetValidator(ruleValidator);
|
||||
|
|
|
@ -18,8 +18,8 @@ namespace RulesEngine.UnitTest.ActionTests
|
|||
[Fact]
|
||||
public async Task CustomActionOnRuleMustHaveContextValues()
|
||||
{
|
||||
var workflows = GetWorkflowRules();
|
||||
var re = new RulesEngine(workflows, null, reSettings: new ReSettings {
|
||||
var workflow = GetWorkflow();
|
||||
var re = new RulesEngine(workflow, null, reSettings: new ReSettings {
|
||||
CustomActions = new Dictionary<string, System.Func<Actions.ActionBase>> {
|
||||
|
||||
{ "ReturnContext", () => new ReturnContextAction() }
|
||||
|
@ -33,13 +33,13 @@ namespace RulesEngine.UnitTest.ActionTests
|
|||
[Fact]
|
||||
public async Task CustomAction_WithSystemTextJsobOnRuleMustHaveContextValues()
|
||||
{
|
||||
var workflows = GetWorkflowRules();
|
||||
var workflowStr = JsonConvert.SerializeObject(workflows);
|
||||
var workflow = GetWorkflow();
|
||||
var workflowStr = JsonConvert.SerializeObject(workflow);
|
||||
var serializationOptions = new System.Text.Json.JsonSerializerOptions { Converters = { new JsonStringEnumConverter() } };
|
||||
var workflowViaTextJson = System.Text.Json.JsonSerializer.Deserialize<WorkflowRules[]>(workflowStr,serializationOptions);
|
||||
var workflowViaTextJson = System.Text.Json.JsonSerializer.Deserialize<Workflow[]>(workflowStr,serializationOptions);
|
||||
|
||||
|
||||
var re = new RulesEngine(workflows, null, reSettings: new ReSettings {
|
||||
var re = new RulesEngine(workflow, null, reSettings: new ReSettings {
|
||||
CustomActions = new Dictionary<string, System.Func<Actions.ActionBase>> {
|
||||
|
||||
{ "ReturnContext", () => new ReturnContextAction() }
|
||||
|
@ -51,10 +51,10 @@ namespace RulesEngine.UnitTest.ActionTests
|
|||
var result = await re.ExecuteAllRulesAsync("successReturnContextAction", true);
|
||||
}
|
||||
|
||||
private WorkflowRules[] GetWorkflowRules()
|
||||
private Workflow[] GetWorkflow()
|
||||
{
|
||||
return new WorkflowRules[] {
|
||||
new WorkflowRules {
|
||||
return new Workflow[] {
|
||||
new Workflow {
|
||||
WorkflowName = "successReturnContextAction",
|
||||
Rules = new Rule[] {
|
||||
new Rule {
|
||||
|
|
|
@ -46,16 +46,16 @@ namespace RulesEngine.UnitTest
|
|||
public async Task ExecuteActionWorkflowAsync_CalledWithNoActionsInWorkflow_ExecutesSuccessfully()
|
||||
{
|
||||
|
||||
var engine = new RulesEngine(GetWorkflowRulesWithoutActions());
|
||||
var engine = new RulesEngine(GetWorkflowsWithoutActions());
|
||||
var result = await engine.ExecuteActionWorkflowAsync("NoActionWorkflow", "NoActionTest", new RuleParameter[0]);
|
||||
Assert.NotNull(result);
|
||||
Assert.Null(result.Output);
|
||||
}
|
||||
|
||||
|
||||
private WorkflowRules[] GetWorkflowRulesWithoutActions()
|
||||
private Workflow[] GetWorkflowsWithoutActions()
|
||||
{
|
||||
var workflow1 = new WorkflowRules {
|
||||
var workflow1 = new Workflow {
|
||||
WorkflowName = "NoActionWorkflow",
|
||||
Rules = new List<Rule>{
|
||||
new Rule{
|
||||
|
@ -69,10 +69,10 @@ namespace RulesEngine.UnitTest
|
|||
return new[] { workflow1 };
|
||||
}
|
||||
|
||||
private WorkflowRules[] GetWorkflowWithActions()
|
||||
private Workflow[] GetWorkflowWithActions()
|
||||
{
|
||||
|
||||
var workflow1 = new WorkflowRules {
|
||||
var workflow1 = new Workflow {
|
||||
WorkflowName = "ActionWorkflow",
|
||||
Rules = new List<Rule>{
|
||||
new Rule{
|
||||
|
|
|
@ -81,9 +81,9 @@ namespace RulesEngine.UnitTest
|
|||
Assert.Contains(result1, c => c.IsSuccess);
|
||||
|
||||
// Fetch and add new rules.
|
||||
var newWorkflowRules = ParseAsWorkflowRules(newWorkflowFile);
|
||||
var newWorkflow = ParseAsWorkflow(newWorkflowFile);
|
||||
|
||||
Assert.Throws<RuleValidationException>(() => re.AddWorkflow(newWorkflowRules));
|
||||
Assert.Throws<RuleValidationException>(() => re.AddWorkflow(newWorkflow));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
@ -103,8 +103,8 @@ namespace RulesEngine.UnitTest
|
|||
Assert.Contains(result1, c => c.IsSuccess);
|
||||
|
||||
// Fetch and update new rules.
|
||||
WorkflowRules newWorkflowRules = ParseAsWorkflowRules(newWorkflowFile);
|
||||
re.AddOrUpdateWorkflow(newWorkflowRules);
|
||||
Workflow newWorkflow = ParseAsWorkflow(newWorkflowFile);
|
||||
re.AddOrUpdateWorkflow(newWorkflow);
|
||||
|
||||
// Run new rules.
|
||||
List<RuleResultTree> result2 = await re.ExecuteAllRulesAsync("inputWorkflow", input1, input2, input3);
|
||||
|
@ -123,21 +123,21 @@ namespace RulesEngine.UnitTest
|
|||
public void GetAllRegisteredWorkflows_ReturnsListOfAllWorkflows(string ruleFileName)
|
||||
{
|
||||
var re = GetRulesEngine(ruleFileName);
|
||||
var workflows = re.GetAllRegisteredWorkflowNames();
|
||||
var workflow = re.GetAllRegisteredWorkflowNames();
|
||||
|
||||
Assert.NotNull(workflows);
|
||||
Assert.Equal(2, workflows.Count);
|
||||
Assert.Contains("inputWorkflow", workflows);
|
||||
Assert.NotNull(workflow);
|
||||
Assert.Equal(2, workflow.Count);
|
||||
Assert.Contains("inputWorkflow", workflow);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAllRegisteredWorkflows_NoWorkflow_ReturnsEmptyList()
|
||||
{
|
||||
var re = new RulesEngine();
|
||||
var workflows = re.GetAllRegisteredWorkflowNames();
|
||||
var workflow = re.GetAllRegisteredWorkflowNames();
|
||||
|
||||
Assert.NotNull(workflows);
|
||||
Assert.Empty(workflows);
|
||||
Assert.NotNull(workflow);
|
||||
Assert.Empty(workflow);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
@ -257,12 +257,12 @@ namespace RulesEngine.UnitTest
|
|||
public void RulesEngine_New_IncorrectJSON_ThrowsException()
|
||||
{
|
||||
Assert.Throws<RuleValidationException>(() => {
|
||||
var workflow = new WorkflowRules();
|
||||
var workflow = new Workflow();
|
||||
var re = CreateRulesEngine(workflow);
|
||||
});
|
||||
|
||||
Assert.Throws<RuleValidationException>(() => {
|
||||
var workflow = new WorkflowRules() { WorkflowName = "test" };
|
||||
var workflow = new Workflow() { WorkflowName = "test" };
|
||||
var re = CreateRulesEngine(workflow);
|
||||
});
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
|
||||
var fileData = File.ReadAllText(files[0]);
|
||||
var bre = new RulesEngine(JsonConvert.DeserializeObject<WorkflowRules[]>(fileData), null);
|
||||
var bre = new RulesEngine(JsonConvert.DeserializeObject<Workflow[]>(fileData), null);
|
||||
var result = await bre.ExecuteAllRulesAsync("inputWorkflow", ruleParams?.ToArray());
|
||||
var ruleResult = result?.FirstOrDefault(r => string.Equals(r.Rule.RuleName, "GiveDiscount10", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.True(ruleResult.IsSuccess);
|
||||
|
@ -515,7 +515,7 @@ namespace RulesEngine.UnitTest
|
|||
public async Task ExecuteRule_RuntimeError_ShouldReturnAsErrorMessage()
|
||||
{
|
||||
|
||||
var workflow = new WorkflowRules {
|
||||
var workflow = new Workflow {
|
||||
WorkflowName = "TestWorkflow",
|
||||
Rules = new[] {
|
||||
new Rule {
|
||||
|
@ -542,7 +542,7 @@ namespace RulesEngine.UnitTest
|
|||
public async Task ExecuteRule_RuntimeError_ThrowsException()
|
||||
{
|
||||
|
||||
var workflow = new WorkflowRules {
|
||||
var workflow = new Workflow {
|
||||
WorkflowName = "TestWorkflow",
|
||||
Rules = new[] {
|
||||
new Rule {
|
||||
|
@ -567,7 +567,7 @@ namespace RulesEngine.UnitTest
|
|||
public async Task ExecuteRule_RuntimeError_IgnoreException_DoesNotReturnException()
|
||||
{
|
||||
|
||||
var workflow = new WorkflowRules {
|
||||
var workflow = new Workflow {
|
||||
WorkflowName = "TestWorkflow",
|
||||
Rules = new[] {
|
||||
new Rule {
|
||||
|
@ -595,7 +595,7 @@ namespace RulesEngine.UnitTest
|
|||
[Fact]
|
||||
public async Task RemoveWorkFlow_ShouldRemoveAllCompiledCache()
|
||||
{
|
||||
var workflow = new WorkflowRules {
|
||||
var workflow = new Workflow {
|
||||
WorkflowName = "Test",
|
||||
Rules = new Rule[]{
|
||||
new Rule {
|
||||
|
@ -629,7 +629,7 @@ namespace RulesEngine.UnitTest
|
|||
[Fact]
|
||||
public async Task ClearWorkFlow_ShouldRemoveAllCompiledCache()
|
||||
{
|
||||
var workflow = new WorkflowRules {
|
||||
var workflow = new Workflow {
|
||||
WorkflowName = "Test",
|
||||
Rules = new Rule[]{
|
||||
new Rule {
|
||||
|
@ -663,7 +663,7 @@ namespace RulesEngine.UnitTest
|
|||
[Fact]
|
||||
public async Task ExecuteRule_WithNullInput_ShouldNotThrowException()
|
||||
{
|
||||
var workflow = new WorkflowRules {
|
||||
var workflow = new Workflow {
|
||||
WorkflowName = "Test",
|
||||
Rules = new Rule[]{
|
||||
new Rule {
|
||||
|
@ -697,7 +697,7 @@ namespace RulesEngine.UnitTest
|
|||
[Fact]
|
||||
public async Task ExecuteRule_SpecialCharInWorkflowName_RunsSuccessfully()
|
||||
{
|
||||
var workflow = new WorkflowRules {
|
||||
var workflow = new Workflow {
|
||||
WorkflowName = "Exámple",
|
||||
Rules = new Rule[]{
|
||||
new Rule {
|
||||
|
@ -709,7 +709,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
};
|
||||
|
||||
var workflowStr = "{\"WorkflowName\":\"Exámple\",\"WorkflowRulesToInject\":null,\"GlobalParams\":null,\"Rules\":[{\"RuleName\":\"RuleWithLocalParam\",\"Properties\":null,\"Operator\":null,\"ErrorMessage\":null,\"Enabled\":true,\"ErrorType\":\"Warning\",\"RuleExpressionType\":\"LambdaExpression\",\"WorkflowRulesToInject\":null,\"Rules\":null,\"LocalParams\":null,\"Expression\":\"input1 == null || input1.hello.world = \\\"wow\\\"\",\"Actions\":null,\"SuccessEvent\":null}]}";
|
||||
var workflowStr = "{\"WorkflowName\":\"Exámple\",\"WorkflowsToInject\":null,\"GlobalParams\":null,\"Rules\":[{\"RuleName\":\"RuleWithLocalParam\",\"Properties\":null,\"Operator\":null,\"ErrorMessage\":null,\"Enabled\":true,\"ErrorType\":\"Warning\",\"RuleExpressionType\":\"LambdaExpression\",\"WorkflowsToInject\":null,\"Rules\":null,\"LocalParams\":null,\"Expression\":\"input1 == null || input1.hello.world = \\\"wow\\\"\",\"Actions\":null,\"SuccessEvent\":null}]}";
|
||||
|
||||
var re = new RulesEngine(new string[] { workflowStr },null,null);
|
||||
|
||||
|
@ -740,7 +740,7 @@ namespace RulesEngine.UnitTest
|
|||
|
||||
|
||||
|
||||
private RulesEngine CreateRulesEngine(WorkflowRules workflow)
|
||||
private RulesEngine CreateRulesEngine(Workflow workflow)
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(workflow);
|
||||
return new RulesEngine(new string[] { json }, null);
|
||||
|
@ -750,9 +750,9 @@ namespace RulesEngine.UnitTest
|
|||
{
|
||||
var data = GetFileContent(filename);
|
||||
|
||||
var injectWorkflow = new WorkflowRules {
|
||||
var injectWorkflow = new Workflow {
|
||||
WorkflowName = "inputWorkflowReference",
|
||||
WorkflowRulesToInject = new List<string> { "inputWorkflow" }
|
||||
WorkflowsToInject = new List<string> { "inputWorkflow" }
|
||||
};
|
||||
|
||||
var injectWorkflowStr = JsonConvert.SerializeObject(injectWorkflow);
|
||||
|
@ -766,10 +766,10 @@ namespace RulesEngine.UnitTest
|
|||
return File.ReadAllText(filePath);
|
||||
}
|
||||
|
||||
private WorkflowRules ParseAsWorkflowRules(string workflowRulesFileName)
|
||||
private Workflow ParseAsWorkflow(string WorkflowsFileName)
|
||||
{
|
||||
string content = GetFileContent(workflowRulesFileName);
|
||||
return JsonConvert.DeserializeObject<WorkflowRules>(content);
|
||||
string content = GetFileContent(WorkflowsFileName);
|
||||
return JsonConvert.DeserializeObject<Workflow>(content);
|
||||
}
|
||||
|
||||
private dynamic GetInput1()
|
||||
|
|
|
@ -20,40 +20,40 @@ namespace RulesEngine.UnitTest
|
|||
[Fact]
|
||||
private async Task EmptyRules_ReturnsExepectedResults()
|
||||
{
|
||||
var workflows = GetEmptyWorkflows();
|
||||
var workflow = GetEmptyWorkflow();
|
||||
var reSettings = new ReSettings { };
|
||||
RulesEngine rulesEngine = new RulesEngine();
|
||||
|
||||
Func<Task> action = () => {
|
||||
new RulesEngine(workflows, reSettings: reSettings);
|
||||
new RulesEngine(workflow, reSettings: reSettings);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
Exception ex = await Assert.ThrowsAsync<Exceptions.RuleValidationException>(action);
|
||||
|
||||
Assert.Contains("Atleast one of Rules or WorkflowRulesToInject must be not empty", ex.Message);
|
||||
Assert.Contains("Atleast one of Rules or WorkflowsToInject must be not empty", ex.Message);
|
||||
}
|
||||
[Fact]
|
||||
private async Task NestedRulesWithEmptyNestedActions_ReturnsExepectedResults()
|
||||
{
|
||||
var workflows = GetEmptyNestedWorkflows();
|
||||
var workflow = GetEmptyNestedWorkflows();
|
||||
var reSettings = new ReSettings { };
|
||||
RulesEngine rulesEngine = new RulesEngine();
|
||||
|
||||
Func<Task> action = () => {
|
||||
new RulesEngine(workflows, reSettings: reSettings);
|
||||
new RulesEngine(workflow, reSettings: reSettings);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
Exception ex = await Assert.ThrowsAsync<Exceptions.RuleValidationException>(action);
|
||||
|
||||
Assert.Contains("Atleast one of Rules or WorkflowRulesToInject must be not empty", ex.Message);
|
||||
Assert.Contains("Atleast one of Rules or WorkflowsToInject must be not empty", ex.Message);
|
||||
}
|
||||
|
||||
private WorkflowRules[] GetEmptyWorkflows()
|
||||
private Workflow[] GetEmptyWorkflow()
|
||||
{
|
||||
return new[] {
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "EmptyRulesTest",
|
||||
Rules = new Rule[] {
|
||||
}
|
||||
|
@ -61,10 +61,10 @@ namespace RulesEngine.UnitTest
|
|||
};
|
||||
}
|
||||
|
||||
private WorkflowRules[] GetEmptyNestedWorkflows()
|
||||
private Workflow[] GetEmptyNestedWorkflows()
|
||||
{
|
||||
return new[] {
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "EmptyNestedRulesTest",
|
||||
Rules = new Rule[] {
|
||||
new Rule {
|
||||
|
@ -129,7 +129,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "EmptyNestedRulesActionsTest",
|
||||
Rules = new Rule[] {
|
||||
new Rule {
|
||||
|
|
|
@ -22,9 +22,9 @@ namespace RulesEngine.UnitTest
|
|||
[InlineData(NestedRuleExecutionMode.Performance)]
|
||||
public async Task NestedRulesShouldFollowExecutionMode(NestedRuleExecutionMode mode)
|
||||
{
|
||||
var workflows = GetWorkflows();
|
||||
var workflow = GetWorkflow();
|
||||
var reSettings = new ReSettings { NestedRuleExecutionMode = mode };
|
||||
var rulesEngine = new RulesEngine(workflows, reSettings: reSettings);
|
||||
var rulesEngine = new RulesEngine(workflow, reSettings: reSettings);
|
||||
dynamic input1 = new ExpandoObject();
|
||||
input1.trueValue = true;
|
||||
|
||||
|
@ -68,9 +68,9 @@ namespace RulesEngine.UnitTest
|
|||
[Fact]
|
||||
private async Task NestedRulesWithNestedActions_ReturnsCorrectResults()
|
||||
{
|
||||
var workflows = GetWorkflows();
|
||||
var workflow = GetWorkflow();
|
||||
var reSettings = new ReSettings { };
|
||||
var rulesEngine = new RulesEngine(workflows, reSettings: reSettings);
|
||||
var rulesEngine = new RulesEngine(workflow, reSettings: reSettings);
|
||||
dynamic input1 = new ExpandoObject();
|
||||
input1.trueValue = true;
|
||||
|
||||
|
@ -84,16 +84,16 @@ namespace RulesEngine.UnitTest
|
|||
[Fact]
|
||||
private async Task NestedRulesWithNestedActions_WorkflowParsedWithSystemTextJson_ReturnsCorrectResults()
|
||||
{
|
||||
var workflows = GetWorkflows();
|
||||
var workflowStr = JsonConvert.SerializeObject(workflows);
|
||||
var workflow = GetWorkflow();
|
||||
var workflowStr = JsonConvert.SerializeObject(workflow);
|
||||
|
||||
var serializationOptions = new System.Text.Json.JsonSerializerOptions { Converters = { new JsonStringEnumConverter() } };
|
||||
|
||||
|
||||
var workflowsViaTextJson = System.Text.Json.JsonSerializer.Deserialize<WorkflowRules[]>(workflowStr, serializationOptions);
|
||||
var workflowViaTextJson = System.Text.Json.JsonSerializer.Deserialize<Workflow[]>(workflowStr, serializationOptions);
|
||||
|
||||
var reSettings = new ReSettings { };
|
||||
var rulesEngine = new RulesEngine(workflowsViaTextJson, reSettings: reSettings);
|
||||
var rulesEngine = new RulesEngine(workflowViaTextJson, reSettings: reSettings);
|
||||
dynamic input1 = new ExpandoObject();
|
||||
input1.trueValue = true;
|
||||
|
||||
|
@ -108,10 +108,10 @@ namespace RulesEngine.UnitTest
|
|||
|
||||
|
||||
|
||||
private WorkflowRules[] GetWorkflows()
|
||||
private Workflow[] GetWorkflow()
|
||||
{
|
||||
return new[] {
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "NestedRulesTest",
|
||||
Rules = new Rule[] {
|
||||
new Rule {
|
||||
|
@ -176,7 +176,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "NestedRulesActionsTest",
|
||||
Rules = new Rule[] {
|
||||
new Rule {
|
||||
|
|
|
@ -22,8 +22,8 @@ namespace RulesEngine.UnitTest
|
|||
[InlineData("RuleEnabledNestedFeatureTest", new bool[] { true, true, false })]
|
||||
public async Task RulesEngine_ShouldOnlyExecuteEnabledRules(string workflowName, bool[] expectedRuleResults)
|
||||
{
|
||||
var workflows = GetWorkflows();
|
||||
var rulesEngine = new RulesEngine(workflows, reSettings: new ReSettings() { EnableExceptionAsErrorMessage = false });
|
||||
var workflow = GetWorkflows();
|
||||
var rulesEngine = new RulesEngine(workflow, reSettings: new ReSettings() { EnableExceptionAsErrorMessage = false });
|
||||
var input1 = new {
|
||||
TrueValue = true
|
||||
};
|
||||
|
@ -95,10 +95,10 @@ namespace RulesEngine.UnitTest
|
|||
return areAllRulesEnabled;
|
||||
}
|
||||
|
||||
private WorkflowRules[] GetWorkflows()
|
||||
private Workflow[] GetWorkflows()
|
||||
{
|
||||
return new[] {
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "RuleEnabledFeatureTest",
|
||||
Rules = new List<Rule> {
|
||||
new Rule {
|
||||
|
@ -118,7 +118,7 @@ namespace RulesEngine.UnitTest
|
|||
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "RuleEnabledNestedFeatureTest",
|
||||
Rules = new List<Rule> {
|
||||
new Rule {
|
||||
|
|
|
@ -22,12 +22,12 @@ namespace RulesEngine.UnitTest
|
|||
[InlineData("GlobalParamReferencedInNextGlobalParams")]
|
||||
[InlineData("LocalParamReferencedInNextLocalParams")]
|
||||
[InlineData("GlobalParamAndLocalParamsInNestedRules")]
|
||||
public async Task BasicWorkflowRules_ReturnsTrue(string workflowName)
|
||||
public async Task BasicWorkflows_ReturnsTrue(string workflowName)
|
||||
{
|
||||
var workflows = GetWorkflowRulesList();
|
||||
var workflow = GetWorkflowList();
|
||||
|
||||
var engine = new RulesEngine(null, null);
|
||||
engine.AddWorkflow(workflows);
|
||||
engine.AddWorkflow(workflow);
|
||||
|
||||
var input1 = new {
|
||||
trueValue = true,
|
||||
|
@ -45,10 +45,10 @@ namespace RulesEngine.UnitTest
|
|||
[InlineData("GlobalAndLocalParams")]
|
||||
public async Task WorkflowUpdate_GlobalParam_ShouldReflect(string workflowName)
|
||||
{
|
||||
var workflows = GetWorkflowRulesList();
|
||||
var workflow = GetWorkflowList();
|
||||
|
||||
var engine = new RulesEngine(null, null);
|
||||
engine.AddWorkflow(workflows);
|
||||
engine.AddWorkflow(workflow);
|
||||
|
||||
var input1 = new {
|
||||
trueValue = true,
|
||||
|
@ -58,7 +58,7 @@ namespace RulesEngine.UnitTest
|
|||
var result = await engine.ExecuteAllRulesAsync(workflowName, input1);
|
||||
Assert.True(result.All(c => c.IsSuccess));
|
||||
|
||||
var workflowToUpdate = workflows.Single(c => c.WorkflowName == workflowName);
|
||||
var workflowToUpdate = workflow.Single(c => c.WorkflowName == workflowName);
|
||||
engine.RemoveWorkflow(workflowName);
|
||||
workflowToUpdate.GlobalParams.First().Expression = "true == false";
|
||||
engine.AddWorkflow(workflowToUpdate);
|
||||
|
@ -75,12 +75,12 @@ namespace RulesEngine.UnitTest
|
|||
[InlineData("GlobalAndLocalParams", new[] { false })]
|
||||
public async Task DisabledScopedParam_ShouldReflect(string workflowName, bool[] outputs)
|
||||
{
|
||||
var workflows = GetWorkflowRulesList();
|
||||
var workflow = GetWorkflowList();
|
||||
|
||||
var engine = new RulesEngine(new string[] { }, null, new ReSettings {
|
||||
EnableScopedParams = false
|
||||
});
|
||||
engine.AddWorkflow(workflows);
|
||||
engine.AddWorkflow(workflow);
|
||||
|
||||
var input1 = new {
|
||||
trueValue = true,
|
||||
|
@ -103,10 +103,10 @@ namespace RulesEngine.UnitTest
|
|||
[InlineData("LocalParamsOnly2")]
|
||||
public async Task ErrorInScopedParam_ShouldAppearAsErrorMessage(string workflowName)
|
||||
{
|
||||
var workflows = GetWorkflowRulesList();
|
||||
var workflow = GetWorkflowList();
|
||||
|
||||
var engine = new RulesEngine(new string[] { }, null);
|
||||
engine.AddWorkflow(workflows);
|
||||
engine.AddWorkflow(workflow);
|
||||
|
||||
var input = new { };
|
||||
var result = await engine.ExecuteAllRulesAsync(workflowName, input);
|
||||
|
@ -123,10 +123,10 @@ namespace RulesEngine.UnitTest
|
|||
[InlineData("LocalParamsOnlyWithComplexInput")]
|
||||
public async Task RuntimeErrorInScopedParam_ShouldAppearAsErrorMessage(string workflowName)
|
||||
{
|
||||
var workflows = GetWorkflowRulesList();
|
||||
var workflow = GetWorkflowList();
|
||||
|
||||
var engine = new RulesEngine(new string[] { }, null);
|
||||
engine.AddWorkflow(workflows);
|
||||
engine.AddWorkflow(workflow);
|
||||
|
||||
|
||||
|
||||
|
@ -143,7 +143,7 @@ namespace RulesEngine.UnitTest
|
|||
|
||||
private void CheckResultTreeContainsAllInputs(string workflowName, List<RuleResultTree> result)
|
||||
{
|
||||
var workflow = GetWorkflowRulesList().Single(c => c.WorkflowName == workflowName);
|
||||
var workflow = GetWorkflowList().Single(c => c.WorkflowName == workflowName);
|
||||
var expectedInputs = new List<string>() { "input1" };
|
||||
expectedInputs.AddRange(workflow.GlobalParams?.Select(c => c.Name) ?? new List<string>());
|
||||
|
||||
|
@ -176,10 +176,10 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
|
||||
}
|
||||
private WorkflowRules[] GetWorkflowRulesList()
|
||||
private Workflow[] GetWorkflowList()
|
||||
{
|
||||
return new WorkflowRules[] {
|
||||
new WorkflowRules {
|
||||
return new Workflow[] {
|
||||
new Workflow {
|
||||
WorkflowName = "NoLocalAndGlobalParams",
|
||||
Rules = new List<Rule> {
|
||||
new Rule {
|
||||
|
@ -188,7 +188,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "LocalParamsOnly",
|
||||
Rules = new List<Rule> {
|
||||
new Rule {
|
||||
|
@ -209,7 +209,7 @@ namespace RulesEngine.UnitTest
|
|||
},
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "LocalParamsOnly2",
|
||||
Rules = new List<Rule> {
|
||||
new Rule {
|
||||
|
@ -226,7 +226,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
},
|
||||
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "GlobalParamsOnly",
|
||||
GlobalParams = new List<ScopedParam> {
|
||||
new ScopedParam {
|
||||
|
@ -241,7 +241,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "GlobalAndLocalParams",
|
||||
GlobalParams = new List<ScopedParam> {
|
||||
new ScopedParam {
|
||||
|
@ -263,7 +263,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "GlobalParamReferencedInLocalParams",
|
||||
GlobalParams = new List<ScopedParam> {
|
||||
new ScopedParam {
|
||||
|
@ -285,7 +285,7 @@ namespace RulesEngine.UnitTest
|
|||
},
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "GlobalParamReferencedInNextGlobalParams",
|
||||
GlobalParams = new List<ScopedParam> {
|
||||
new ScopedParam {
|
||||
|
@ -304,7 +304,7 @@ namespace RulesEngine.UnitTest
|
|||
},
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "LocalParamReferencedInNextLocalParams",
|
||||
Rules = new List<Rule> {
|
||||
new Rule {
|
||||
|
@ -323,7 +323,7 @@ namespace RulesEngine.UnitTest
|
|||
},
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "GlobalParamAndLocalParamsInNestedRules",
|
||||
GlobalParams = new List<ScopedParam> {
|
||||
new ScopedParam {
|
||||
|
@ -362,7 +362,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "LocalParamsOnlyWithComplexInput",
|
||||
Rules = new List<Rule> {
|
||||
new Rule {
|
||||
|
@ -378,7 +378,7 @@ namespace RulesEngine.UnitTest
|
|||
}
|
||||
}
|
||||
},
|
||||
new WorkflowRules {
|
||||
new Workflow {
|
||||
WorkflowName = "GlobalParamsOnlyWithComplexInput",
|
||||
GlobalParams = new List<ScopedParam> {
|
||||
new ScopedParam {
|
||||
|
|
Loading…
Reference in New Issue