Apache SCXML 状态机

来源:互联网 发布:time machine 恢复 mac 编辑:程序博客网 时间:2024/06/05 18:40

http://www.javacodegeeks.com/2012/06/apache-commons-scxml-finite-state.html

For full source code visit https://github.com/ozkansari/atmstatemachine

Apache Commons SCXML: Finite State Machine Implementation



atm_status.xml

<pre name="code" class="html"><scxml initial="idle" name="atm.connRestored" version="0.9" xmlns="http://www.w3.org/2005/07/scxml"><!--   node-size-and-position x=0.0 y=0.0 w=1050.0 h=590.0  --> <state id="idle"><!--   node-size-and-position x=40.0 y=220.0 w=100.0 h=100.0  -->  <transition event="atm.connected" target="loading"></transition> </state> <state id="loading"><!--   node-size-and-position x=300.0 y=220.0 w=100.0 h=100.0  -->  <transition event="atm.loadSuccess" target="inService"></transition>  <transition event="atm.connClosed" target="disconnected"></transition>  <transition event="atm.loadFail" target="outOfService"></transition> </state> <state id="inService"><!--   node-size-and-position x=570.0 y=30.0 w=100.0 h=100.0  -->  <transition event="atm.shutdown" target="outOfService"><!--   edge-path [outOfService]  x=580.0 y=190.0 pointx=0.0 pointy=3.0 offsetx=-1.0 offsety=-2.0  --></transition>  <transition event="atm.connLost" target="disconnected"><!--   edge-path [disconnected]  x=757.0 y=270.0 pointx=0.0 pointy=-12.0 offsetx=13.0 offsety=0.0  --></transition> </state> <state id="outOfService"><!--   node-size-and-position x=570.0 y=260.0 w=100.0 h=100.0  -->  <transition event="atm.startup" target="inService"><!--   edge-path [inService]  x=660.0 y=190.0  --></transition>  <transition event="atm.connLost" target="disconnected"></transition> </state> <state id="disconnected"><!--   node-size-and-position x=570.0 y=450.0 w=100.0 h=100.0  -->  <transition event="atm.connRestored" target="inService"><!--   edge-path [inService]  x=860.0 y=275.0  --></transition> </state></scxml>



AtmStatusEventEnum.java

package net.javafun.example.atmstatusfsm;public enum AtmStatusEventEnum {CONNECT("atm.connected"), CONNECTION_CLOSED("atm.connClosed"),CONNECTION_LOST("atm.connLost"),CONNECTION_RESTORED("atm.connRestored"),LOAD_SUCCESS("atm.loadSuccess"),LOAD_FAIL("atm.loadFail"),SHUTDOWN("atm.shutdown"),STARTUP("atm.startup"),;private final String eventName;private AtmStatusEventEnum(String eventName) {this.eventName = eventName;}public String getEventName() {return eventName;}public static String getNamesAsCsv(){StringBuilder sb = new StringBuilder();for (AtmStatusEventEnum e : AtmStatusEventEnum.values()) {sb.append(e.name());sb.append(",");}return sb.substring(0,sb.length()-2);}}

AtmStatusFSM.java

