dynamic tools for .net developers™  LaMarvin Home
home » constable » faq » state machine

Using CAZE as a finite state machine (FSM)

At its core, CAZE is an implementation of a finite state machine (FSM, also called a finite automaton): However, in order to use CAZE as a finite state machine, you should carefully consider the following CAZE features that don't have counterparts in the FSM world:

Principals and roles

With CAZE, you'll represent state transitions with action authorization rules. Because an ActionRule has to be associated with a role, you'll have to add at least one role to the AuthorizationPolicy.Roles collection. The role associated with an action rule is used by CAZE to determine whether the rule is executable (i.e. whether the state transition defined by the rule is enabled). If the AuthorizationPolicy.CurrentPrincipal is member of the role, the rule is executable (the state transition is enabled). Otherwise, the rule isn't executable (from the FSM perspective, the state transition doesn't exist). When using CAZE as a FSM, you obviously don't want the current principal to influence the set of available state transition. The best way to do it is to use the DynamicRole class:
  1. Create an instance of the DynamicRole class and make sure the DynamicRole.IsMemberResult property is set to true.
  2. Add the instance to the AuthorizationPolicy.Roles collection.
  3. Associate each ActionRule (state transition) with the DynamicRole instance you've added in the previous step.
Another approach you can use to ensure all action rules are allowed is to derive from the AuthorizationPolicy class and override the AuthorizationPolicy.IsRoleMember method in such a way that it always returns true.

The sample code at the end of this page illustrates both approaches.

Initial state

The CAZE authorization policy doesn't have a notion of an initial or a final state. All states are equivalent in this regard and you'll have to make sure that after populating an instance of the AuthorizationPolicy class with states, you set the AuthorizationPolicy.CurrentState property to the desired initial state.

State transitions

In CAZE, state transitions are invoked by executing actions. The ActionRule class associates an Action with two states:
  • The ActionRule.State property determines the state in which the action can be executed (the action represents the input symbol in FSM parlance).
  • The ActionRule.TargetState property determines the target state in which the state machine resides after the action is executed.

Sample code

The following code defines a simple voting state machine and illustrates how to actually code around the above described CAZE features:
[Visual Basic]
' Let's name the authorization policy to
' make the FSM concepts more clear.
Dim fsmVoting As AuthorizationPolicy = New AuthorizationPolicy

' Add a DynamicRole instance making sure that any
' principal is member of the role. This will effectively 
' make the policy (state-machine) principal agnostic.
' Note that an empty string is a valid role identifier).
fsmVoting.Roles.Add(New DynamicRole("", True))

' Define the states of the machine.
fsmVoting.States.AddNew("NotRunning")
fsmVoting.States.AddNew("InProgress")
fsmVoting.States.AddNew("Suspended")
fsmVoting.States.AddNew("Stopped")

' Define the actions (the machine's alphabet).
fsmVoting.Actions.AddNew("Start")
fsmVoting.Actions.AddNew("Stop")
fsmVoting.Actions.AddNew("Suspend")
fsmVoting.Actions.AddNew("Resume")

' Define the action rules, i.e. state transitions. 
' Note: we're associating the rules with the previously
' defined DynamiRole with 'everyone' membership.
fsmVoting.ActionRules.AddNew("Start", "", "NotRunning", "InProgress")
fsmVoting.ActionRules.AddNew("Stop", "", "InProgress", "Stopped")
fsmVoting.ActionRules.AddNew("Suspend", "", "InProgress", "Suspended")
fsmVoting.ActionRules.AddNew("Resume", "", "Suspended", "InProgress")

' The first state added to the States collection is 
' used as the initial value of the CurrentState property.
' Because it is the "NotRunning" state, we don't have to
' set the initial state explicitly. If the FSM should "start"
' with a different initial state, we'd use code like this:
' fsmVoting.CurrentState = fsmVoting.States["InProgress"];

' Now we're ready to invoke state transitions. We do it
' by executing actions; the TargetState property of the 
' action determines the new state of the state machine.
Debug.Assert(fsmVoting.IsActionExecutable("Start"))
fsmVoting.ExecuteAction("Start")
Debug.Assert(fsmVoting.CurrentState.Id = "InProgress")

Debug.Assert(fsmVoting.IsActionExecutable("Suspend"))
fsmVoting.ExecuteAction("Suspend")
Debug.Assert(fsmVoting.CurrentState.Id = "Suspended")

