📄 machine.java
字号:
/***************************************************************************** * net.openai.fsm.Machine ***************************************************************************** * @author JC on E * @date 9/24/2000 * 2001 OpenAI Labs *****************************************************************************/package net.openai.util.fsm;import java.util.Vector;import java.io.Serializable;import net.openai.util.fsm.event.MachineEvent;import net.openai.util.fsm.event.MachineListener;/** * The controlling Machine class for the Finite State Machine */public class Machine implements Serializable { /** A handle to the start state. This will be the first state added to the machine. */ private State startState = null; /** A handle to the current state of the machine. */ private State currentState = null; /** A dummy object to synchronize on across methods. */ private Integer syncObject = new Integer(-1); /** A list of listeners for this Machine. */ private Vector listeners = new Vector(); /** * Constructs a new Machine object with no start state. */ public Machine() { } /** * Constructs a new Machine object. * * @param startState The <code>State</code> object to begin on. This must * be <code>non-null</code>. */ public Machine(State startState) { setStartState(startState); } /** * Adds a MachineListener to this Machine that we will deliver events to. * * @param listener The MachineListener to add. */ public final void addMachineListener(MachineListener listener) { if(listener == null) throw new NullPointerException("Cannot add null listener."); synchronized(listeners) { if(!listeners.contains(listener)) listeners.addElement(listener); } } /** * Removes a MachineListener from this Machine. * * @param listener The MachineListener to remove. */ public final void removeMachineListener(MachineListener listener) { if(listener == null) return; synchronized(listeners) { listeners.removeElement(listener); } } /** * Sends a MachineEvent to all of the listeners on this Machine. * * @param type The type of event to fire. */ private void fireMachineEvent(int type) { Vector toFireTo = null; synchronized(listeners) { toFireTo = (Vector)listeners.clone(); } int numListeners = toFireTo.size(); for(int i = 0; i < numListeners; i++) ((MachineListener)toFireTo.elementAt(i)). handleMachineEvent(new MachineEvent(this, type)); } /** * Sets the start state for this machine. * * @param state The new start state for this machine. */ public final void setStartState(State state) { if(state == null) throw new NullPointerException("Null start state"); synchronized(syncObject) { if(this.startState != null) this.startState.setStartStateFlag(false); this.startState = state; this.startState.setStartStateFlag(true); } } /** * Returns a handle to the starting state for this machine. * * @return The starting state for this machine or null if one is not set. */ public final State getStartState() { State returnValue = null; synchronized(syncObject) { returnValue = startState; } return returnValue; } /** * Forcibly sets the current state of this machine. * <br><br> * NOTE: This is NOT recommended for use in general, but it is provided * in case there is a need for it. No checking is done as to * whether or not the state can be reached though valid transitions * and any state listeners, and state IO is not performed. * * @param state The new current state. */ protected final void setCurrentState(State state) { synchronized(syncObject) { this.currentState = state; } } /** * Returns the current state of this machine. * * @return The current state of this machine. */ public final State getCurrentState() { State returnValue = null; synchronized(syncObject) { returnValue = currentState; } return returnValue; } /** * Takes input and passes it to the current <code>State</code>. If the * condition is met by one of the <code>Condition</code>s of the * <code>State</code>, then the new current <code>State</code> will be that * returned by the input method of the present <code>State</code>. * * @param condition The input to pass to the current <code>State</code>. * @throws UnhandledConditionException If the current <code>State</code> * returns <code>null</code> for its input method, then a condition * has arisen that is not handled. */ public final void input(Object condition) throws UnhandledConditionException { synchronized(syncObject) { if(currentState == null) currentState = startState; // find the new state State newState = currentState.input(condition); if(newState == null) throw new UnhandledConditionException(currentState, condition); Object stateData = currentState.exitState(); currentState = newState; currentState.enterState(stateData); } } /** * Convenience method to handle the boolean primitive as an input * condition. * * @param condition The value to input. */ public final void input(boolean condition) throws UnhandledConditionException { input(new Boolean(condition)); } /** * Convenience method to handle the byte primitive type as an input * condition. * * @param condition The value to input. */ public final void input(byte condition) throws UnhandledConditionException { input(new Byte(condition)); } /** * Convience method to handle the char primitive type as an input * condition. * * @param condition The value to input. */ public final void input(char condition) throws UnhandledConditionException { input(new Character(condition)); } /** * Convience method to handle the double primitive type as an input * condition. * * @param condition The value to input. */ public final void input(double condition) throws UnhandledConditionException { input(new Double(condition)); } /** * Convience method to handle the float primitive type as an input * condition. * * @param condition The value to input. */ public final void input(float condition) throws UnhandledConditionException { input(new Float(condition)); } /** * Convience method to handle the int primitive type as an input * condition. * * @param condition The value to input. */ public final void input(int condition) throws UnhandledConditionException { input(new Integer(condition)); } /** * Convience method to handle the long primitive type as an input * condition. * * @param condition The value to input. */ public final void input(long condition) throws UnhandledConditionException { input(new Long(condition)); } /** * Convience method to handle the Short primitive type as an input * condition. * * @param condition The value to input. */ public final void input(short condition) throws UnhandledConditionException { input(new Short(condition)); } /** * Resets this machine so that its current <code>State</code> is the * start state. No state transitions will be fired. This is the same * as calling <code>reset(false, false)</code>. */ public final void reset() { reset(false, false); } /** * Resets this machine so that its current <code>State</code> is the * start state. If <code>asTransition</code> is <code>true</code> then * the output of the current state (if it exists) will be input into * the start state and the start state will be the new current state. * If it is <code>false</code> then the current state will simply be set * to be the start state. * * @param asTransition If <code>true</code> then the current state * and the start state will act as if there is * a transition between them. * @param nullifyInput If <code>true</code> then null will be fed into * the start state instead of the output of the * current state. */ public final void reset(boolean asTransition, boolean nullifyInput) { synchronized(syncObject) { if(asTransition) { Object stateData = null; if(currentState != null) stateData = currentState.exitState(); currentState = startState; if(nullifyInput) stateData = null; if(currentState != null) currentState.enterState(stateData); } else { currentState = startState; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -