StateMachine

Types

Link copied to clipboard
data class CreationArguments(val autoDestroyOnStatesReuse: Boolean = true, val isUndoEnabled: Boolean = false, val doNotThrowOnMultipleTransitionsMatch: Boolean = false, val requireNonBlankNames: Boolean = false, val eventRecordingArguments: StateMachine.EventRecordingArguments? = null)
Link copied to clipboard
data class EventRecordingArguments(val clearRecordsOnMachineRestart: Boolean = true, val skipIgnoredEvents: Boolean = true)
Link copied to clipboard
fun interface IgnoredEventHandler
Link copied to clipboard
interface Listener

Provides StateMachine specific notifications and also duplicates IState.Listener and Transition.Listener functionality allowing to listen all notifications in one place if necessary.

Link copied to clipboard
Link copied to clipboard
fun interface Logger

State machine uses this interface to support internal logging on different platforms

Link copied to clipboard
fun interface PendingEventHandler

Properties

Link copied to clipboard
abstract val childMode: ChildMode
Link copied to clipboard
Link copied to clipboard

Configuration arguments which were used to create the machine

Link copied to clipboard
Link copied to clipboard

Indicates that machine is started and has clear initial state (has not processed any events but StartEvent yet)

Link copied to clipboard
abstract val initialState: IState?
Link copied to clipboard
abstract val isActive: Boolean
Link copied to clipboard
abstract val isDestroyed: Boolean

Indicates that machine was destroyed. There is no way to restore machine instance from this state. Once machine became destroyed it is not usable anymore.

Link copied to clipboard
abstract val isFinished: Boolean
Link copied to clipboard
abstract val isRunning: Boolean

Indicates whether the machine is started or stopped.

Link copied to clipboard

If machine catches exception from client code (listeners callbacks) it stores it until event processing completes, and passes it to this handler. That keeps machine in well-defined predictable state and allows to complete all required notifications. Note that generally speaking listeners should not throw.

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
abstract val machine: StateMachine
Link copied to clipboard
Link copied to clipboard
abstract var metaInfo: MetaInfo?

Might be changed only during machine setup.

Link copied to clipboard
abstract val name: String?
Link copied to clipboard
abstract val parent: IState?
Link copied to clipboard
abstract var payload: Any?

Arbitrary user defined data. The property allows to store some data in a state without subclassing it. This might be handy in same simple use cases.

Link copied to clipboard
abstract val states: Set<IState>
Link copied to clipboard
Link copied to clipboard
abstract val transitions: Set<Transition<*>>

Functions

Link copied to clipboard
open suspend override fun accept(visitor: CoVisitor)
open override fun accept(visitor: Visitor)
Link copied to clipboard
fun IState.activeStates(selfIncluding: Boolean = false): Set<IState>

Set of states that the state is currently in. Including state itself if selfIncluding is true. Internal states of nested machines are not included.

Link copied to clipboard
fun <S : IFinalState> IState.addFinalState(state: S, init: StateBlock<S>? = null): S

Helper method for adding final states. This is exactly the same as simply call IState.addState but makes code more self expressive.

Link copied to clipboard
fun <S : IState> IState.addInitialState(state: S, init: StateBlock<S>? = null): S

A shortcut for IState.addState and IState.setInitialState calls

Link copied to clipboard
abstract fun <L : IState.Listener> addListener(listener: L): L
abstract fun <L : StateMachine.Listener> addListener(listener: L): L
Link copied to clipboard
abstract fun <S : IState> addState(state: S, init: StateBlock<S>? = null): S
Link copied to clipboard
abstract fun <E : Event> addTransition(transition: Transition<E>): Transition<E>
Link copied to clipboard
abstract fun asState(): IState

For internal use only

Link copied to clipboard
Link copied to clipboard
inline fun <D : Any> IState.choiceDataState(name: String? = null, noinline choiceAction: suspend EventAndArgument<*>.() -> DataState<D>): DefaultChoiceDataState<D>
Link copied to clipboard
fun IState.choiceState(name: String? = null, choiceAction: suspend EventAndArgument<*>.() -> State): DefaultChoiceState
Link copied to clipboard
inline fun <D : Any> IState.dataState(name: String? = null, defaultData: D? = null, childMode: ChildMode = ChildMode.EXCLUSIVE, dataExtractor: DataExtractor<D> = defaultDataExtractor(), noinline init: StateBlock<DataState<D>>? = null): DefaultDataState<D>
Link copied to clipboard

Creates type safe argument transition to DataState.

inline fun <E : DataEvent<D>, D : Any> TransitionStateApi.dataTransition(name: String? = null, targetState: DataState<D>, type: TransitionType = LOCAL, metaInfo: MetaInfo? = null): Transition<E>

Shortcut function for type safe argument transition. Data transition can be target-less (self-targeted), it is useful to update DataState data Note that transition must be TransitionType.EXTERNAL to update data.

Link copied to clipboard

Data transition, otherwise same as transitionOn

Link copied to clipboard
suspend fun StateMachine.destroy(stop: Boolean = true)

