Updates to docs
This commit is contained in:
@@ -15,6 +15,16 @@ material in this reference documentation.
|
||||
include::samples/States.java[tags=snippetA]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/States2.java[tags=snippetA]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/States3.java[tags=snippetA]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/Events.java[tags=snippetA]
|
||||
@@ -86,6 +96,22 @@ directly contained in a state machine and all other regions in the
|
||||
state machine also are completed, then it means that the entire state
|
||||
machine is completed.
|
||||
|
||||
*History State*::
|
||||
A pseudo state which allows a state machine to remember its last
|
||||
active state. Two types of history state exists, _shallow_ which only
|
||||
remember top level state and _deep_ which remembers active states in a
|
||||
sub-machines.
|
||||
|
||||
*Choice State*::
|
||||
A pseudo state which allows to make a transition choice based of i.e.
|
||||
event headers or extended state variables.
|
||||
|
||||
*Fork State*::
|
||||
A pseudo state which gives a controlled entry into a regions.
|
||||
|
||||
*Join State*::
|
||||
A pseudo state which gives a controlled exit from a regions.
|
||||
|
||||
*Region*::
|
||||
A region is an orthogonal part of either a composite state or a state
|
||||
machine. It contains states and transitions.
|
||||
@@ -124,6 +150,45 @@ flags, nested if/else/break clauses or other impractical logic you
|
||||
simply rely on state, state variables or other interaction with a
|
||||
state machine.
|
||||
|
||||
==== Pseudo States
|
||||
PseudoState is a special type of state which usually introduces more
|
||||
higher level logic into a state machine by either giving a state a
|
||||
special meaning like initial state. State machine can then internally
|
||||
react to these states by doing various actions available in UML state
|
||||
machine concepts.
|
||||
|
||||
===== Initial
|
||||
Initial state is always needed for every single state machine whether
|
||||
you have a simple one level state machine or more complex state
|
||||
machine composed with submachines or regions. Initial state simple
|
||||
defines where state machine should go when it starts and without it
|
||||
state machine is ill-formed.
|
||||
|
||||
===== End
|
||||
Terminate state which is also called as end state will indicate that a
|
||||
particular state machine has reached its final state. Effectively this
|
||||
mean that a state machine will no longer process any events and will
|
||||
not transit to any other state. However in a case of submachines are
|
||||
regions, state machine is able to restart from its terminal state.
|
||||
|
||||
===== Choice
|
||||
Choice can be used to choose a transition conditionally.
|
||||
|
||||
===== History
|
||||
History state can be used to remember a last active state
|
||||
configuration. After state machine has been exited, history state can
|
||||
be used to restore previous knows configuration. There are two types
|
||||
of history states available, _SHALLOW_ only remember active state of a
|
||||
state machine itself while _DEEP_ also remembers nested states.
|
||||
|
||||
===== Fork
|
||||
Fork can be used to do an explicit entry into one or more regions.
|
||||
|
||||
===== Join
|
||||
Join is used to merge several transitions together originating from
|
||||
different regions. It it generally used to wait and block for
|
||||
participating regions to get into its join target states.
|
||||
|
||||
==== Guard Conditions
|
||||
Guard conditions are expressions which evaluates either to *TRUE* or
|
||||
*FALSE* based on extended state variables and event parameters. Guards
|
||||
|
||||
BIN
docs/src/reference/asciidoc/images/statechart5.png
Normal file
BIN
docs/src/reference/asciidoc/images/statechart5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/src/reference/asciidoc/images/statechart6.png
Normal file
BIN
docs/src/reference/asciidoc/images/statechart6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -442,3 +442,183 @@ What happened in above run:
|
||||
* We print lcd status and request next track.
|
||||
* We stop playing.
|
||||
|
||||
== Tasks
|
||||
|
||||
Tasks is a sample demonstrating a parallel task handling within a
|
||||
regions and additionally adds an error handling to either
|
||||
automatically or manually fixing task problems before continuing back
|
||||
to a state where tasks can be run again.
|
||||
|
||||
image::images/statechart5.png[width=500]
|
||||
|
||||
On a high level what happens in this state machine is:
|
||||
|
||||
* We're always trying to get into READY state so that we can use event
|
||||
RUN to execute tasks.
|
||||
* TASKS state which is composed with 3 independent regions has been
|
||||
put in a middle of FORK and JOIN states which will cause regions to
|
||||
go into its initial states and to be joined by end states.
|
||||
* From JOIN state we go automatically into a CHOICE state which checks
|
||||
existence of error flags in extended state variables. Tasks can set
|
||||
these flags and it gives CHOICE state a possibility to go into ERROR
|
||||
state where errors can be handled either automatically or manually.
|
||||
* AUTOMATIC state in ERROR can try to automatically fix error and goes
|
||||
back to READY if it succeed to do so. If error is something what
|
||||
can't be handled automatically, user intervention is needed and
|
||||
machine is put into MANUAL state via FALLBACK event.
|
||||
|
||||
.States
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetB]
|
||||
----
|
||||
|
||||
.Events
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetC]
|
||||
----
|
||||
|
||||
.Configuration - states
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAA]
|
||||
----
|
||||
|
||||
.Configuration - transitions
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAB]
|
||||
----
|
||||
|
||||
Guard below is guarding choice entry into a ERROR state and needs to
|
||||
return TRUE if error has happened. For this guard simply checks that
|
||||
all extended state variables(T1, T2 and T3) are TRUE.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAC]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAD]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAE]
|
||||
----
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/tasks/Application.java[tags=snippetAF]
|
||||
----
|
||||
|
||||
Lets see an example how this state machine actually works.
|
||||
|
||||
[source,text]
|
||||
----
|
||||
sm>sm start
|
||||
State machine started
|
||||
Entry state READY
|
||||
|
||||
sm>tasks run
|
||||
Entry state TASKS
|
||||
run task on T1
|
||||
run task on T2
|
||||
run task on T3
|
||||
run task on T1 done
|
||||
run task on T2 done
|
||||
run task on T3 done
|
||||
Entry state T1
|
||||
Entry state T3
|
||||
Entry state T2
|
||||
Entry state T1E
|
||||
Entry state T2E
|
||||
Entry state T3E
|
||||
Exit state TASKS
|
||||
Entry state JOIN
|
||||
Exit state JOIN
|
||||
Entry state READY
|
||||
|
||||
sm>
|
||||
----
|
||||
|
||||
== Washer
|
||||
|
||||
Washer is a sample demonstrating a use of a history state to recover a
|
||||
running state configuration with a simulated power off situation.
|
||||
|
||||
Anyone ever used a washing machine knows that if you can somehow pause
|
||||
the program it will continue from a same state when lid is closed.
|
||||
This kind of behaviour can be implemented in a state machine by using
|
||||
a history pseudo state.
|
||||
|
||||
image::images/statechart6.png[width=500]
|
||||
|
||||
.States
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/washer/Application.java[tags=snippetB]
|
||||
----
|
||||
|
||||
.Events
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/washer/Application.java[tags=snippetC]
|
||||
----
|
||||
|
||||
.Configuration - states
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/washer/Application.java[tags=snippetAA]
|
||||
----
|
||||
|
||||
.Configuration - transitions
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/demo/washer/Application.java[tags=snippetAB]
|
||||
----
|
||||
|
||||
Lets see an example how this state machine actually works.
|
||||
[source,text]
|
||||
----
|
||||
sm>sm start
|
||||
Entry state RUNNING
|
||||
Entry state WASHING
|
||||
State machine started
|
||||
|
||||
sm>sm event RINSE
|
||||
Exit state WASHING
|
||||
Entry state RINSING
|
||||
Event RINSE send
|
||||
|
||||
sm>sm event DRY
|
||||
Exit state RINSING
|
||||
Entry state DRYING
|
||||
Event DRY send
|
||||
|
||||
sm>sm event CUTPOWER
|
||||
Exit state DRYING
|
||||
Exit state RUNNING
|
||||
Entry state POWEROFF
|
||||
Event CUTPOWER send
|
||||
|
||||
sm>sm event RESTOREPOWER
|
||||
Exit state POWEROFF
|
||||
Entry state RUNNING
|
||||
Entry state WASHING
|
||||
Entry state DRYING
|
||||
Event RESTOREPOWER send
|
||||
----
|
||||
|
||||
What happened in above run:
|
||||
|
||||
* State machine is started which causes machine to get initialized.
|
||||
* We go to RINSING state.
|
||||
* We go to DRYING state.
|
||||
* We cut power and go to POWEROFF state.
|
||||
* State is restored via HISTORY state which takes state machine back
|
||||
to its previous known state.
|
||||
|
||||
|
||||
@@ -22,6 +22,15 @@ Statemachine is configured and how it leverages Spring's lightweight
|
||||
IoC containers to simplify the application internals to make it more
|
||||
manageable.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Configuration examples in this section are not feature complete, i.e.
|
||||
you always need to have definitions of both states and transitions,
|
||||
otherwise state machine configuration would be ill-formed. We have
|
||||
simply made code snippets less verbose by leaving other needed parts
|
||||
away.
|
||||
====
|
||||
|
||||
=== Configuring States
|
||||
We'll get into more complex configuration examples a bit later but
|
||||
lets first start with a something simple. For most simple state
|
||||
@@ -43,6 +52,20 @@ particular states are sub-states of some other state.
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetB]
|
||||
----
|
||||
|
||||
=== Configuring Regions
|
||||
|
||||
There are no special configuration methods to mark a collection of
|
||||
states to be part of a orthogonal state. To put it simple, orthogonal
|
||||
state is created when same hierarchical state machine has multiple set
|
||||
of states each having a initial state. Because a individual state
|
||||
machine can only have one initial state, multiple initial states mush
|
||||
mean that a specific state mush have multiple independent regions.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetP]
|
||||
----
|
||||
|
||||
=== Configuring Transitions
|
||||
We support three different types of transitions, `external`,
|
||||
`internal` and `local`. Transitions are either triggered by a signal
|
||||
@@ -80,6 +103,93 @@ Actions can be defined with various steps within a state transitions.
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetE]
|
||||
----
|
||||
|
||||
=== Configuring Pseudo States
|
||||
|
||||
_Pseudo state_ configuration is usually done by configuring states and
|
||||
transitions. Pseudo states are automatically added to state machine as
|
||||
states.
|
||||
|
||||
==== Initial State
|
||||
Simply mark a particular state as initial state by using `initial()`
|
||||
method. There are two methods where one takes extra argument to define
|
||||
an initial action. This initial action is good for example initialize
|
||||
extended state variables.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetQ]
|
||||
----
|
||||
|
||||
==== Terminate State
|
||||
Simply mark a particular state as end state by using `end()` method.
|
||||
This can be done max one time per individual sub-machine or region.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetA]
|
||||
----
|
||||
|
||||
==== History State
|
||||
History state can be defined once for each individual state machine.
|
||||
You need to choose its state identifier and `History.SHALLOW` or
|
||||
`History.DEEP` respectively.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetR]
|
||||
----
|
||||
|
||||
==== Choice State
|
||||
Choice needs to be defined in both states and transitions to work
|
||||
properly. Mark particular state as choice state by using `choice()`
|
||||
method. This state needs to match source state when transition is
|
||||
configured for this choice.
|
||||
|
||||
Transition is configured using `withChoice()` where you define source
|
||||
state and `first/then/last` structure which is equivalent to normal
|
||||
`if/elseif/else`. With `first` and `then` you can specify a guard just
|
||||
like you'd use a condition with `if/elseif` clauses.
|
||||
|
||||
Transition needs to be able to exist so make sure `last` is used.
|
||||
Otherwise configuration is ill-formed.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetS]
|
||||
----
|
||||
|
||||
==== Fork State
|
||||
Fork needs to be defined in both states and transitions to work
|
||||
properly. Mark particular state as choice state by using `fork()`
|
||||
method. This state needs to match source state when transition is
|
||||
configured for this fork.
|
||||
|
||||
Target state needs to be a super state or immediate states in
|
||||
regions. Using a super state as target will take all regions into
|
||||
initial states. Targeting individual state give more controlled entry
|
||||
into regions.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetT]
|
||||
----
|
||||
|
||||
==== Join State
|
||||
Join needs to be defined in both states and transitions to work
|
||||
properly. Mark particular state as choice state by using `join()`
|
||||
method. This state doesn't need to match either source states or
|
||||
target state in a transition configuretion.
|
||||
|
||||
Select one target state where transition goes when all source states
|
||||
has been joined. If you use state hosting regions as source, end
|
||||
states of a regions are used as joins. Otherwise you can pick any
|
||||
states from a regions.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::samples/DocsConfigurationSampleTests.java[tags=snippetU]
|
||||
----
|
||||
|
||||
[[sm-factories]]
|
||||
== State Machine Factories
|
||||
There are use cases when state machine needs to be created dynamically
|
||||
|
||||
Reference in New Issue
Block a user