public class StateMachine extends java.lang.Object implements EventConsumer, InfoAppend, java.io.Closeable
StateMachine
. This class builds the frame for all states.
Any state should be defined as inner class derived from either ...or
StateSimple
: A simple state with transitions, an optional entry- and an exit-action.
StateComposite
: It contains more as one sub states.
StateParallel
: It contains more as one StateComposite
for parallel behavior:
Any StateComposite contains a sub statemachine which works parallel if this state is active.
org.vishia.states.example.StateExampleSimple
.
StateSimple.entry(EventObject)
respectively StateSimple.exit()
.
StateSimple.entry
respectively StateSimple.exit
with an Implementation of StateAction
which can be located in any other class,
usual as inner anonymous class. In that cases the entry and exit can use data from any other class.
StateSimple.Trans
.
If a transition should contain an action the transition variable should be an anonymous inner derived class
of StateSimple.Trans
which overrides the StateSimple.Trans.action(EventObject)
.
The other possibility is assignment of action code with StateSimple.Trans.setAction(StateAction)
Any state should override the method StateSimple.checkTrans(EventObject)
. This method checks all conditions
which can fire any transition and returns the selected transition instance or null if nothing should fire. This method should not execute
actions. It should only test the condition and select the transition. The actions are done in the calling environment of this method,
lastly if processEvent(EventObject)
of the whole statemachine is invoked.
StateMachine
all state classes are instantiated and listed in the StateMachine.
All transitions are evaluated and transformed in a unified list of transition objects.
For all transitions the necessary exitState()- and entryState() operations are detected and stored, so that complex state switches
are executed correctly. The designation of destination states in the written source code uses the class names of the states.
The transition evaluation process on construction searches and lists the instances of the states.
getState(Class)
StateMachine
can be quested whether a state is active yet: isInState(Class)
or isInState(Class)
EventTimerThread#EventThread(String)
are necessary which is a parameter for the constructor
#StateMachine(EventTimerThread, EventTimerMng)
.
EventTimerThread
is used an instance of EventTimerMng
is possible and recommended .
The timer manager can manage any number of time orders.
It sends an EventTimerMng.TimeEvent
to this StateMachine it the time is expired.
processEvent(EventObject)
with or without events
by given a null argument, for example cyclically if an EventTimerThread
is not used.
StateSimple.Trans
and StateSimple.Timeout
.Modifier and Type | Class and Description |
---|---|
protected static class |
StateMachine.StateCompositeTop |
Modifier and Type | Field and Description |
---|---|
boolean |
debugEntryExit |
boolean |
debugState
If set true, then any state transition is logged with System.out.printf("...").
|
boolean |
debugTrans |
(package private) EventSource |
evSourceTimeout
The event source for timeout events is the statemachine itself.
|
private java.lang.String |
name |
boolean |
permitException
True then permits exceptions in one state transition. send a log output to System.err but check other transitions.
|
(package private) java.util.List<StateSimple> |
stateList
List of all states parallel to the #stateMap for code generation, filled with reflection.
|
(package private) java.util.HashMap<java.lang.Integer,StateSimple> |
stateMap
Map of all states defined as inner classes of the derived class, filled with reflection.
|
protected StateMachine.StateCompositeTop |
stateTop
The state which presents the whole state machine.
|
(package private) EventThread_ifc |
theThread
Aggregation to the used event queue or the thread for this statemachine.
|
(package private) EventTimerThread_ifc |
timerThread
Aggregation to the used timer thread for this timeouts in the stateMachine.
|
(package private) EventWithDst |
triggerEvent |
static java.lang.String |
version
Version, history and license.
|
mEventConsumed, mEventConsumerException, mEventConsumFinished, mEventDonotRelinquish, mMaskReservedHere
Modifier | Constructor and Description |
---|---|
protected |
StateMachine(StateSimple[] aSubstates)
Special constructor for StateMGen, with given topState, without reflection analysis.
|
|
StateMachine(java.lang.String name)
Creates a state machine which is executed directly by
processEvent(java.util.EventObject) . |
|
StateMachine(java.lang.String name,
EventTimerThread_ifc timerThread,
EventThread_ifc evThread)
Constructs a state machine with a given thread and a given timer manager.
|
Modifier and Type | Method and Description |
---|---|
void |
close() |
protected int |
eventDebug(java.util.EventObject ev)
This method can be overridden if applying an event should be debugged
or for example logged in the derived class.
|
EventThread_ifc |
evThread()
This operation should return that thread, which is associated to this consumer.
|
StateSimple |
getState(java.lang.Class<? extends StateSimple> stateClass)
Gets the state instance to the State class inside this state machine.
|
java.lang.CharSequence |
infoAppend(java.lang.StringBuilder u)
Appends or returns tan information about the instance.
|
boolean |
isInState(java.lang.Class<? extends StateSimple> stateClass)
Checks whether the given state is the active one.
|
int |
processEvent(java.util.EventObject ev)
Applies an event to this state machine.
|
java.util.List<StateSimple> |
stateList() |
java.lang.String |
toString()
Shows the name of the Statemachine and all active states.
|
boolean |
triggerRun(EventSource source)
Triggers a run cycle for the statemachine in the execution thread
or runs the state machine immediately if the execution thread is this thread or the execution thread is not given.
|
public static final java.lang.String version
theThread
for the stateMachine execution itself,
whereby this is now the common EventThread_ifc
instead the specific used org.vihia.event.EventTimerThread
and timerThread
maybe the same, maybe another thread for timeout handling.
This is due to new properties of TimeOrder
.
stateTop
, more unique
StateComposite
, instance of stateTop
.
public boolean debugState
MsgRedirectConsole
to use a proper log system.public boolean debugTrans
public boolean debugEntryExit
public boolean permitException
final EventThread_ifc theThread
final EventTimerThread_ifc timerThread
final EventSource evSourceTimeout
final EventWithDst triggerEvent
protected final StateMachine.StateCompositeTop stateTop
java.util.HashMap<java.lang.Integer,StateSimple> stateMap
DataShow
to assure comparability.java.util.List<StateSimple> stateList
private final java.lang.String name
public StateMachine(java.lang.String name)
processEvent(java.util.EventObject)
. StateSimple.Timeout
is not possible.public StateMachine(java.lang.String name, EventTimerThread_ifc timerThread, EventThread_ifc evThread)
StateComposite.StateComposite()
:
It checks the class for inner classes which are the states.
Each inner class which is instance of StateSimple
is instantiated and stored both in the stateMap
to find all states by its class.hashCode
and in the stateTop
StateCompositeFlat.aSubstates
for debugging only.
StateComposite#buildStatePathSubstates()
is invoked for the topstate and recursively for all states
to store the state path in all states.
Then StateCompositeFlat.createTransitionListSubstate(int)
is invoked for the stateTop
which checks the transition of all states recursively. Therewith all necessary data for the state machines's processing
are created on construction.thread
- if given all events are stored in the thread's event queue, the state machine is executed only in that thread.if
- given timer events can be created.StateComposite.StateComposite()
,
StateComposite#buildStatePathSubstates(StateComposite, int)
,
StateSimple#buildStatePath(StateComposite)
,
StateCompositeFlat.createTransitionListSubstate(int)
,
StateSimple#createTransitionList()
protected StateMachine(StateSimple[] aSubstates)
stateTop
- public java.util.List<StateSimple> stateList()
public final EventThread_ifc evThread()
EventConsumer
evThread
in interface EventConsumer
protected int eventDebug(java.util.EventObject ev)
(at)Override public int eventToTopDebug(EventObject ev) { //any statements ... return super.eventToTopDebug(ev); }The method is invoked if the event is really processed, not only stored in a queue. it is applied to the
stateTop
and in that way to all current states and their transitions.ev
- The event from user or from queue, maybe null.StateComposite.processEvent(java.util.EventObject)
public boolean triggerRun(EventSource source)
source
- maybe nullpublic StateSimple getState(java.lang.Class<? extends StateSimple> stateClass)
StateSimple.isInState()
or for some statistically checks
like StateSimple.dateLastEntry
etc.stateClass
- write getState(MyStateMachine.StateClass.InnerStateClass.class)
public boolean isInState(java.lang.Class<? extends StateSimple> stateClass)
stateClass
- The hashcode of the class is used internally to check whether this is the active state.public int processEvent(java.util.EventObject ev)
EventWithDst#sendEvent()
if this class is given
as EventConsumer
. If the statemachine is aggregated with a EventTimerThread
by constructor #StateMachine(String, EventTimerThread)
and this routine is invoked from another thread then the event will be stored in theThread
.
If the state machine is not aggregated with a EventTimerThread then the execution is immediately done.
via call of eventDebug(EventObject)
.
EventWithDst#sendEvent()
especially if the state machine should be executed
in the users thread and without events.
This method is invoked from the EventTimerThread
if the event queue is processed there.processEvent
in interface EventConsumer
ev
- the event to executeStateSimple
,
especially from here StateSimple.mEventConsumed
and StateSimple.mEventDonotRelinquish
.
The last one is identically with EventConsumer.mEventDonotRelinquish
and is set, if this event is forwarded to the #theThreaad of this state machine.public java.lang.CharSequence infoAppend(java.lang.StringBuilder u)
InfoAppend
StringBuilder u = new StringBulder(1000); u.append(something_else); myInstance.infoAppend(u); //uses this interface u.append(some_more); System.out.append(u); //output the information String savedInfo = u.toString(); //save permanent.Implementing pattern
QOverride public infoAppend(StringBuilder u) { if(u == null){ u = new StringBuilder(); } //it can be null! u.append(special_information).append(": ").append(somewhatElse); return u; }Contiguity with toString: It uses the same information, assembled in a StringBuilder:
QOverride public String toString(){ return infoAppend(null).toString()); }
infoAppend
in interface InfoAppend
u
- if not null then the info is appended to u, u is returned.
public void close() throws java.io.IOException
close
in interface java.io.Closeable
close
in interface java.lang.AutoCloseable
java.io.IOException
public java.lang.String toString()
toString
in class java.lang.Object
Object.toString()