Destroys machine structure clearing all listeners, states etc.

Link copied to clipboard

Blocking analog of destroy

Link copied to clipboard
suspend fun StateMachine.exportToMermaid(showEventLabels: Boolean = false, unsafeCallConditionalLambdas: Boolean = false): String

Export StateMachine to Mermaid state diagram

Link copied to clipboard
fun StateMachine.exportToMermaidBlocking(showEventLabels: Boolean = false, unsafeCallConditionalLambdas: Boolean = false): String

Blocking analog for exportToMermaid

Link copied to clipboard
suspend fun StateMachine.exportToPlantUml(showEventLabels: Boolean = false, unsafeCallConditionalLambdas: Boolean = false): String

Export StateMachine to PlantUML state diagram

Link copied to clipboard
fun StateMachine.exportToPlantUmlBlocking(showEventLabels: Boolean = false, unsafeCallConditionalLambdas: Boolean = false): String

Blocking analog for exportToPlantUml

Link copied to clipboard
inline fun <D : Any> IState.finalDataState(name: String? = null, defaultData: D? = null, dataExtractor: DataExtractor<D> = defaultDataExtractor(), noinline init: StateBlock<FinalDataState<D>>? = null): DefaultFinalDataState<D>
Link copied to clipboard
fun IState.finalState(name: String? = null, init: StateBlock<FinalState>? = null): DefaultFinalState
Link copied to clipboard
inline fun <S : IState> IState.findState(recursive: Boolean = true): S?

Find state by type. Search by type is suitable when using own state subclasses that usually do not have a name. Only on state should match the type or exception will be thrown.

fun IState.findState(name: String, recursive: Boolean = true): IState?

Get state by name. This might be used to start listening to state after state machine setup.

fun <S : IState> IState.findState(class: KClass<S>, recursive: Boolean = true): S?

For internal use. Workaround that Kotlin does not support recursive inline functions.

Link copied to clipboard

Find transition by Event type. This might be used to start listening to transition after state machine setup.

Find transition by name. This might be used to start listening to transition after state machine setup.

Link copied to clipboard
Link copied to clipboard
fun IState.historyState(name: String? = null, defaultState: IState? = null, historyType: HistoryType = HistoryType.SHALLOW): DefaultHistoryState
Link copied to clipboard
inline fun <D : Any> IState.initialChoiceDataState(name: String? = null, noinline choiceAction: suspend EventAndArgument<*>.() -> DataState<D>): DefaultChoiceDataState<D>
Link copied to clipboard
fun IState.initialChoiceState(name: String? = null, choiceAction: suspend EventAndArgument<*>.() -> State): DefaultChoiceState
Link copied to clipboard
inline fun <D : Any> IState.initialDataState(name: String? = null, defaultData: D, childMode: ChildMode = ChildMode.EXCLUSIVE, dataExtractor: DataExtractor<D> = defaultDataExtractor(), noinline init: StateBlock<DataState<D>>? = null): DefaultDataState<D>
Link copied to clipboard
inline fun <D : Any> IState.initialFinalDataState(name: String? = null, defaultData: D? = null, dataExtractor: DataExtractor<D> = defaultDataExtractor(), noinline init: StateBlock<FinalDataState<D>>? = null): DefaultFinalDataState<D>
Link copied to clipboard
Link copied to clipboard
fun IState.initialState(name: String? = null, childMode: ChildMode = ChildMode.EXCLUSIVE, init: StateBlock<State>? = null): DefaultState

A shortcut for state and IState.setInitialState calls

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
suspend fun IState.log(lazyMessage: () -> String)
Link copied to clipboard
Link copied to clipboard
open suspend fun onCleanup()

Called when state is sequentially used on multiple machine instances, to perform cleanup steps.

Link copied to clipboard
inline fun StateMachine.onDestroyed(crossinline block: suspend StateMachine.() -> Unit): StateMachine.Listener
Link copied to clipboard
inline fun StateMachine.onStarted(crossinline block: suspend StateMachine.(TransitionParams<*>) -> Unit): StateMachine.Listener
Link copied to clipboard
Link copied to clipboard
inline fun StateMachine.onStateExit(crossinline block: suspend StateMachine.(IState, TransitionParams<*>) -> Unit): StateMachine.Listener
Link copied to clipboard
Link copied to clipboard
open suspend fun onStopped()

Called when machine is stopped, to perform cleanup steps.

Link copied to clipboard
inline fun StateMachine.onStopped(crossinline block: suspend StateMachine.() -> Unit): StateMachine.Listener
Link copied to clipboard
inline fun StateMachine.onTransitionComplete(crossinline block: suspend StateMachine.(activeStates: Set<IState>, TransitionParams<*>) -> Unit): StateMachine.Listener
Link copied to clipboard
Link copied to clipboard
abstract suspend fun processEvent(event: Event, argument: Any? = null): ProcessingResult

Processes Event. Machine must be started to be able to process events.

Link copied to clipboard