package net.javafun.example.atmstatusfsm;import java.util.Collection;import java.util.Set;import org.apache.commons.scxml.env.AbstractStateMachine;import org.apache.commons.scxml.model.State;/** * Atm Status Finite State Machine Example *  * @see <a href="http://commons.apache.org/scxml/index.html "> Apache Commons Scxml Library </a> * @author ozkans * */public class AtmStatusFSM extends AbstractStateMachine {/** * State Machine uses this scmxml config file *///private static final String SCXML_CONFIG_ATM_STATUS = "net/javafun/example/atmfsm/atm_status.xml";private static final String SCXML_CONFIG_ATM_STATUS = "atm_status.xml";/* ------------------------------------------------------------------------ *//* CONSTRUCTOR(S) *//* ------------------------------------------------------------------------ */public AtmStatusFSM() {        super(AtmStatusFSM.class.getClassLoader().getResource(SCXML_CONFIG_ATM_STATUS));}/* ------------------------------------------------------------------------ *//* HELPER METHOD(S) *//* ------------------------------------------------------------------------ */public void firePreDefinedEvent(AtmStatusEventEnum eventEnum){System.out.println("EVENT: " + eventEnum);this.fireEvent(eventEnum.getEventName());}public void callState(String name){this.invoke(name);}public String getCurrentStateId() {Set<?> states = getEngine().getCurrentStatus().getStates();State state = (State) states.iterator().next();return state.getId();}public State getCurrentState() {Set<?> states = getEngine().getCurrentStatus().getStates();return ( (State) states.iterator().next());}public Collection<?> getCurrentStateEvents() {return getEngine().getCurrentStatus().getEvents();}/* ------------------------------------------------------------------------ */// STATES// // Each method below is the activity corresponding to a state in the// SCXML document (see class constructor for pointer to the document)./* ------------------------------------------------------------------------ */ public void idle() {System.out.println("STATE: idle 被触发"); }  public void loading() { System.out.println("STATE: loading 被触发"); }  public void inService() { System.out.println("STATE: inService 被触发"); }  public void outOfService() { System.out.println("STATE: outOfService 被触发"); }  public void disconnected() { System.out.println("STATE: disconnected 被触发"); }}

用Java JFrame UI测试:

package net.javafun.example.atmstatusfsm;import java.awt.BorderLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.List;import java.util.Map;import javax.swing.JButton;import javax.swing.JComboBox;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import org.apache.commons.scxml.model.Transition;import org.apache.commons.scxml.model.TransitionTarget;public class AtmDisplay extends JFrame implements ActionListener {private static final long serialVersionUID = -5083315372455956151L;private AtmStatusFSM atmStatusFSM;private JButton button;private JLabel state;private JComboBox eventComboBox = new JComboBox();public static void main(String[] args) {new AtmDisplay();}public AtmDisplay() {super("ATM Display Demo");atmStatusFSM = new AtmStatusFSM();/* //仅用作测试设置初始化状态,不设置的话使用atm_status.xml里面默认的初始状态@SuppressWarnings("unchecked")Map<String, TransitionTarget> mapTg = atmStatusFSM.getEngine().getStateMachine().getTargets();for(Map.Entry<String, TransitionTarget> entry : mapTg.entrySet()){System.out.println(entry.getKey() + " ==== " + entry.getValue().getId());}TransitionTarget tsTarget =  mapTg.get("inService");atmStatusFSM.getEngine().getStateMachine().setInitialTarget(tsTarget); //设置初始状态为inServiceatmStatusFSM.resetMachine();atmStatusFSM.fireEvent(AtmStatusEventEnum.SHUTDOWN.getEventName());*/setupUI();}@SuppressWarnings("deprecation")private void setupUI() {System.out.println("setupUI");JPanel panel = new JPanel();panel.setLayout(new BorderLayout());setContentPane(panel);button = makeButton("FIRE_EVENT", AtmStatusEventEnum.getNamesAsCsv(), "Submit" );panel.add(button, BorderLayout.CENTER);state = new JLabel(atmStatusFSM.getCurrentStateId());panel.add(state, BorderLayout.SOUTH);initEvents();panel.add(eventComboBox, BorderLayout.NORTH);pack();setLocation(200, 200);setResizable(false);setSize(300, 125);show();setDefaultCloseOperation(EXIT_ON_CLOSE);}@SuppressWarnings("unchecked")private void initEvents() {System.out.println("initEvents");eventComboBox.removeAllItems();List<Transition> transitionList = atmStatusFSM.getCurrentState().getTransitionsList();for (Transition transition : transitionList) {eventComboBox.addItem(transition.getEvent() );}}public void actionPerformed(ActionEvent e) {System.out.println("actionPerformed");String command = e.getActionCommand();if(command.equals("FIRE_EVENT")) {checkAndFireEvent();}}private boolean checkAndFireEvent() {System.out.println("checkAndFireEvent");atmStatusFSM.fireEvent(eventComboBox.getSelectedItem().toString());state.setText(atmStatusFSM.getCurrentStateId());initEvents();repaint();return true;}private JButton makeButton(final String actionCommand, final String toolTipText, final String altText) {JButton button = new JButton(altText);button.setActionCommand(actionCommand);button.setToolTipText(toolTipText);button.addActionListener(this);button.setOpaque(false);return button;}}


不用UI测试:

package net.javafun.example.atmstatusfsm;import java.util.List;import java.util.Map;import org.apache.commons.scxml.model.Transition;import org.apache.commons.scxml.model.TransitionTarget;public class TestAtm { public static void main(String[] args) {AtmStatusFSM atmStatusFSM = new AtmStatusFSM();setInitStatus(atmStatusFSM);  //仅用作测试设置初始化状态,不设置的话使用atm_status.xml里面默认的初始状态show(atmStatusFSM);show2(atmStatusFSM);//atmStatusFSM.fireEvent(AtmStatusEventEnum.CONNECT.getEventName()); //如果当前状态下没有该Event,那么不会出错,也不会fireEventatmStatusFSM.fireEvent(AtmStatusEventEnum.SHUTDOWN.getEventName());//show2(atmStatusFSM);}private static void setInitStatus(AtmStatusFSM atmStatusFSM) {System.out.println("手动设置初始状态:");Map<String, TransitionTarget> mapTg = atmStatusFSM.getEngine().getStateMachine().getTargets();TransitionTarget tsTarget =  mapTg.get("inService");atmStatusFSM.getEngine().getStateMachine().setInitialTarget(tsTarget);atmStatusFSM.resetMachine();System.out.println();}@SuppressWarnings("unchecked")public static void show(AtmStatusFSM atmStatusFSM){System.out.println("列出所有targets:");Map<String,TransitionTarget> mapTg = atmStatusFSM.getEngine().getStateMachine().getTargets();for(Map.Entry<String, TransitionTarget> entry : mapTg.entrySet()){System.out.println(entry.getKey() + " ==== " + entry.getValue().getId());}System.out.println("列出所有States:");Map<String,TransitionTarget> mapSt = atmStatusFSM.getEngine().getStateMachine().getStates();for(Map.Entry<String, TransitionTarget> entry : mapSt.entrySet()){System.out.println(entry.getKey() + " ==== " + entry.getValue().getId());}System.out.println();}public static void show2(AtmStatusFSM atmStatusFSM){System.out.println("列出当前状态及其所有target:");String currentStatus = atmStatusFSM.getCurrentStateId();System.out.println("currentStatus: " + currentStatus);System.out.println("currentStatus's all events: " );    //List<String> list =atmStatusFSM.getCurrentStateEvents();List<Transition> transitionList = atmStatusFSM.getCurrentState().getTransitionsList();for (Transition transition : transitionList) {System.out.println(" " + transition.getEvent());}System.out.println();}}










0 0