Designing state machines using State Map Compiler (SMC)

A state machine is an entity, which handles the states of an entity by taking it thru various states, handles states’ entry – exit actions, controls the state transitions & transition actions.

Using state map compiler:
State map compiler helps us to design state machines easily. SMC has a well-defined format to write states, transitions & actions. From a programmer point-of-view, we can say that the state machine is a program which handles different states of a business object.

Steps:
1. Decide the states, actions & transitions
2. Write the .sm file (the .sm file overview)
3. Write the .java file corresponding to the business object.

This should contain the implementations for all actions (entry, exit & transition actions). Name of the .java file should match to that of the .sm file.

4. Compile the .sm file.

Compilation command: java -jar smc.jar -java MySmFile.sm
SMC can generate state machines for C, C++, C#, Java, Lua, Objective-C, Perl, Python, Ruby, Tcl and VB.net. Sounds cool right?

5. If the .sm file doesn’t have any error, we will get a context file with name MySmFileContext.java. This java file is the java equivalent of the .sm file.

Sample 1: TestSm.sm

%class 		TestSm		// Business object class name 
%package 	         subin.rnd.sm	// package name 
%access		package 
%start 		Sm::Init	         	// initial state. map::state name 
 
%map 		Sm		// map 
%% 
	Init 
	Entry 
	{ 
		doPrint("Entry"); 
	} 
	Exit 
	{ 
		doPrint("Exit"); 
	}  

	{ 
		next Finish	// transition "next" 
		{ 
			doPrint("Transition"); 
		} 
	}  

	Finish 
	Entry 
	{ 
		doPrint("Finished"); 
	} 
	{ 
	}  

%%

Note:
The transition can be based on a guard condition too. In the above example there is no such condition which restrict the state machine from transiting to a different state. See the example below:

next [ctxt.isConditionOneTrue()] 
State1 
{ 
    doSomeThing(); 
}  

next [!ctxt.isConditionOneTrue() && ctxt.isConditionTwoTrue()] 
State2 
{ 
    doSomeThing(); 
    doSomeThingElseToo(); 
}

next State3 
{ 
    doItIfEveryThingElseFails(); 
}

Here ctxt stands for the business object and we can’t use any other name for that. The business object should contain the implementation for these guard conditions. The guard conditions can be some static methods too. The order by which we specified the condition is also important. The condition-less transition takes place if everything else fails & it should be specified at the end. Otherwise whenever the state machine finds it, transition will occur and it wont check for following conditions.

Sample 2: TestSm.java (Business Object)

package subin.rnd.sm;  

public class TestSm 
{ 
    public static void main(String[] args) 
    { 
        // Transition from the initial state. 
        // When the business object is created, the entry actions 
        // in the initial state will get executed. 
        new TestSm().next(); 
    }  

    // Java equivalent of .sm 
    // Business object should contain an instance of it. 
    TestSmContext context;  

    public TestSm() 
    { 
        // Context should take the business object as an 
        // argument in its constructor. 
        this.context = new TestSmContext(this); 
    }  

    // Implementation of the action doPrint(). 
    void doPrint(String aString) 
    { 
        System.out.println(aString); 
    }  

    // Handling the state transition. 
    // For each transition, the business object should contain 
    // an equivalent method which contains only one line; 
    // a corresponding method call to the context object. 
    void next() 
    { 
        this.context.next(); 
    }  

}

Output:

Entry 
Exit 
Transition 
Finished

Useful links:
State machine: http://en.wikipedia.org/wiki/Finite_state_machine
SMC home page: http://smc.sourceforge.net/
SMC download page: http://sourceforge.net/projects/smc

Advertisements