Mega Code Archive

 
Categories / Java / Collections Data Structure
 

The representation of a finite state machine

/*  * JBoss, Home of Professional Open Source  * Copyright 2005, JBoss Inc., and individual contributors as indicated  * by the @authors tag. See the copyright.txt in the distribution for a  * full listing of individual contributors.  *  * This is free software; you can redistribute it and/or modify it  * under the terms of the GNU Lesser General Public License as  * published by the Free Software Foundation; either version 2.1 of  * the License, or (at your option) any later version.  *  * This software is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  * Lesser General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public  * License along with this software; if not, write to the Free  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.  */ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; /**  * The representation of a finite state machine.  *   * @author Scott.Stark@jboss.org  * @version $Revision: 2787 $  */ @SuppressWarnings("unchecked") public class StateMachine implements Cloneable {   /** A description of the state machine */   private String description;   /** The set of states making up the state machine */   private HashSet states;   /** The starting state */   private State startState;   /** The current state of the state machine */   private State currentState;   /**    * Create a state machine given its states and start state.    *     * @param states -    *          Set<State> for the state machine    * @param startState -    *          the starting state    */   public StateMachine(Set states, State startState) {     this(states, startState, null);   }   /**    * Create a state machine given its states and start state.    *     * @param states -    *          Set<State> for the state machine    * @param startState -    *          the starting state    * @param description -    *          an optional description of the state machine    */   public StateMachine(Set states, State startState, String description) {     this.states = new HashSet(states);     this.startState = startState;     this.currentState = startState;     this.description = description;   }   /**    * Make a copy of the StateMachine maintaining the current state.    *     * @return a copy of the StateMachine.    */   public Object clone() {     StateMachine clone = new StateMachine(states, startState, description);     clone.currentState = currentState;     return clone;   }   /**    * Get the state machine description.    *     * @return an possibly null description.    */   public String getDescription() {     return description;   }   /**    * Get the current state of the state machine.    *     * @return the current state.    */   public State getCurrentState() {     return currentState;   }   /**    * Get the start state of the state machine.    *     * @return the start state.    */   public State getStartState() {     return startState;   }   /**    * Get the states of the state machine.    *     * @return the machine states.    */   public Set getStates() {     return states;   }   /**    * Transition to the next state given the name of a valid transition.    *     * @param actionName -    *          the name of transition that is valid for the current state.    * @return the next state    * @throws IllegalTransitionException    */   public State nextState(String actionName) throws IllegalTransitionException {     Transition t = currentState.getTransition(actionName);     if (t == null) {       String msg = "No transition for action: '" + actionName + "' from state: '"           + currentState.getName() + "'";       throw new IllegalTransitionException(msg);     }     State nextState = t.getTarget();     System.out.println("nextState(" + actionName + ") = " + nextState);     currentState = nextState;     return currentState;   }   /**    * Reset the state machine back to the start state    *     * @return the start state    */   public State reset() {     this.currentState = startState;     return currentState;   }   public String toString() {     StringBuffer tmp = new StringBuffer("StateMachine[:\n");     tmp.append("\tCurrentState: " + currentState.getName());     Iterator i = states.iterator();     while (i.hasNext()) {       tmp.append('\n').append(i.next());     }     tmp.append(']');     return tmp.toString();   } } /*  * JBoss, Home of Professional Open Source Copyright 2005, JBoss Inc., and  * individual contributors as indicated by the @authors tag. See the  * copyright.txt in the distribution for a full listing of individual  * contributors.  *   * This is free software; you can redistribute it and/or modify it under the  * terms of the GNU Lesser General Public License as published by the Free  * Software Foundation; either version 2.1 of the License, or (at your option)  * any later version.  *   * This software is distributed in the hope that it will be useful, but WITHOUT  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more  * details.  *   * You should have received a copy of the GNU Lesser General Public License  * along with this software; if not, write to the Free Software Foundation,  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF  * site: http://www.fsf.org.  */ /**  * The respresentation of a state in a state machine.  *   * @author Scott.Stark@jboss.org  * @version $Revision: 2787 $  */ @SuppressWarnings("unchecked") class State {   /** The name of the state */   private String name;   /** HashMap<String, Transition> */   private HashMap allowedTransitions = new HashMap();   /** Arbitrary state data */   private Object data;   public State(String name) {     this(name, null);   }   public State(String name, Map transitions) {     this.name = name;     if (transitions != null) {       allowedTransitions.putAll(transitions);     }   }   /**    * Get the state name.    *     * @return the name of the state.    */   public String getName() {     return name;   }   public Object getData() {     return data;   }   public void setData(Object data) {     this.data = data;   }   /**    * An accept state is indicated by no transitions    *     * @return true if this is an accept state, false otherwise.    */   public boolean isAcceptState() {     return allowedTransitions.size() == 0;   }   /**    * Add a transition to the allowed transition map.    *     * @param transition    * @return this to allow chained addTransition calls    */   public State addTransition(Transition transition) {     allowedTransitions.put(transition.getName(), transition);     return this;   }   /**    * Lookup an allowed transition given its name.    *     * @param name -    *          the name of a valid transition from this state.    * @return the valid transition if it exists, null otherwise.    */   public Transition getTransition(String name) {     Transition t = (Transition) allowedTransitions.get(name);     return t;   }   /**    * Get the Map<String, Transition> of allowed transitions for this state.    *     * @return the allowed transitions map.    */   public Map getTransitions() {     return allowedTransitions;   }   public String toString() {     StringBuffer tmp = new StringBuffer("State(name=");     tmp.append(name);     Iterator i = allowedTransitions.entrySet().iterator();     while (i.hasNext()) {       Map.Entry e = (Map.Entry) i.next();       tmp.append("\n\t on: ");       tmp.append(e.getKey());       Transition t = (Transition) e.getValue();       tmp.append(" go to: ");       tmp.append(t.getTarget().getName());     }     tmp.append(')');     return tmp.toString();   } } /*  * JBoss, Home of Professional Open Source Copyright 2005, JBoss Inc., and  * individual contributors as indicated by the @authors tag. See the  * copyright.txt in the distribution for a full listing of individual  * contributors.  *   * This is free software; you can redistribute it and/or modify it under the  * terms of the GNU Lesser General Public License as published by the Free  * Software Foundation; either version 2.1 of the License, or (at your option)  * any later version.  *   * This software is distributed in the hope that it will be useful, but WITHOUT  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more  * details.  *   * You should have received a copy of the GNU Lesser General Public License  * along with this software; if not, write to the Free Software Foundation,  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF  * site: http://www.fsf.org.  */ /**  * A representation of a transition from a state to another state.  *   * @author Scott.Stark@jboss.org  * @version $Revision: 1958 $  */ class Transition {   private String name;   private State target;   public Transition(String name, State target) {     this.name = name;     this.target = target;   }   public String getName() {     return name;   }   public State getTarget() {     return target;   } } /*  * JBoss, Home of Professional Open Source Copyright 2005, JBoss Inc., and  * individual contributors as indicated by the @authors tag. See the  * copyright.txt in the distribution for a full listing of individual  * contributors.  *   * This is free software; you can redistribute it and/or modify it under the  * terms of the GNU Lesser General Public License as published by the Free  * Software Foundation; either version 2.1 of the License, or (at your option)  * any later version.  *   * This software is distributed in the hope that it will be useful, but WITHOUT  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more  * details.  *   * You should have received a copy of the GNU Lesser General Public License  * along with this software; if not, write to the Free Software Foundation,  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF  * site: http://www.fsf.org.  */ /**  * An exception thrown when an invalid transition is attempted from a state.  *   * @author Scott.Stark@jboss.org  * @version $Revision: 2800 $  */ class IllegalTransitionException extends Exception {   /** The serialVersionUID */   private static final long serialVersionUID = -3392564168782896452L;   public IllegalTransitionException(String msg) {     super(msg);   } }