Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

completed flow implementation, execution of flow code with dsl condit…

…ions and activties. Check FlowTests for more info.
  • Loading branch information...
commit a29fb76df1498fbdd2b8bd91ca5918be1a346936 1 parent c7d8623
@nara nara authored
View
20 FluentFlow/ActivityProcessNode.cs
@@ -0,0 +1,20 @@
+using RulesEngine;
+
+namespace FluentFlow
+{
+ public class ActivityProcessNode<T> : ProcessNode<T>
+ {
+ private AbstractActivity activity;
+ public ActivityProcessNode(AbstractActivity activity, FlowElement<T> master)
+ : base(master)
+ {
+ this.activity = activity;
+ }
+
+ internal override void Evaluate(T instance)
+ {
+ if (this.activity != null) activity.Execute(instance);
+ base.Evaluate(instance);
+ }
+ }
+}
View
20 FluentFlow/ConditionDecisionNode.cs
@@ -0,0 +1,20 @@
+using RulesEngine;
+
+namespace FluentFlow
+{
+ public class ConditionDecisionNode<T> : DecisionNode<T>
+ {
+ private AbstractCondition condition;
+
+ public ConditionDecisionNode(AbstractCondition condition, FlowElement<T> master)
+ : base(master)
+ {
+ this.condition = condition;
+ }
+
+ protected override bool Condition(T instance)
+ {
+ return condition.Evaluate(instance);
+ }
+ }
+}
View
29 FluentFlow/DecisionNode.cs
@@ -2,25 +2,38 @@
namespace FluentFlow
{
- public class DecisionNode<T> : FlowElement<T>
+ public abstract class DecisionNode<T> : FlowElement<T>
{
- public DecisionNode(Func<T> condition)
+ private TrueFalseNode<T> trueNode;
+ private FalseTrueNode<T> falseNode;
+
+ protected DecisionNode(FlowElement<T> master) : base(master)
{
}
- public TrueDecisionNode<T> WhenTrue(Action<FlowNode<T>> action)
+ public TrueFalseNode<T> WhenTrue(Action<FlowNode<T>> action)
{
- throw new NotImplementedException();
+ trueNode = new TrueFalseNode<T>(action, master);
+ return trueNode;
}
- public FalseDecisionNode<T> WhenFalse(Action<FlowNode<T>> action)
+ public FalseTrueNode<T> WhenFalse(Action<FlowNode<T>> action)
{
- throw new NotImplementedException();
+ falseNode = new FalseTrueNode<T>(action, master);
+ return falseNode;
}
- public override void Evaluate(T instance)
+ protected abstract bool Condition(T instance);
+
+ internal override void Evaluate(T instance)
{
- throw new NotImplementedException();
+ var branchNode = trueNode ?? (falseNode ?? (DicisionBranchNode<T>)null);
+ if (branchNode == null) return;
+
+ if(this.Condition(instance))
+ branchNode.Evaluate(instance);
+ else
+ branchNode.EvaluateOtherResult(instance);
}
}
}
View
13 FluentFlow/FalseDecisionNode.cs
@@ -1,13 +0,0 @@
-using System;
-
-namespace FluentFlow
-{
- public class FalseDecisionNode<T> : FollowingNode<T>
- {
- public FollowingNode<T> WhenTrue(Action<FlowNode<T>> action)
- {
- action(new FlowNode<T>());
- return new FollowingNode<T>();
- }
- }
-}
View
21 FluentFlow/Flow.cs
@@ -2,26 +2,11 @@
namespace FluentFlow
{
- public class Flow<T> : FlowElement<T>
+ public static class Flow
{
- public override void Evaluate(T instance)
+ public static FlowNode<T> For<T>()
{
- throw new NotImplementedException();
- }
-
- public static DecisionNode<T> Decide(Func<T, bool> func)
- {
- throw new NotImplementedException();
- }
-
- public static FollowingNode<T> Do(Action<FlowNode<T>> action)
- {
- throw new NotImplementedException();
- }
-
- public static FollowingNode<T> Do(Action<T> action)
- {
- throw new NotImplementedException();
+ return new FlowNode<T>();
}
}
}
View
21 FluentFlow/FlowElement.cs
@@ -2,6 +2,25 @@ namespace FluentFlow
{
public abstract class FlowElement<T>
{
- public abstract void Evaluate(T instance);
+ protected FlowElement<T> master;
+
+ protected FlowElement()
+ {
+ master = this;
+ }
+
+ protected FlowElement(FlowElement<T> master)
+ {
+ this.master = master;
+ }
+ internal abstract void Evaluate(T instance);
+
+ public virtual void Execute(T instance)
+ {
+ if(this.master != null)
+ this.master.Evaluate(instance);
+ else
+ this.Evaluate(instance);
+ }
}
}
View
40 FluentFlow/FlowNode.cs
@@ -5,29 +5,51 @@ namespace FluentFlow
{
public class FlowNode<T> : FlowElement<T>
{
- public override void Evaluate(T instance)
+ private DecisionNode<T> decisionNode;
+ private ProcessNode<T> actionNode;
+
+ public FlowNode()
{
- throw new NotImplementedException();
+ }
+
+ public FlowNode(FlowElement<T> master): base(master)
+ {
+ }
+
+ internal override void Evaluate(T instance)
+ {
+ if (decisionNode != null) decisionNode.Evaluate(instance);
+ if (actionNode != null) actionNode.Evaluate(instance);
}
public DecisionNode<T> Decide(Func<T, bool> func)
{
- throw new NotImplementedException();
+ decisionNode = new ConditionDecisionNode<T>(new FuncCondition<T>(func), master);
+ return decisionNode;
+ }
+
+ public DecisionNode<T> Decide<TCondition>(TCondition condition) where TCondition : AbstractCondition
+ {
+ decisionNode = new ConditionDecisionNode<T>(condition, master);
+ return decisionNode;
}
- public DecisionNode<T> Decide<TRule>() where TRule : AbstractRule
+ public ProcessNode<T> Do(Action<FlowNode<T>> action)
{
- throw new NotImplementedException();
+ actionNode = new FlowProcessNode<T>(action, master);
+ return actionNode;
}
- public FollowingNode<T> Do(Action<FlowNode<T>> action)
+ public ProcessNode<T> Do(Action<T> action)
{
- throw new NotImplementedException();
+ actionNode = new ActivityProcessNode<T>(new ActionActivity<T>(action), master);
+ return actionNode;
}
- public FollowingNode<T> Do(Action<T> action)
+ public ProcessNode<T> Do(AbstractActivity activity)
{
- throw new NotImplementedException();
+ actionNode = new ActivityProcessNode<T>(activity, master);
+ return actionNode;
}
}
}
View
26 FluentFlow/FlowProcessNode.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace FluentFlow
+{
+ public class FlowProcessNode<T> : ProcessNode<T>
+ {
+ private Action<FlowNode<T>> action;
+ public FlowProcessNode(Action<FlowNode<T>> action, FlowElement<T> master)
+ : base(master)
+ {
+ this.action = action;
+ }
+
+ internal override void Evaluate(T instance)
+ {
+ if (action != null)
+ {
+ var flowNode = new FlowNode<T>(master);
+ action(flowNode);
+ flowNode.Evaluate(instance);
+ }
+ base.Evaluate(instance);
+ }
+ }
+
+}
View
8 FluentFlow/FluentFlow.csproj
@@ -45,14 +45,16 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="ActivityProcessNode.cs" />
<Compile Include="DecisionNode.cs" />
- <Compile Include="FalseDecisionNode.cs" />
<Compile Include="Flow.cs" />
<Compile Include="FlowElement.cs" />
<Compile Include="FlowNode.cs" />
- <Compile Include="FollowingNode.cs" />
+ <Compile Include="FlowProcessNode.cs" />
+ <Compile Include="ProcessNode.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="TrueDecisionNode.cs" />
+ <Compile Include="ConditionDecisionNode.cs" />
+ <Compile Include="TrueFalseNode.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RulesEngine\RulesEngine.csproj">
View
18 FluentFlow/FollowingNode.cs
@@ -1,18 +0,0 @@
-namespace FluentFlow
-{
- public class FollowingNode<T> : FlowElement<T>
- {
- public FlowNode<T> Then
- {
- get
- {
- return new FlowNode<T>();
- }
- }
-
- public override void Evaluate(T instance)
- {
- throw new System.NotImplementedException();
- }
- }
-}
View
29 FluentFlow/ProcessNode.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace FluentFlow
+{
+ public class ProcessNode<T> : FlowElement<T>
+ {
+ private Action<FlowNode<T>> continuedAction;
+ private Action<T> finalAction;
+ private FlowNode<T> then;
+
+ public ProcessNode(FlowElement<T> master) : base(master)
+ {
+ }
+
+ public FlowNode<T> Then
+ {
+ get
+ {
+ if (then == null) then = new FlowNode<T>(master);
+ return then;
+ }
+ }
+
+ internal override void Evaluate(T instance)
+ {
+ if (then != null) then.Evaluate(instance);
+ }
+ }
+}
View
13 FluentFlow/TrueDecisionNode.cs
@@ -1,13 +0,0 @@
-using System;
-
-namespace FluentFlow
-{
- public class TrueDecisionNode<T> : FollowingNode<T>
- {
- public FollowingNode<T> WhenFalse(Action<FlowNode<T>> action)
- {
- action(new FlowNode<T>());
- return new FollowingNode<T>();
- }
- }
-}
View
47 FluentFlow/TrueFalseNode.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace FluentFlow
+{
+ public class DicisionBranchNode<T> : FlowProcessNode<T>
+ {
+ protected ProcessNode<T> onOtherResult;
+
+ public DicisionBranchNode(Action<FlowNode<T>> action, FlowElement<T> master)
+ : base(action, master)
+ {
+ }
+
+ public void EvaluateOtherResult(T instance)
+ {
+ if(onOtherResult != null) onOtherResult.Evaluate(instance);
+ }
+ }
+
+ public class TrueFalseNode<T> : DicisionBranchNode<T>
+ {
+ public TrueFalseNode(Action<FlowNode<T>> action, FlowElement<T> master)
+ : base(action, master)
+ {
+ }
+
+ public ProcessNode<T> WhenFalse(Action<FlowNode<T>> action)
+ {
+ onOtherResult = new FlowProcessNode<T>(action, master);
+ return onOtherResult;
+ }
+ }
+
+ public class FalseTrueNode<T> : DicisionBranchNode<T>
+ {
+ public FalseTrueNode(Action<FlowNode<T>> action, FlowElement<T> master)
+ : base(action, master)
+ {
+ }
+
+ public ProcessNode<T> WhenTrue(Action<FlowNode<T>> action)
+ {
+ onOtherResult = new FlowProcessNode<T>(action, master);
+ return onOtherResult;
+ }
+ }
+}
View
81 RuleEngineTests/FlowTests.cs
@@ -2,28 +2,83 @@
using FluentFlow;
using NUnit.Framework;
using RulesEngine;
+using RulesEngine.BooEvaluator;
namespace RuleEngineTests
{
[TestFixture]
public class FlowTests
{
+ private BooLangEvaluator evaluator;
+
+ [SetUp]
+ public void Setup()
+ {
+ var dslEngineStorage = new DslEngineStorage();
+ evaluator = new BooLangEvaluator(dslEngineStorage);
+ }
+
[Test]
public void Can_Setup_Flow()
{
- var flow = Flow<Order>
- .Do(a => a.Price = 10)
- .Then.Decide(o => o.Price > 10)
- .WhenTrue(a =>
- a.Do(t => t.Price = 10)
- .Then.Decide(aa => aa.Price > 15)
- .WhenTrue(b => b.Do(t => t.Price = 20))
- .WhenFalse(b => b.Do(t => t.Price = 30))
- )
- .WhenFalse(a1 => a1.Do(t => t.Price = 30).Then.Do(t => t.Price = 40).Then.Do(t => t.Price = 50).
- Then.Decide(aa => aa.Price > 40).WhenFalse(a => a.Do(a2 => a2.Message ="test")));
-
- flow.Evaluate(new Order());
+ var flow = Flow.For<Order>()
+ .Do(a =>
+ a.Price = 10)
+ .Then
+ .Decide(o => o.Price > 10)
+ .WhenTrue(a => a.Do(t => t.Price = 10)
+ .Then
+ .Decide(aa => aa.Price > 15)
+ .WhenTrue(b => b.Do(t => t.Price = 20))
+ .WhenFalse(b => b.Do(t => t.Price = 30))
+ )
+ .WhenFalse(a1 => a1.Do(t => t.Price = 30)
+ .Then.Do(t => t.Price = 40).Then.Do(t => t.Price = 50).Then
+ .Decide(aa => aa.Price > 40).WhenFalse(a => a.Do(a2 => a2.Message ="test")));
+
+ var order = new Order {Price = 15};
+ flow.Execute(order);
+ Console.WriteLine(order.Price);
+ Console.WriteLine(order.Message);
+ }
+
+ [Test]
+ public void Can_Setup_Flow_With_Dsl_Conditions()
+ {
+ var statement = "return (this.Price > 15 and this.Price < 20)";
+ EvaluatorAccessPoint.DslConditionEvaluator = evaluator;
+
+ var flow = Flow.For<Order>()
+ .Decide(new DslCondition(statement))
+ .WhenTrue(a => a.Do(o => o.Message = "true"))
+ .WhenFalse(a => a.Do(o => o.Message = "false"));
+
+ var order = new Order { Price = 16 };
+ flow.Execute(order);
+ Assert.AreEqual("true", order.Message);
+ order.Price = 21;
+ flow.Execute(order);
+ Assert.AreEqual("false", order.Message);
+ }
+
+ [Test]
+ public void Can_Setup_Flow_With_Dsl_Conditions_And_DslActiviy()
+ {
+ var condition = "return (this.Price > 15 and this.Price < 20)";
+ var activity = @"this.Message = ""true""; return true; ";
+ EvaluatorAccessPoint.DslConditionEvaluator = evaluator;
+
+ var flow = Flow.For<Order>()
+ .Decide(new DslCondition(condition))
+ .WhenTrue(a => a.Do(new DslActivity(activity)))
+ .WhenFalse(a => a.Do(o => o.Message = "false"));
+
+ var order = new Order { Price = 16 };
+ flow.Execute(order);
+ Assert.AreEqual("true", order.Message);
+ order.Price = 21;
+ flow.Execute(order);
+ Assert.AreEqual("false", order.Message);
}
}
}
View
7 RulesEngine/DslActivity.cs
@@ -4,6 +4,13 @@ public class DslActivity : AbstractActivity
{
public string DslStatement { get; set; }
+ public DslActivity(){}
+
+ public DslActivity(string statement)
+ {
+ this.DslStatement = statement;
+ }
+
public override void Execute(object context)
{
if(EvaluatorAccessPoint.DslConditionEvaluator != null)
View
7 RulesEngine/DslCondition.cs
@@ -4,6 +4,13 @@ public class DslCondition : AbstractCondition
{
public string DslStatement { get; set; }
+ public DslCondition(){}
+
+ public DslCondition(string statement)
+ {
+ this.DslStatement = statement;
+ }
+
public override bool Evaluate(object context)
{
return EvaluatorAccessPoint.DslConditionEvaluator != null
Please sign in to comment.
Something went wrong with that request. Please try again.