import java.util.*; /*This class will create an instance of a Finite State Machine. The class maintains a hashtable of the created states. It contains functions to add states, remove states, add and remove transitions (using functions in the state class), reset the machine (return the current state to the initial state), determine of the machine is a valid machine (does it have an initial state?), start the stimulation, end the stimulation, output the contents of the machine, set the initial state, return the current state, and send events to cause transitions.*/ public class FiniteStateMachine { /* PRIVATE VARIABLES*/ /*Create a hashtable to hold the states*/ protected Hashtable states = new Hashtable(); /*Create a boolean to determine if the simulation is running or not. This determines which functions can be used.*/ private boolean simActive = false; /*Set the initial state to null*/ private State initialState = null; /*Set the current state to null*/ private State currentState = null; /* PUBLIC FUNCTIONS*/ /*Main function*/ public static void main(String[] args) {} /*isValid() determines if the machine is runnable (It is runnable if it has an initial state*/ public boolean isValid() { if(initialState!=null) { return true; } else { return false; } //end if initialState isn't null statement } //End isValid() method /*Reset returns the current state to the initial state*/ public void reset() { currentState = initialState; }//End reset method /*Return the current state of the machine, regardless of whether the simulator is running or not.*/ public State getCurrentState() { return currentState; }//End getCurrentState method /*Add a state to the hashtable*/ public void addState(String stateName) throws FSMException { /*Verify that the state does not already exist*/ if (!simActive) { if (states.containsKey(stateName)) { throw new StateExistsException(stateName); } else { /*If the state doesn't already exist, add it to the hashtable*/ State newState = new State(stateName); states.put(newState.getLabel(), newState); }//End if state exists statement } /*If the simulation is running, a state cannot be added.*/ else { throw new SimulationRunningException("addState()"); }//End if simulation is running statement. }//End addState method /*This function removes a state from the hashtable*/ public void removeState(String stateName) throws FSMException { if (!simActive) { State toDelete = (State)states.get(stateName); /*If the state doesn't exist, throw an exception*/ if (toDelete==null) { throw new StateDoesNotExistException(stateName); }//End if state doesn't exist statement /*If a state is pointed to by transitions, throw an exception that it cannot be removed*/ else if (toDelete.isReached()) { throw new TransitionPointsToStateException(); }//End if state is reached statement. /*If the removed state is the initial state, set the initial state to null*/ else { if (toDelete==initialState) { initialState = null; } //End if state is initial state statement /*Remove the state*/ states.remove(stateName); }//End if state exists and isn't reached statement. } /*If the simulation is running, states cannot be removed.*/ else { throw new SimulationRunningException("removeState()"); }//End if simulation is running statement }//End removeState method /*Add a transition to a state, given the source state, the destination state, and the event that triggers the transition.*/ public void addTransition(String src_lbl, String dst_lbl, String letterEvent) throws FSMException { if (!simActive) { /*Throw an exception if the source doesn't exist*/ if(!states.containsKey(src_lbl)) { throw new StateDoesNotExistException(" source "+src_lbl); }//End if src state does not exist statement. /*Throw an exception if the destination doesn't exist*/ else if (!states.containsKey(dst_lbl)) { throw new StateDoesNotExistException(" dest "+dst_lbl); }//End if dest state does not exist statement. else { // retrieve handle to state object, then add transition // to that state object State handle_to_src = (State)states.get(src_lbl); State handle_to_dst = (State)states.get(dst_lbl); /*Create letter object to pass to state class*/ Letter event = new Letter(letterEvent); handle_to_src.addTransition(event, handle_to_dst); } //End if src and dest states exist statement. } /*If simulation is running, throw exception*/ else { throw new SimulationRunningException("addTransition()"); }//End if simulation is running statement. }//End of addTransition method /*Delete transition defined by starting state and event*/ public void deleteTransition(String stateOne, Letter eventCause) throws FSMException { if (!simActive) { /*Assuming the exception is thrown from State class if transition doesn't exist*/ State handle_to_state = (State)states.get(stateOne); handle_to_state.deleteTransition(eventCause); } /*Transition cannot be deleted if simulation is running*/ else { throw new SimulationRunningException("deleteTransition()"); }//End if simulation is running statement. }//End of deleteTransition method. /*Set the initial state of the machine*/ public void setInitialState(String stateName) throws FSMException { if(!simActive) { /*If the given state doesn't exist, throw exception*/ if (!states.containsKey(stateName)) { throw new StateDoesNotExistException(stateName); } /*Otherwise, set the initial state to given state, and current state to given state*/ else { State toBeInitial = (State)states.get(stateName); initialState = toBeInitial; currentState = toBeInitial; }//End of if state exists statement. } /*Cannot setInitialState if simulation is running*/ else { throw new SimulationRunningException("setInitialState()"); }//End of if simulation running statement. } //End of setInitialState method. /*Start simulation*/ public void startSimulation() throws FSMException { /*If not already running, set boolean to true to limit functions.*/ if(!simActive) { /*If machine is valid, start simulation*/ if(isValid()) { simActive = true; } /*Otherwise throw an exception that the FSM is not valid.*/ else { throw new FSMNotValidException(); }//End if isValid() statement } /*If machine is already running, cannot startSimulation*/ else { throw new SimulationRunningException("startSimulation()"); }//End if machine is running statement }//End startSimulation method /*Stop simulation from running*/ public void stopSimulation() throws FSMException { /*If machine is running, stop it by setting boolean to false*/ if(simActive) { simActive = false; } /*If machine is not running, throw exception - cannot stop machine that's not running*/ else { throw new SimulationStoppedException("stopSimulation()"); }//End if simulation is runnning statement. }//End stopSimulation method. /*Send event to state to cause transition*/ public String sendEvent(String trigger) throws FSMException { if(simActive) { /*If there is an initial state, create letter object, and call on nextState function in State class. nextState returns current state, and sendEvent returns the String that defines this state.*/ if (currentState!=null) { Letter next_trigger = new Letter(trigger); currentState = currentState.nextState(next_trigger); return currentState.getLabel(); } /*If current state does not exist, throw exception*/ else { throw new StateDoesNotExistException("Current"); }//End if current state is null statement. } else { /*If simulation is not running, throw exception that event cannot be handled.*/ throw new SimulationStoppedException("sendEvent()"); }//End if simulation is running statement. }//End sendEvent method /*Print out states and transitions in machine.*/ public void displayMe() { /*Print out defined states*/ System.out.println("(machine"); System.out.println(" (initialState "+(initialState==null?"null":initialState.getLabel())+")"); System.out.println(" (currentState "+(initialState==null?"null":currentState.getLabel())+")"); System.out.println(" (states"); /*Enumerate states in hashtable*/ Enumeration run = states.elements(); while (run.hasMoreElements()) { State temp = (State)run.nextElement(); /*Use State class' displayMe to display properties of each state.*/ temp.displayMe(); }//End of while loop that traverses hashtable. System.out.println(" )"); System.out.println(")"); }//End of displayMe method }//End of FiniteStateMachine class