package GCB; /** Finite state machine * * driven by states defined in StateVariable set * execute() methods are the core of the machine (various flavors) * timer() method checks for states that are not progressing * trace() method writes string to trace file * * @author George C. Blankenship, Jr. */ /** StateVariable for an FSM * * @author George C. Blankenship, Jr. */ public class StateVariable extends ListEntry { // constants static final String CODE_FILE = "StateVariable"; static final int CODE_REVISION = 1; // class attributes (static variables) // object attributes (variables) - publically referencable private StateMachine fsm; // FSM private int index; // state variable identifier private String description; // description of the state for display private long time, // time when the state became current timeout, // length of time the state can run normalTimeout; // default value for timeout private boolean missed; // true->state has run too long (completion timeout) private StateVariable resetState, // restart point after an error nextState; // queued state to be used (resumed) after completion private Trace trace; // constructors /** StateVariable() is the constructor for a state variable with no timeout or reset * The timeout is the maximum length of time the state may run without a completion execution * invocation. A reset state is used as a restart point after an error. * * @param t is a trace object for tracing this variable * @param f is the state machine * @param s is a String that is the description of the state * @return (no return value - constructor) */ public StateVariable(Trace t, StateMachine f, String s) { super(); this.trace = t; this.fsm = f; // state machine that uses the state index = fsm.getNextIndex(); // assign a index to the state description = s; // state description timeout = 0; // no timeout normalTimeout = timeout; missed = false; resetState = null; // no reset state nextState = null; // no next state this.trace.write("create state "+String.valueOf(index)+": "+ description+" (no reset or timeout)"); fsm.add(this); // add to chain of states for the FSM } /** StateVariable() is the constructor for a state variable with a reset and no timeout * The timeout is the maximum length of time the state may run without a completion execution * invocation. A reset state is used as a restart point after an error. * * @param t is a trace object for tracing this variable * @param f is the state machine * @param s is a String that is the description of the state * @param r is a StateVariable that will be used as a restart point after an error * @return (no return value - constructor) */ public StateVariable(Trace t, StateMachine f ,String s, StateVariable r) { super(); this.trace = t; this.fsm = f; // state machine that uses the state index = fsm.getNextIndex(); // assign a index to the state description = s; // state description timeout = 0; // no timeout normalTimeout = timeout; missed = false; resetState = r; // reset state nextState = null; // no next state trace.write("create state "+String.valueOf(index)+": "+ description+" (reset="+r.getDescription()+"), (no timeout)"); fsm.add(this); // add to chain of states for the FSM } /** StateVariable() is the constructor for a state variable with a timeout and no reset * The timeout is the maximum length of time the state may run without a completion execution * invocation. A reset state is used as a restart point after an error. * * @param t is a trace object for tracing this variable * @param f is the state machine * @param s is a String that is the description of the state * @param ms is the length of time the state can normally run * @return (no return value - constructor) */ public StateVariable(Trace t, StateMachine f, String s, long ms) { super(); this.trace = t; this.fsm = f; // state machine that uses the state index = fsm.getNextIndex(); // assign a index to the state description = s; // state description timeout = ms; // timeout (ms past start of state) normalTimeout = timeout; missed = false; resetState = null; // no reset state nextState = null; // no next state trace.write("create state "+String.valueOf(index)+": "+ description+" (timeout="+String.valueOf(timeout)+")"); fsm.add(this); // add to chain of states for the FSM } /** StateVariable() is the constructor for a state variable with a reset and timeout * The timeout is the maximum length of time the state may run without a completion execution * invocation. A reset state is used as a restart point after an error. * * @param t is a trace object for tracing this variable * @param f is the state machine * @param s is a String that is the description of the state * @param r is a StateVariable that will be used as a restart point after an error * @param ms is the length of time the state can normally run * @return (no return value - constructor) */ public StateVariable(Trace t, StateMachine f, String s, StateVariable r, long ms) { super(); this.trace = t; this.fsm = f; // state machine that uses the state index = fsm.getNextIndex(); // assign a index to the state description = s; // state description timeout = ms; // timeout (ms past start of state) normalTimeout = timeout; missed = false; resetState = r; // reset state nextState = null; // no next state trace.write("create state "+String.valueOf(index)+": "+ description+" (reset="+r.getDescription()+ "), (timeout="+String.valueOf(timeout)+")"); fsm.add(this); // add to chain of states for the FSM } /** getFSM() retrieves the state machine * The state machine is the object that relates the state. * * (no input) * @return fsm - the Finite State Machine */ public StateMachine getFSM() {return fsm;} /** getIndex() retrieves the state variable's index * The index uniquely identifies the state. * * (no input) * @return index - the unique identifier of the state */ public int getIndex() {return index;} /** getDescription() retrieves the state text description * The description is used for messages. * * (no input) * @return description - the state description */ public String getDescription() {return description;} /** setTime() sets the starting time for the state * The starting time is used to establish the timeout basis. * * @param t - the system clock time of the state start * @return (no return) */ public void setTime(long t) {time = t;} // set start time of state /** getTime() retrieves the starting time for the state * The starting time is used to establish the timeout basis. * * (no input) * @return time is the starting time for the state */ public long getTime() {return time;} // fetch start time of state /** getNormalTimeout() retrieves the default timeout for the state * The default timeout is established when the state was created. * * (no input) * @return time is the default timeout for the state */ public long getNormalTimeout() {return normalTimeout;}// fetch normal timeout of state /** setTimeout() sets the run time for the state * The run time is the maximum time that a state can run without a completion. * * @param t - the run time * @return (no return) */ public void setTimeout(long t) {timeout=t;} // change the timeout for the state /** getTimeout() retrieves the current run time for a state * The run time is used to establish that a state has run too long. * * (no input) * @return time is the run time for a state */ public long getTimeout() {return timeout;} // fetch the timeout for the state /** setMissed() sets the state missed completion status * The missing completion status reflects the timeout for state completion. True indicates * that the state missed a completion (timeout). False indicates that the state is running * normally * * @param t is a boolean (true or false) * @return (no return) */ public void setMissed(boolean b) {missed = b;} /** wasMissed() retrieves the completion status for a state * If the state does not complete within the run time, the completion has been missed. True * indicates that the completion was missed (timeout). False indicates that the run time has * not yet been reached (no timeout). * * (no input) * @return a boolean that indicates whether the state completed within the run time. */ public boolean wasMissed() {return missed;} // state missed (timeout occurred) /** setNextState() sets a state to be executed when the current state completes * This is used to establish a resumption point when a state reaches a recoverable error. * * @param s - the StateVariable to be made current when the current completes * @return boolean - false->state already queued */ public boolean setNextState(StateVariable s) { trace.write("queue state ("+s.getDescription()+")"); if(nextState!=null) { trace.write("state ("+nextState.getDescription()+" already queued"); return false; } nextState = s; return true; } /** getNextState() retrieves a queued state to be executed after a successful completion * A state is queued for exection after a current state, if the state was interrupted by * a recoverable error. The current state is the recovery point. * * (no input) * @return a StateVariable that is to become the current state. */ public StateVariable getNextState() { StateVariable s = nextState; nextState = null; return s; } public StateVariable getResetState() {return resetState;} /** getShortSummary() gets a string that contains of the current status of the state * The status includes * state description * state index * * (no input) * @return a string for the summary */ public String getShortSummary() { String summary = new String("state "+description+" ("+String.valueOf(index)+")"); return summary; } /** getSummary() gets a string that contains of the current status of the state * The status includes * controlling fsm * state description * state index * * (no input) * @return a string for the summary */ public String getSummary() { String summary = new String("FSM "+fsm.getName()+" "+getShortSummary()); return summary; } }