mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-17 13:53:49 +00:00
add kdocs
This commit is contained in:
parent
e3da761249
commit
bc7789ad2c
@ -2,13 +2,25 @@ package dev.inmo.micro_utils.fsm.common
|
|||||||
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default realization of [StatesHandler]. It will incapsulate checking of [State] type in [checkHandleable] and class
|
||||||
|
* casting in [handleState]
|
||||||
|
*/
|
||||||
class StateHandlerHolder<I : State>(
|
class StateHandlerHolder<I : State>(
|
||||||
private val inputKlass: KClass<I>,
|
private val inputKlass: KClass<I>,
|
||||||
private val strict: Boolean = false,
|
private val strict: Boolean = false,
|
||||||
private val delegateTo: StatesHandler<I>
|
private val delegateTo: StatesHandler<I>
|
||||||
) : StatesHandler<State> {
|
) : StatesHandler<State> {
|
||||||
|
/**
|
||||||
|
* Checks that [state] can be handled by [delegateTo]. Under the hood it will check exact equality of [state]
|
||||||
|
* [KClass] and use [KClass.isInstance] of [inputKlass] if [strict] == false
|
||||||
|
*/
|
||||||
fun checkHandleable(state: State) = state::class == inputKlass || (!strict && inputKlass.isInstance(state))
|
fun checkHandleable(state: State) = state::class == inputKlass || (!strict && inputKlass.isInstance(state))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls [delegateTo] method [StatesHandler.handleState] with [state] casted to [I]. Use [checkHandleable]
|
||||||
|
* to be sure that this [StateHandlerHolder] will be able to handle [state]
|
||||||
|
*/
|
||||||
override suspend fun StatesMachine.handleState(state: State): State? {
|
override suspend fun StatesMachine.handleState(state: State): State? {
|
||||||
return delegateTo.run { handleState(state as I) }
|
return delegateTo.run { handleState(state as I) }
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
package dev.inmo.micro_utils.fsm.common
|
package dev.inmo.micro_utils.fsm.common
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default realization of states handler
|
||||||
|
*/
|
||||||
fun interface StatesHandler<I : State> {
|
fun interface StatesHandler<I : State> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
suspend fun StatesMachine.handleState(state: I): State?
|
suspend fun StatesMachine.handleState(state: I): State?
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,20 @@ private suspend fun <I : State> StatesMachine.launchStateHandling(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default [StatesMachine] may [startChain] and use inside logic for handling [State]s. By default you may use
|
||||||
|
* [DefaultStatesMachine] or build it with [dev.inmo.micro_utils.fsm.common.dsl.buildFSM]. Implementers MUST NOT start
|
||||||
|
* handling until [start] method will be called
|
||||||
|
*/
|
||||||
interface StatesMachine : StatesHandler<State> {
|
interface StatesMachine : StatesHandler<State> {
|
||||||
|
/**
|
||||||
|
* Starts handling of [State]s
|
||||||
|
*/
|
||||||
fun start(scope: CoroutineScope): Job
|
fun start(scope: CoroutineScope): Job
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start chain of [State]s witn [state]
|
||||||
|
*/
|
||||||
suspend fun startChain(state: State)
|
suspend fun startChain(state: State)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -28,12 +40,25 @@ interface StatesMachine : StatesHandler<State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default realization of [StatesMachine]. It uses [statesManager] for incapsulation of [State]s storing and contexts
|
||||||
|
* resolving, and uses [launchStateHandling] for [State] handling
|
||||||
|
*/
|
||||||
class DefaultStatesMachine (
|
class DefaultStatesMachine (
|
||||||
private val statesManager: StatesManager,
|
private val statesManager: StatesManager,
|
||||||
private val handlers: List<StateHandlerHolder<*>>
|
private val handlers: List<StateHandlerHolder<*>>
|
||||||
) : StatesMachine {
|
) : StatesMachine {
|
||||||
|
/**
|
||||||
|
* Will call [launchStateHandling] for state handling
|
||||||
|
*/
|
||||||
override suspend fun StatesMachine.handleState(state: State): State? = launchStateHandling(state, handlers)
|
override suspend fun StatesMachine.handleState(state: State): State? = launchStateHandling(state, handlers)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch handling of states. On [statesManager] [StatesManager.onStartChain],
|
||||||
|
* [statesManager] [StatesManager.onChainStateUpdated] will be called lambda with performing of state. If
|
||||||
|
* [launchStateHandling] will returns some [State] then [statesManager] [StatesManager.update] will be used, otherwise
|
||||||
|
* [StatesManager.endChain].
|
||||||
|
*/
|
||||||
override fun start(scope: CoroutineScope): Job = scope.launchSafelyWithoutExceptions {
|
override fun start(scope: CoroutineScope): Job = scope.launchSafelyWithoutExceptions {
|
||||||
val statePerformer: suspend (State) -> Unit = { state: State ->
|
val statePerformer: suspend (State) -> Unit = { state: State ->
|
||||||
val newState = launchStateHandling(state, handlers)
|
val newState = launchStateHandling(state, handlers)
|
||||||
@ -55,6 +80,9 @@ class DefaultStatesMachine (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just calls [StatesManager.startChain] of [statesManager]
|
||||||
|
*/
|
||||||
override suspend fun startChain(state: State) {
|
override suspend fun startChain(state: State) {
|
||||||
statesManager.startChain(state)
|
statesManager.startChain(state)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ import kotlinx.coroutines.flow.*
|
|||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement this repo if you want to use some custom repo for [DefaultStatesManager]
|
||||||
|
*/
|
||||||
interface DefaultStatesManagerRepo {
|
interface DefaultStatesManagerRepo {
|
||||||
/**
|
/**
|
||||||
* Must save [state] as current state of chain with [State.context] of [state]
|
* Must save [state] as current state of chain with [State.context] of [state]
|
||||||
@ -29,18 +32,19 @@ interface DefaultStatesManagerRepo {
|
|||||||
/**
|
/**
|
||||||
* @return Current state by [context]
|
* @return Current state by [context]
|
||||||
*/
|
*/
|
||||||
suspend fun contains(context: Any): Boolean
|
suspend fun contains(context: Any): Boolean = getContextState(context) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param repo This repo will be used as repository for storing states. All operations with this repo will happen BEFORE
|
||||||
|
* any event will be sent to [onChainStateUpdated], [onStartChain] or [onEndChain]. By default will be used
|
||||||
|
* [InMemoryDefaultStatesManagerRepo] or you may create custom [DefaultStatesManagerRepo] and pass as [repo] parameter
|
||||||
* @param onContextsConflictResolver Receive old [State], new one and the state currently placed on new [State.context]
|
* @param onContextsConflictResolver Receive old [State], new one and the state currently placed on new [State.context]
|
||||||
* key. In case when this callback will returns true, the state placed on [State.context] of new will be replaced by
|
* key. In case when this callback will returns true, the state placed on [State.context] of new will be replaced by
|
||||||
* new state by using [endChain] with that state
|
* new state by using [endChain] with that state
|
||||||
* @param repo This repo will be used as repository for storing states. All operations with this repo will happen BEFORE
|
|
||||||
* any event will be sent to [onChainStateUpdated], [onStartChain] or [onEndChain].
|
|
||||||
*/
|
*/
|
||||||
class DefaultStatesManager(
|
class DefaultStatesManager(
|
||||||
private val repo: DefaultStatesManagerRepo,
|
private val repo: DefaultStatesManagerRepo = InMemoryDefaultStatesManagerRepo(),
|
||||||
private val onContextsConflictResolver: suspend (old: State, new: State, currentNew: State) -> Boolean = { _, _, _ -> true }
|
private val onContextsConflictResolver: suspend (old: State, new: State, currentNew: State) -> Boolean = { _, _, _ -> true }
|
||||||
) : StatesManager {
|
) : StatesManager {
|
||||||
private val _onChainStateUpdated = MutableSharedFlow<Pair<State, State>>(0)
|
private val _onChainStateUpdated = MutableSharedFlow<Pair<State, State>>(0)
|
||||||
|
@ -2,6 +2,10 @@ package dev.inmo.micro_utils.fsm.common.managers
|
|||||||
|
|
||||||
import dev.inmo.micro_utils.fsm.common.State
|
import dev.inmo.micro_utils.fsm.common.State
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple [DefaultStatesManagerRepo] for [DefaultStatesManager] which will store data in [map] and use primitive
|
||||||
|
* functionality
|
||||||
|
*/
|
||||||
class InMemoryDefaultStatesManagerRepo(
|
class InMemoryDefaultStatesManagerRepo(
|
||||||
private val map: MutableMap<Any, State> = mutableMapOf()
|
private val map: MutableMap<Any, State> = mutableMapOf()
|
||||||
) : DefaultStatesManagerRepo {
|
) : DefaultStatesManagerRepo {
|
||||||
|
Loading…
Reference in New Issue
Block a user