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;
}
}