Skip to content

Instantly share code, notes, and snippets.

@ozkansari
Created June 6, 2012 12:53
Show Gist options
  • Save ozkansari/2881653 to your computer and use it in GitHub Desktop.
Save ozkansari/2881653 to your computer and use it in GitHub Desktop.
Atm Status Finite State Machine Example using Apache Commons SCXML Library
<scxml initial="idle" name="atm.connRestored" version="0.9"
xmlns="http://www.w3.org/2005/07/scxml">
<state id="idle">
<transition event="atm.connected" target="loading"></transition>
</state>
<state id="loading">
<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">
<transition event="atm.shutdown" target="outOfService"></transition>
<transition event="atm.connLost" target="disconnected"></transition>
</state>
<state id="outOfService">
<transition event="atm.startup" target="inService"></transition>
<transition event="atm.connLost" target="disconnected"></transition>
</state>
<state id="disconnected">
<transition event="atm.connRestored" target="inService"></transition>
</state>
</scxml>
package net.javafun.example.atmstatusfsm;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
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;
/**
* Atm Status Change GUI
*
* @author ozkansari.com
*
*/
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();
setupUI();
}
@SuppressWarnings("deprecation")
private void 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() {
eventComboBox.removeAllItems();
List transitionList = atmStatusFSM.getCurrentState().getTransitionsList();
for (Transition transition : transitionList) {
eventComboBox.addItem(transition.getEvent() );
}
}
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if(command.equals("FIRE_EVENT")) {
checkAndFireEvent();
}
}
private boolean 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;
}
}
package net.javafun.example.atmstatusfsm;
/**
* Atm Status Change Events
*
* @author ozkansari.com
*
*/
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);
}
}
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
*
* @see Apache Commons Scxml Library
* @author ozkansari.com
*
*/
public class AtmStatusFSM extends AbstractStateMachine {
/**
* State Machine uses this scmxml config file
*/
private static final String SCXML_CONFIG_ATM_STATUS = "net/javafun/example/atmstatusfsm/atm_status.xml";
/* CONSTRUCTOR(S) */
public AtmStatusFSM() {
super(AtmStatusFSM.class.getClassLoader().getResource(SCXML_CONFIG_ATM_STATUS));
}
/* HELPER METHOD(S) */
/*
* Fire the event
*/
public void firePreDefinedEvent(AtmStatusEventEnum eventEnum){
System.out.println("EVENT: " + eventEnum);
this.fireEvent(eventEnum.getEventName());
}
public void callState(String name){
this.invoke(name);
}
/*
* Get current state ID as string
*/
public String getCurrentStateId() {
Set states = getEngine().getCurrentStatus().getStates();
State state = (State) states.iterator().next();
return state.getId();
}
/*
* Get current state as apache's State object
*/
public State getCurrentState() {
Set states = getEngine().getCurrentStatus().getStates();
return ( (State) states.iterator().next());
}
/*
* Get events belongs to current status of the FSM
*/
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");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment