1, Introduction
1.1 introduction to SMC
SMC is a state machine software code generation tool developed in Java. SMC supports a variety of development languages: C, JavaScript, Python, C + +, Lua, Ruby, c#, Objective-C, Scala, Groovy, Perl, TCL, Java, PHP and VB Net, and what we need to do is to complete one sm's script and the principal class that owns these states.
the principle of using finite state machine to control the behavior of objects is to use polymorphism. We often write our own code, which requires a lot of space. In case we need to add one or more states, it will be troublesome to maintain ourselves. SMC tool can help us solve this problem.
SMC can generate all state classes and state machine classes required by the finite state machine through a configuration file, and also includes the transformation logic between all States.
1.2 environmental preparation
let's take the java language as an example.
before using this tool, we need JDK environment. The latest version of SMC supports jdk1 7. Previous versions of SMC support jdk1 6. If there is no problem in the middle, the JDK version on the computer must correspond to the JDK version of SMC.
smc download address: http://sourceforge.net/projects/smc/files/.
2, smc file format description
%class Class of state machine %package The package in which the class is located %access The accessibility level of the generated class %start Specifies the start state of the state machine %map Name of the state machine %%...%%:This pair%%The middle defines various state classes and various behaviors of states. Format description is as follows:
Note: the sm file name needs to be the same as The% class class name specified in the sm file is the same
Start --Status 1 (name can be customized) { DoStart --Do Status Name: execution status 1 State2–After executing state 1, jump to this state(Status 2) {method1();}–Functions to be implemented when executing state 1 } State2-Status 2 { DoState2 [ctxt.isSuccessState2()== true] – ctxt:Context, entity class CoreSchMatch in isSuccessState2()The return value of the function is true Perform this function when State3 { notifyClientState2Ok(); } DoState2 [ctxt.isSuccessState2()==== false] – ctxt:Context, entity class CoreSchMatch in isSuccessState2()The return value of the function is false Perform this function when State2Fail{notifyClientState2Fail();} } State3 { DoState3 nil{method3();releaseStm();}–Indicates emptying resources; nli-End state } State2Fail { DoState2Fail nil{releaseStm();}–Indicates emptying resources; nli-End state } Default –With its own state, load all actions defined above { DoStart nil {} DoState2 nil {} DoState3 nil {} DoState2Fail nil {} }
3, java - smc code generation process
3.1 java environment
1. Create java project;
2. Import jar package: SMC jar
3. Create: schmatchstate SM file
3.2 writing smc documents
a simple state machine is designed below. When the program is initialized, it enters the initial state of "start"; When a signal is received in the "start" initial state, it enters the "busy" state; when a "special" signal is received in the "busy" state, it enters the "idle" state; when a "exception" signal is received in the "busy" state, it enters the "stop" exit state.
To implement this state machine SM script we named it schmatchstate sm,
The specific script is as follows:
%{ %} %class SchMatchState %package com.math.sch %start SchMatchStateMap::Start %map SchMatchStateMap %% Start { DoStart Busy{state2Busy();} } Busy { DoBusy [ctxt.isSpecialState() == true] Idle{idleProcess();} DoBusy [ctxt.isSpecialState() == false] Stop{stopProcess();} } Idle{ DoIdle nil {release();} } Stop{ DoStop nil {release();} } Default { DoStart nil {} DoBusy nil {} DoIdle nil {} DoStop nil {} } %%
3.3 write batch file: runsmsch bat
1. Create file: runsmsch bat
Document content:
java -jar Smc.jar -java -g -d ./ The state machine that needs to be processed sm file name
Example:
java -jar Smc.jar -java -g -d ./ SchMatchState.sm
2. Execute runsmsch Bat command:
(1) Window+R, open cmd command line window;
(2) On the command line, enter SMC Location of jar package:
(3) Execute runsmsch Command in bat file:
Note: the sm file name needs to be the same as The% class class name specified in the sm file is the same. The exception is generated due to the different names on my side:
Execution process:
3. After execution, the program will automatically create the SchMatchStateContext class, which defines the whole process of the state machine.
4. All function functions defined in the state machine will be automatically created in the SchMatchState class, and the corresponding functions can be implemented according to the actual needs.
if the SchMatchState class is not generated, the corresponding classes and functions can be generated in the SchMatchStateContext class according to the prompts, and the corresponding function functions can be realized.
5. Implement the startCoreSchMatch() function in the SchMatchState class, which is used to start the state machine -- > and execute all action functions:
public void startCoreSchMatch(){ fsm.enterStartState(); fsm.DoStart(); fsm.DoBusy(); fsm.DoIdle(); fsm.DoStop(); }
3.4 java code
3.4.1 SchMatchState class
package com.math.sch; public class SchMatchState { private SchMatchStateContext fsm; private String currentState = "start"; public static void main(String[] args) { new SchMatchState().start(); } public void start(){ System.out.println("State machine start: "); this.fsm = new SchMatchStateContext(this); startCoreSchMatch(); } public void startCoreSchMatch(){ fsm.enterStartState(); fsm.DoStart(); fsm.DoBusy(); fsm.DoIdle(); fsm.DoStop(); } public void state2Busy() { this.currentState = "busy"; System.out.println("Current status:"+currentState+" -> Transition status to: busy"); } public boolean isSpecialState() { if("busy".equals(currentState)){ this.currentState = "Special"; return true; } return false; } public void idleProcess() { System.out.println("Current status:"+currentState+" -> Transition status to: idle"); this.currentState = "stop"; } public void stopProcess() { this.currentState = "stop"; System.out.println("Current status:"+currentState); } public void release() { this.currentState = "start"; System.out.println("The state machine ends and empties"); } }
Output of execution results:
Conclusion: FSM is a fixed paradigm, so using tools to help us realize it can reduce the chance of making mistakes. The input file is: entity sm. We focus on business logic, so smc code related to state can be generated for us.
3.4.2 SchMatchStateContext class
/* * ex: set ro: * DO NOT EDIT. * generated by smc (http://smc.sourceforge.net/) * from file : SchMatchState.sm */ package com.math.sch; import java.io.PrintStream; public class SchMatchStateContext extends statemap.FSMContext { //--------------------------------------------------------------- // Member methods. // public SchMatchStateContext(SchMatchState owner) { super (SchMatchStateMap.Start); _owner = owner; } public SchMatchStateContext(SchMatchState owner, SchMatchStateState initState) { super (initState); _owner = owner; } public void enterStartState() { getState().Entry(this); return; } public void DoBusy() { _transition = "DoBusy"; getState().DoBusy(this); _transition = ""; return; } public void DoIdle() { _transition = "DoIdle"; getState().DoIdle(this); _transition = ""; return; } public void DoStart() { _transition = "DoStart"; getState().DoStart(this); _transition = ""; return; } public void DoStop() { _transition = "DoStop"; getState().DoStop(this); _transition = ""; return; } public SchMatchStateState getState() throws statemap.StateUndefinedException { if (_state == null) { throw( new statemap.StateUndefinedException()); } return ((SchMatchStateState) _state); } protected SchMatchState getOwner() { return (_owner); } public void setOwner(SchMatchState owner) { if (owner == null) { throw ( new NullPointerException( "null owner")); } else { _owner = owner; } return; } //--------------------------------------------------------------- // Member data. // transient private SchMatchState _owner; //--------------------------------------------------------------- // Inner classes. // public static abstract class SchMatchStateState extends statemap.State { //----------------------------------------------------------- // Member methods. // protected SchMatchStateState(String name, int id) { super (name, id); } protected void Entry(SchMatchStateContext context) {} protected void Exit(SchMatchStateContext context) {} protected void DoBusy(SchMatchStateContext context) { Default(context); } protected void DoIdle(SchMatchStateContext context) { Default(context); } protected void DoStart(SchMatchStateContext context) { Default(context); } protected void DoStop(SchMatchStateContext context) { Default(context); } protected void Default(SchMatchStateContext context) { if (context.getDebugFlag() == true) { PrintStream str = context.getDebugStream(); str.println( "TRANSITION : Default"); } throw ( new statemap.TransitionUndefinedException( "State: " + context.getState().getName() + ", Transition: " + context.getTransition())); } //----------------------------------------------------------- // Member data. // } /* package */ static abstract class SchMatchStateMap { //----------------------------------------------------------- // Member methods. // //----------------------------------------------------------- // Member data. // //------------------------------------------------------- // Constants. // public static final SchMatchStateMap_Default.SchMatchStateMap_Start Start = new SchMatchStateMap_Default.SchMatchStateMap_Start("SchMatchStateMap.Start", 0); public static final SchMatchStateMap_Default.SchMatchStateMap_Busy Busy = new SchMatchStateMap_Default.SchMatchStateMap_Busy("SchMatchStateMap.Busy", 1); public static final SchMatchStateMap_Default.SchMatchStateMap_Idle Idle = new SchMatchStateMap_Default.SchMatchStateMap_Idle("SchMatchStateMap.Idle", 2); public static final SchMatchStateMap_Default.SchMatchStateMap_Stop Stop = new SchMatchStateMap_Default.SchMatchStateMap_Stop("SchMatchStateMap.Stop", 3); private static final SchMatchStateMap_Default Default = new SchMatchStateMap_Default("SchMatchStateMap.Default", -1); } protected static class SchMatchStateMap_Default extends SchMatchStateState { //----------------------------------------------------------- // Member methods. // protected SchMatchStateMap_Default(String name, int id) { super (name, id); } protected void DoStart(SchMatchStateContext context) { if (context.getDebugFlag() == true) { PrintStream str = context.getDebugStream(); str.println("TRANSITION : SchMatchStateMap.Default.DoStart()"); } return; } protected void DoBusy(SchMatchStateContext context) { if (context.getDebugFlag() == true) { PrintStream str = context.getDebugStream(); str.println("TRANSITION : SchMatchStateMap.Default.DoBusy()"); } return; } protected void DoIdle(SchMatchStateContext context) { if (context.getDebugFlag() == true) { PrintStream str = context.getDebugStream(); str.println("TRANSITION : SchMatchStateMap.Default.DoIdle()"); } return; } protected void DoStop(SchMatchStateContext context) { if (context.getDebugFlag() == true) { PrintStream str = context.getDebugStream(); str.println("TRANSITION : SchMatchStateMap.Default.DoStop()"); } return; } //----------------------------------------------------------- // Inner classse. // private static final class SchMatchStateMap_Start extends SchMatchStateMap_Default { //------------------------------------------------------- // Member methods. // private SchMatchStateMap_Start(String name, int id) { super (name, id); } protected void DoStart(SchMatchStateContext context) { SchMatchState ctxt = context.getOwner(); if (context.getDebugFlag() == true) { PrintStream str = context.getDebugStream(); str.println("TRANSITION : SchMatchStateMap.Start.DoStart()"); } (context.getState()).Exit(context); context.clearState(); try { ctxt.state2Busy(); } finally { context.setState(SchMatchStateMap.Busy); (context.getState()).Entry(context); } return; } //------------------------------------------------------- // Member data. // } private static final class SchMatchStateMap_Busy extends SchMatchStateMap_Default { //------------------------------------------------------- // Member methods. // private SchMatchStateMap_Busy(String name, int id) { super (name, id); } protected void DoBusy(SchMatchStateContext context) { SchMatchState ctxt = context.getOwner(); if (context.getDebugFlag() == true) { PrintStream str = context.getDebugStream(); str.println("TRANSITION : SchMatchStateMap.Busy.DoBusy()"); } if (ctxt.isSpecialState() == true) { (context.getState()).Exit(context); context.clearState(); try { ctxt.idleProcess(); } finally { context.setState(SchMatchStateMap.Idle); (context.getState()).Entry(context); } } else if (ctxt.isSpecialState() == false) { (context.getState()).Exit(context); context.clearState(); try { ctxt.stopProcess(); } finally { context.setState(SchMatchStateMap.Stop); (context.getState()).Entry(context); } } else { super.DoBusy(context); } return; } //------------------------------------------------------- // Member data. // } private static final class SchMatchStateMap_Idle extends SchMatchStateMap_Default { //------------------------------------------------------- // Member methods. // private SchMatchStateMap_Idle(String name, int id) { super (name, id); } protected void DoIdle(SchMatchStateContext context) { SchMatchState ctxt = context.getOwner(); if (context.getDebugFlag() == true) { PrintStream str = context.getDebugStream(); str.println("TRANSITION : SchMatchStateMap.Idle.DoIdle()"); } SchMatchStateState endState = context.getState(); context.clearState(); try { ctxt.release(); } finally { context.setState(endState); } return; } //------------------------------------------------------- // Member data. // } private static final class SchMatchStateMap_Stop extends SchMatchStateMap_Default { //------------------------------------------------------- // Member methods. // private SchMatchStateMap_Stop(String name, int id) { super (name, id); } protected void DoStop(SchMatchStateContext context) { SchMatchState ctxt = context.getOwner(); if (context.getDebugFlag() == true) { PrintStream str = context.getDebugStream(); str.println("TRANSITION : SchMatchStateMap.Stop.DoStop()"); } SchMatchStateState endState = context.getState(); context.clearState(); try { ctxt.release(); } finally { context.setState(endState); } return; } //------------------------------------------------------- // Member data. // } //----------------------------------------------------------- // Member data. // } } /* * Local variables: * buffer-read-only: t * End: */