Debug.Assert(fsmVoting.IsActionExecutable("Resume"))
fsmVoting.ExecuteAction("Resume")
Debug.Assert(fsmVoting.CurrentState.Id = "InProgress")

Debug.Assert(fsmVoting.IsActionExecutable("Stop"))
fsmVoting.ExecuteAction("Stop")
Debug.Assert(fsmVoting.CurrentState.Id = "Stopped")

[C#]
// Let's name the authorization policy to
// make the FSM concepts more clear.
AuthorizationPolicy fsmVoting = new AuthorizationPolicy();

// Add a DynamicRole instance making sure that any
// principal is member of the role. This will effectively 
// make the policy (state-machine) principal agnostic.
// Note that an empty string is a valid role identifier).
fsmVoting.Roles.Add(new DynamicRole("", true));

// Define the states of the machine.
fsmVoting.States.AddNew("NotRunning");
fsmVoting.States.AddNew("InProgress");
fsmVoting.States.AddNew("Suspended");
fsmVoting.States.AddNew("Stopped");

// Define the actions (the machine's alphabet).
fsmVoting.Actions.AddNew("Start");
fsmVoting.Actions.AddNew("Stop");
fsmVoting.Actions.AddNew("Suspend");
fsmVoting.Actions.AddNew("Resume");

// Define the action rules, i.e. state transitions. 
// Note: we're associating the rules with the previously
// defined DynamiRole with 'everyone' membership.
fsmVoting.ActionRules.AddNew("Start", "", "NotRunning", "InProgress");
fsmVoting.ActionRules.AddNew("Stop", "", "InProgress", "Stopped");
fsmVoting.ActionRules.AddNew("Suspend", "", "InProgress", "Suspended");
fsmVoting.ActionRules.AddNew("Resume", "", "Suspended", "InProgress");

// The first state added to the States collection is 
// used as the initial value of the CurrentState property.
// Because it is the "NotRunning" state, we don't have to
// set the initial state explicitly. If the FSM should "start"
// with a different initial state, we'd use code like this:
// fsmVoting.CurrentState = fsmVoting.States["InProgress"];

// Now we're ready to invoke state transitions. We do it
// by executing actions; the TargetState property of the 
// action determines the new state of the state machine.
Debug.Assert(fsmVoting.IsActionExecutable("Start"));
fsmVoting.ExecuteAction("Start");
Debug.Assert(fsmVoting.CurrentState.Id == "InProgress");

Debug.Assert(fsmVoting.IsActionExecutable("Suspend"));
fsmVoting.ExecuteAction("Suspend");
Debug.Assert(fsmVoting.CurrentState.Id == "Suspended");

Debug.Assert(fsmVoting.IsActionExecutable("Resume"));
fsmVoting.ExecuteAction("Resume");
Debug.Assert(fsmVoting.CurrentState.Id == "InProgress");

Debug.Assert(fsmVoting.IsActionExecutable("Stop"));
fsmVoting.ExecuteAction("Stop");
Debug.Assert(fsmVoting.CurrentState.Id == "Stopped");
The following code illustrates how you can inherit from the AuthorizationPolicy class and override the AuthorizationPolicy.IsRoleMember method making sure that all action rules (state transitions) will be enabled regardless of the current principal:
[Visual Basic]
' <summary>
' A simple state machine (all action rules are enabled).
' </summary>
Private Class StateMachine
  Inherits AuthorizationPolicy
  ' <summary>
  ' Returns always <see langword="true"/> making the class 
  ' principal-agnostics (i.e. any principal
  ' can execute the defined actions).
  ' </summary>
  Protected Overrides Function IsRoleMember( _
    ByVal principal As IPrincipal, _
    ByVal role As Role) As Boolean
    
    Return True
  End Function
End Class

[C#]
/// <summary>
/// A simple state machine (all action rules are enabled).
/// </summary>
private class StateMachine : AuthorizationPolicy
{
  /// <summary>
  /// Returns always <see langword="true"/> making the class 
  /// principal-agnostics (i.e. any principal
  /// can execute the defined actions).
  /// </summary>
  protected override bool IsRoleMember(IPrincipal principal, Role role)
  {
    return true;
  }
}




© 2002-2007 LaMarvin. All Rights Reserved.     [Terms of use]     [Privacy] This site doesn't open new browser windows.