Blocking analog of StateMachine.processEvent which can be called from usual (not suspendable) code.

Link copied to clipboard
abstract fun removeListener(listener: IState.Listener)
abstract fun removeListener(listener: StateMachine.Listener)
Link copied to clipboard
Link copied to clipboard
inline fun <S : IState> IState.requireState(recursive: Boolean = true): S

Require state by type

fun IState.requireState(name: String, recursive: Boolean = true): IState
Link copied to clipboard

Require transition by Event type

Link copied to clipboard
suspend fun StateMachine.restart(argument: Any? = null)

Shortcut for StateMachine.stopBlocking and StateMachine.start sequence calls

Link copied to clipboard
fun StateMachine.restartBlocking(argument: Any? = null)
Link copied to clipboard
suspend fun StateMachine.restoreByRecordedEvents(recordedEvents: RecordedEvents, muteListeners: Boolean = true, disableStructureHashCodeCheck: Boolean = false, validator: RestorationResultValidator = StrictValidator): RestorationResult

Processes RecordedEvents with purpose of restoring a StateMachine to a state configuration as it was before (when the record was made). Starts the StateMachine if necessary and returns RestorationResult allowing to inspect how the restoration was processed. Specified RestorationResultValidator will be called to validate the result so do not have to remember to perform validation of the RestorationResult.

Link copied to clipboard
fun StateMachine.restoreByRecordedEventsBlocking(recordedEvents: RecordedEvents, muteListeners: Boolean = true, disableStructureHashCodeCheck: Boolean = false)

Blocking restoreByRecordedEvents alternative

Link copied to clipboard
abstract fun setInitialState(state: IState)

Initial child state is required if child mode is ChildMode.EXCLUSIVE and a state has children

Link copied to clipboard
abstract suspend fun start(argument: Any? = null)

Starts state machine

Link copied to clipboard
fun StateMachine.startBlocking(argument: Any? = null)
Link copied to clipboard
suspend fun StateMachine.startFrom(stateName: String, argument: Any? = null)
suspend fun <D : Any> StateMachine.startFrom(state: DataState<D>, data: D, argument: Any? = null)

suspend fun StateMachine.startFrom(states: Set<IState>, argument: Any? = null)

Allows to target multiple states (they must be parallel state sub-children). Implemented by targetParallelStates

suspend fun StateMachine.startFrom(state: IState, argument: Any? = null)

Starts machine from particular state

suspend fun StateMachine.startFrom(state1: IState, state2: IState, vararg states: IState, argument: Any? = null)

Vararg overload for targeting multiple states

Link copied to clipboard
fun StateMachine.startFromBlocking(stateName: String, argument: Any? = null)
fun StateMachine.startFromBlocking(states: Set<IState>, argument: Any? = null)
fun StateMachine.startFromBlocking(state: IState, argument: Any? = null)
fun <D : Any> StateMachine.startFromBlocking(state: DataState<D>, data: D, argument: Any? = null)
fun StateMachine.startFromBlocking(state1: IState, state2: IState, vararg states: IState, argument: Any? = null)
Link copied to clipboard
fun IState.state(name: String? = null, childMode: ChildMode = ChildMode.EXCLUSIVE, init: StateBlock<State>? = null): DefaultState
Link copied to clipboard
suspend fun StateMachine.stop()

Suspendable stopBlocking analog. Should be preferred especially if called from machine notifications.

Link copied to clipboard

Forces state machine to stop Warning: calling this function from notification callback may cause deadlock if you are using single threaded coroutineContext, so stop should be preferred.

Link copied to clipboard

Returns StateMachine.IgnoredEventHandler implementation that throws exception. This might be useful if you want to control that all events are handled (not skipped) by your StateMachine.

Link copied to clipboard

Returns StateMachine.PendingEventHandler implementation that throws exception. This is an old default behaviour.

Link copied to clipboard
inline fun <E : Event> TransitionStateApi.transition(name: String? = null, block: UnitGuardedTransitionBuilder<E>.() -> Unit): Transition<E>

Creates transition. You can specify guard function. Such guarded transition is triggered only when guard function returns true.

inline fun <E : Event> TransitionStateApi.transition(name: String? = null, targetState: State? = null, type: TransitionType = LOCAL, metaInfo: MetaInfo? = null): Transition<E>

Shortcut overload for transition with an optional target state

Link copied to clipboard

Creates conditional transition. Caller should specify lambda which calculates TransitionDirection. For example target state may be different depending on some condition.

Link copied to clipboard

This is more powerful version of transition function. Here target state is a lambda which returns desired State. This allows to use lateinit state variables for recursively depending states and choose target state depending on application business logic.

Link copied to clipboard
suspend fun StateMachine.undo(argument: Any? = null): ProcessingResult

Rolls back transition (usually it is navigating machine to previous state). Previous states are stored in a stack, so this method mey be called multiple times if needed. This function has same effect as alternative syntax processEvent(UndoEvent), but throws if undo feature is not enabled.

Link copied to clipboard

Blocking analog of undo