IT:AD:Stateless:HowTo:Examples/Reading JSON
Summary
The following is about where I stopped investigating…when I realized I would need to find a solution to providing Orthagonal States.
Example
Your mileage may vary…
Reading
{
"name": "SomeWorkflow",
"states": [
{
"name": "OffHook",
"transitions": [
{ "name": "CallDialed", "target": "Ringing" }
]
},
{
"name": "Ringing",
"transitions": [
{ "name": "HungUp", "target": "OffHook" },
{ "name": "CallConnected", "target": "Connected" }
]
},
{
"name": "Connected",
"transitions": [
{ "name": "LeftMessage", "target": "OffHook" },
{ "name": "HungUp", "target": "OffHook" },
{ "name": "PlacedOnHold", "target": "OnHold" }
],
"command": "TelephoneCallExample.XYZ.BeHappy",
"states": [
{
"name": "OnHold",
"transitions": [
{ "name": "TakenOffHold", "target": "Connected" },
{ "name": "HungUp", "target": "OffHook" },
{ "name": "PhoneHurledAgainstWall", "target": "PhoneDestroyed" }
]
}
]
},
{
"name": "PhoneDetroyed",
"transitions": [
]
}
]
}
using the following:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Stateless;
namespace TelephoneCallExample
{
//public class WorkflowRepositoryService
//{
// public WorkflowStatus Get(int id)
// {
// }
//}
public class Workflow
{
public string Name { get; private set; }
public StateMachine<WorkflowState, string> Engine { get; private set; }
public ICollection<WorkflowState> States { get { return _states ??(_states = new Collection<WorkflowState>());} }
ICollection<WorkflowState> _states = new Collection<WorkflowState>();
public WorkflowStatus WorkflowStatus { get; private set; }
public Workflow(WorkflowDefinition workflowDefinition)
{
WorkflowStatus = new WorkflowStatus();
Engine = new StateMachine<WorkflowState, string>(
() => this.Instance,
(x) =>
{
this.Instance = x;
WorkflowStatus.StateName = this.Instance.Name;
}
);
this.Name = workflowDefinition.Name;
ParseWorkflowStates(workflowDefinition.States);
this.Initialize(this.States.First());
}
public void Initialize(WorkflowState x)
{
_instance = x;
}
private WorkflowState _instance;
public WorkflowState Instance
{
get { return _instance; }
set { _instance = value; }
}
public void Trigger(string trigger)
{
Engine.Fire(trigger);
}
public override string ToString()
{
return string.Format("{0} [State:{1}]", this.Name, this.Engine.State.Name);
}
private void ParseWorkflowStates(ICollection<WorkflowStateDefinition> workflowStateDefinitions)
{
foreach (WorkflowStateDefinition workflowStateDefinition in workflowStateDefinitions)
{
Console.WriteLine(string.Format("Registering {0}", workflowStateDefinition.Name));
WorkflowState workflowState = this.States.SingleOrDefault(x => x.Name == workflowStateDefinition.Name);
if (workflowState == null)
{
workflowState = new WorkflowState { Name = workflowStateDefinition.Name };
this.States.Add(workflowState);
}
foreach (WorkflowTargetDefinition workflowTargetDefinition in workflowStateDefinition.Transitions)
{
Console.WriteLine(string.Format("- {0}:{1}", workflowTargetDefinition.Name,
workflowTargetDefinition.Target));
//Get the name, and try to find the State:
var targetState = this.States.SingleOrDefault(x => x.Name == workflowTargetDefinition.Target);
if (targetState == null)
{
targetState = new WorkflowState { Name = workflowTargetDefinition.Target };
this.States.Add(targetState);
}
this.Engine.Configure(workflowState)
.Permit(
workflowTargetDefinition.Name,
targetState);
}
//Are there any subStates?
ParseWorkflowStates(workflowStateDefinition.States);
if (workflowStateDefinition.Command != null)
{
string tmp = workflowStateDefinition.Command;
int pos = tmp.LastIndexOf(".");
string tmpName = tmp.Substring(0, pos);
string tmpName2 = tmp.Substring(pos + 1);
var t = this.GetType().Assembly.GetType(tmpName);
var m = t.GetMethod(tmpName2);
}
}
}
}
public interface IHasName
{
string Name { get; set; }
}
public class WorkflowStatus
{
public Guid Id {get; set; }
public string Name { get; set; }
public string StateName { get; set; }
}
public class WorkflowState :IHasName
{
public string Name { get; set; }
public ICollection<WorkflowTransition> Transitions { get { return _transitions ?? (_transitions = new Collection<WorkflowTransition>()); } }
ICollection<WorkflowTransition> _transitions;
public override string ToString()
{
return string.Format("{0} [Triggers: {1}]", Name,string.Join(",",Transitions.Select(x=>x.Name).ToArray()));
}
}
public class WorkflowTransition : IHasName
{
public string Name { get; set; }
public WorkflowState Target { get; set; }
public override string ToString()
{
return string.Format("{0} [Target: {1}]",Name,Target);
}
}
public class WorkflowDefinition:IHasName
{
public string Name { get; set; }
public WorkflowStateDefinition[] States { get; set; }
}
public class WorkflowStateDefinition : IHasName
{
public string Name { get; set; }
public List<WorkflowTargetDefinition> Transitions { get { return _targets ?? (_targets = new List<WorkflowTargetDefinition>()); } }
private List<WorkflowTargetDefinition> _targets;
public ICollection<WorkflowStateDefinition> States { get { return _states??(_states = new Collection<WorkflowStateDefinition>());} }
private ICollection<WorkflowStateDefinition> _states;
public string Command { get; set; }
}
public class WorkflowTargetDefinition :IHasName
{
public string Name { get; set; }
public string Target { get; set; }
}
class Program
{
static void Main(string[] args)
{
var workflowDefinition = Parse(File.ReadAllText(@"json1.json"));
Workflow workflow = BuildWorkflowEngine( workflowDefinition, Guid.NewGuid());
Fire(workflow, "CallDialed");
Print(workflow);
Fire(workflow, "CallConnected");
Print(workflow);
Fire(workflow, "PlacedOnHold");
Print(workflow);
Fire(workflow, "TakenOffHold");
Print(workflow);
Fire(workflow, "HungUp");
Print(workflow);
Console.WriteLine("Press any key...");
Console.ReadKey(true);
}
private static WorkflowDefinition Parse(string workflowDescriptionJson)
{
WorkflowDefinition workflowDefinition =
JsonConvert.DeserializeObject<WorkflowDefinition>(workflowDescriptionJson);
return workflowDefinition;
}
private static Workflow BuildWorkflowEngine(WorkflowDefinition workflowDefinition, Guid workflowInstance)
{
//Deserialize json into workflow definition:
int workflowId;
Guid workflowInstanceId;
Workflow workflow = new Workflow(workflowDefinition);
return workflow;
}
static void Fire(Workflow workflow, string trigger)
{
Console.WriteLine("[Firing:] {0}", trigger);
workflow.Trigger(trigger);
}
static void Print(Workflow workflow)
{
Console.WriteLine("[Status:] {0}", workflow.Engine.State.Name);
}
}
public class XYZ
{
public void BeHappy()
{
Console.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
public void StartCallTimer()
{
Console.WriteLine("[Timer:] Call started at {0}", DateTime.Now);
}
public void StopCallTimer()
{
Console.WriteLine("[Timer:] Call ended at {0}", DateTime.Now);
}
}
}