All Downloads are FREE. Search and download functionalities are using the official Maven repository.

java-fsm.code.net.openai.util.fsm.Machine Maven / Gradle / Ivy

Go to download

OpenAI FSM is used by Apache cTAKES. It was originally developed out of sourceforge openAI group

The newest version!
/*****************************************************************************
 * 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 State object to begin on.  This must
     *                   be non-null.
     */
    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.
     * 

* 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 State. If the * condition is met by one of the Conditions of the * State, then the new current State will be that * returned by the input method of the present State. * * @param condition The input to pass to the current State. * @throws UnhandledConditionException If the current State * returns null 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 State is the * start state. No state transitions will be fired. This is the same * as calling reset(false, false). */ public final void reset() { reset(false, false); } /** * Resets this machine so that its current State is the * start state. If asTransition is true 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 false then the current state will simply be set * to be the start state. * * @param asTransition If true then the current state * and the start state will act as if there is * a transition between them. * @param nullifyInput If true 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; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy