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

java-fsm.code.net.openai.util.fsm.State 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.State
 *****************************************************************************
 * @author  JC on E
 * @date    9/18/2000
 * 2001 OpenAI Labs
 *****************************************************************************/

package net.openai.util.fsm;

import java.util.Vector;
import java.io.Serializable;

import net.openai.util.fsm.event.StateEvent;
import net.openai.util.fsm.event.StateListener;


/**
 * State abstract class
 */
public abstract class State implements Serializable {

    /** The current "number" for the state name. */
    private static int stateNumber = 0;

    /** A Vector of Conditions to check. */
    private Vector conditions = new Vector();

    /** The name of this state. */
    private String name = getDefaultName();

    /** A flag to indicate that we are a start state.  This can only be set
	by the Machine itself.  If you wish to set a State as a start state
	you must call setStartState() on the machine itself. */
    private boolean startState = false;

    /** A flag to indicate that this is an end state.  Unlike the start state
	flag, a state's end state flag can freely be changed on the state
	itself. */
    private boolean endState = false;

    /** A list of listeners for this state. */
    private Vector listeners = new Vector();

    /**
     * Constructs a new State.
     */
    public State() {
    }

    /**
     * Constructs a new state name that is given by default.
     */
    private static synchronized String getDefaultName() {
	return "";
    }

    /**
     * Sets the name for this state.  If the name passed in is null, then a
     * NullPointerException will be generated.
     *
     * @param name The new name for this state.
     */
    public final void setName(String name) {
	if(name == null)
	    throw new NullPointerException("The state name cannot be null!");
	this.name = new String(name);
    }

    /**
     * Returns the name of this state.
     *
     * @return A String that represents the name of this state.
     */
    public final String getName() {
	return new String(name);
    }

    /**
     * This method will only be called by the machine itself.  It sets the
     * start state flag for this state.
     *
     * @param startState The new start state flag.
     */
    final void setStartStateFlag(boolean startState) {
	if(startState == this.startState)
	    return;
	this.startState = startState;
	fireStateEvent(StateEvent.START_FLAG_CHANGE);
    }

    /**
     * Returns true if this state is a start state, false otherwise.
     *
     * @return The value of this state's start state flag.
     */
    public final boolean getStartStateFlag() {
	return startState;
    }

    /**
     * Sets the value of this state's end state flag.
     *
     * @param endState The new value of this state's end state flag.
     */
    public final void setEndStateFlag(boolean endState) {
	if(endState == this.endState)
	    return;
	this.endState = endState;
	fireStateEvent(StateEvent.END_FLAG_CHANGE);
    }

    /**
     * Returns true if this state is an end state, false otherwise.
     *
     * @return The value of this state's end state flag.
     */
    public final boolean getEndStateFlag() {
	return endState;
    }

    /**
     * Adds a StateListener to this State that we will deliver events to.
     *
     * @param listener The StateListener to add.
     */
    public final void addStateListener(StateListener listener) {
	if(listener == null)
	    throw new NullPointerException("Cannot add null listener.");
	synchronized(listeners) {
	    if(!listeners.contains(listener))
		listeners.addElement(listener);
	}
    }

    /**
     * Removes a StateListener from this State.
     *
     * @param listener The StateListener to remove.
     */
    public final void removeStateListener(StateListener listener) {
	if(listener == null)
	    return;
	synchronized(listeners) {
	    listeners.removeElement(listener);
	}
    }

    /**
     * Sends a StateEvent to all of the listeners on this State.
     *
     * @param type The type of event to fire.
     */
    private void fireStateEvent(int type) {
	Vector toFireTo = null;
	synchronized(listeners) {
	    toFireTo = (Vector)listeners.clone();
	}
	int numListeners = toFireTo.size();
	for(int i = 0; i < numListeners; i++)
	    ((StateListener)toFireTo.elementAt(i)).
		handleStateEvent(new StateEvent(this, type));
    }

    /**
     * Adds a Condition to this State.  If this is the current state in the
     * machine when the machine is receiving input, then this state will
     * iterate down the list of conditions to find the first one that is
     * met by the input to the machine.  Once the first condition that
     * satisfies the input is found, then the condition's target state
     * will be returned to the machine as the new curren state.
     * 

* NOTE: Subsequent calls to this method with the same condition will * put the condition at the end of the list of conditions to be * checked. * * @param condition The new Condition to add. */ public final void addTransition(Condition condition) { // Both condition and state must be non-null if(condition == null) throw new NullPointerException("Cannot add null Condition"); synchronized(conditions) { if(conditions.contains(condition)) conditions.removeElement(condition); conditions.addElement(condition); } //condition.addSourceState(this); } /** * Convenience method for adding a transition from this state to the next. * This method simply calls addTransition() on this state and then calls * setTargetState() the condition. * * @param condition The new Condition to add. * @param targetState The target state for this transition. */ public final void addTransition(Condition condition, State targetState) { addTransition(condition); condition.setTargetState(targetState); } /** * Removes a Condition as a Transition from this State. * * @param condition The Condition/Transition to remove. */ public final void removeTransition(Condition condition) { if(condition == null) return; //condition.removeSourceState(this); synchronized(conditions) { conditions.removeElement(condition); } } /** * Returns a Vector of the current Conditions/Transitions for this State. * * @return The current list of Conditions for this State or null if there * aren't any. */ public final Vector getTransitions() { Vector returnValue = null; synchronized(conditions) { if(!conditions.isEmpty()) returnValue = (Vector)conditions.clone(); } return returnValue; } /** * Iterates through the Condition list and finds the first Condition * that meets condition and returns the associated State. * If no conditions match, then null is returned. * * @param condition The condition to check. For example, if the set of * Conditions check for a particular Integer, then the * first Condition that matches the Integer passed into * this method will be "met" and the associated State * will be returned. * @return The State that maps to the matching Condition or null if no * Conditions meet the criteria. */ final State input(Object condition) { // condition must be non-null if(condition == null) throw new NullPointerException("Null input condition"); Vector toCheck = getTransitions(); if(toCheck == null) return null; // Iterate through the list of Conditions and find the first match int numConditions = toCheck.size(); for(int i = 0; i < numConditions; i++) { Condition cond = (Condition)toCheck.elementAt(i); if(cond.satisfiedBy(condition)) return cond.getTargetState(); } // No conditions matched, so return null return null; } /** * Called directly by the machine when this state is entered. * * @param input The input to feed into this state. */ void enterState(Object input) { fireStateEvent(StateEvent.ENTER_START); enter(input); fireStateEvent(StateEvent.ENTER_END); } /** * Called directly by the machine when this state is exited. * * @return Any output object that is to be fed into the next state. */ Object exitState() { fireStateEvent(StateEvent.EXIT_START); Object returnValue = exit(); fireStateEvent(StateEvent.EXIT_END); return returnValue; } /** * This method is called when the state is entered. * * @param input Any output from a previous state will become the input * for this state. If this is a start state, then * input will be null. */ public abstract void enter(Object input); /** * This method is called when the state is exited via a transition to * another state. * * @return Any output object that is to be fed into the next state. */ public abstract Object exit(); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy