طراحی گردش کاری با استفاده از State machines - قسمت اول
نویسنده: وحید نصیری
تاریخ: ۱۳۹۱/۱۰/۱۰ ۲۱:۱۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
<!doctype html>
<html>
<head>
<title>State Machine Demonstration</title>
<style type="text/css">
#opened
{
left: 10em;
top: 5em;
}
#off
{
left: 12em;
top: 15em;
}
#on
{
left: 28em;
top: 15em;
}
.w
{
width: 5em;
padding: 1em;
position: absolute;
border: 1px solid black;
z-index: 4;
border-radius: 1em;
border: 1px solid #346789;
box-shadow: 2px 2px 19px #e0e0e0;
-o-box-shadow: 2px 2px 19px #e0e0e0;
-webkit-box-shadow: 2px 2px 19px #e0e0e0;
-moz-box-shadow: 2px 2px 19px #e0e0e0;
-moz-border-radius: 0.5em;
border-radius: 0.5em;
opacity: 0.8;
filter: alpha(opacity=80);
cursor: move;
}
.ep
{
float: right;
width: 1em;
height: 1em;
background-color: #994466;
cursor: pointer;
}
.labelClass
{
font-size: 20pt;
}
</style>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery-ui.min.js"></script>
<script type="text/javascript" src="jquery.jsPlumb-all-min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
jsPlumb.importDefaults({
Endpoint: ["Dot", { radius: 5}],
HoverPaintStyle: { strokeStyle: "blue", lineWidth: 2 },
ConnectionOverlays: [
["Arrow", { location: 1, id: "arrow", length: 14, foldback: 0.8}]
]
});
jsPlumb.makeTarget($(".w"), {
dropOptions: { hoverClass: "dragHover" },
anchor: "Continuous"
});
$(".ep").each(function (i, e) {
var p = $(e).parent();
jsPlumb.makeSource($(e), {
parent: p,
anchor: "Continuous",
connector: ["StateMachine", { curviness: 20}],
connectorStyle: { strokeStyle: '#42a62c', lineWidth: 2 },
maxConnections: 2,
onMaxConnections: function (info, e) {
alert("Maximum connections (" + info.maxConnections + ") reached");
}
});
});
jsPlumb.bind("connection", function (info) {
});
jsPlumb.draggable($(".w"));
jsPlumb.connect({ source: "opened", target: "off" });
jsPlumb.connect({ source: "off", target: "on", label: "Turn On" });
jsPlumb.connect({ source: "on", target: "off", label: "Turn Off" });
});
</script>
</head>
<body>
<div class="w" id="opened">
Begin
<div class="ep">
</div>
</div>
<div class="w" id="off">
Off
<div class="ep">
</div>
</div>
<div class="w" id="on">
On
<div class="ep">
</div>
</div>
</body>
</html>
jsPlumb.bind("jsPlumbConnection", function(connectionInfo) {
// update your data model here.
});
jsPlumb.bind("jsPlumbConnectionDetached", function(connectionInfo) {
// update your data model here.
});
JSON.stringify(whole_object)
private StateMachine<string, string> stateMachine;
private StateMachineCOM source;
private string startState;
public delegate void UnhandledTriggerDelegate(State state, StateConfig trigger);
public delegate void EntryExitDelegate();
public delegate bool GuardClauseDelegate();
public string Id;
public EntryExitDelegate OnEntry = null;
public EntryExitDelegate OnExit = null;
public GuardClauseDelegate GuardClauseFromToTrigger = null;
public UnhandledTriggerDelegate OnUnhandledTrigger = null;
public StateMachineRequest(StateMachineCOM source, string startStateId)
{
this.source = source;
this.startState = startStateId;
}
public void Configure()
{
this.stateMachine = new StateMachine<string, string>(startState);
var states = source.States;
states.ForEach(state =>
{
var triggers = source.StateConfigs.AsQueryable()
.Where(config => config.FromStateId == state.StateId)
.Select(config => new {Id=config.TransitionId.ToString(), From= config.FromStateId.ToString(), To= config.ToStateId.ToString(), Permit=config.PermiteAction })
.ToList();
triggers.ForEach(trig =>
{
this.stateMachine.Configure(state.StateId.ToString())
});
});
}
public bool TryFireTrigger(string TrigerId)
{
if (!stateMachine.CanFire(TrigerId))
{
return false;
}
stateMachine.Fire(TrigerId);
return true;
}
public string GetCurrentState()
{
return this.stateMachine.State;
} this.stateMachine.Configure(state.StateId.ToString())
.OnEntry(() => { if (state.OnEnter) OnEntry(trig.Id);})
.OnExit(() => { if (state.OnExit) OnExit(trig.Id); })
.PermitIf(trig.From, trig.To, () => { if (trig.Permit) return GuardClauseFromToTrigger(); return true; }); public class BlogPostStateMachine
{
// .... مثال قسمت دوم
} StateMachineRequest smr = new StateMachineRequest(smc, startId);
smr.Configure(); var smr = new StateMachineRequest(workflowData, startId);
smr.GuardClauseFromToTrigger = new StateMachineRequest.GuardClauseDelegate(this.OnFromStateToState);
smr.OnEntry = new StateMachineRequest.EntryExitDelegate(this.OnEntryState);
smr.OnExit = new StateMachineRequest.EntryExitDelegate(this.OnExitState);
smr.Configure();
public bool OnFromStateToState(string id)
{
// TODO check can go to next state
return true;
}
public void OnEntryState(string stateId)
{
// TODO
}
public void OnExitState(string stateId)
{
// TODO save data + save state + send an email ,Etc
}