From bc7789ad2c38d603d82947890d417f6418599002 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 13 Oct 2021 15:06:58 +0600 Subject: [PATCH] add kdocs --- .../fsm/common/StateHandlerHolder.kt | 12 ++++++++ .../micro_utils/fsm/common/StatesHandler.kt | 6 ++++ .../micro_utils/fsm/common/StatesMachine.kt | 28 +++++++++++++++++++ .../common/managers/DefaultStatesManager.kt | 12 +++++--- .../InMemoryDefaultStatesManagerRepo.kt | 4 +++ 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StateHandlerHolder.kt b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StateHandlerHolder.kt index 5b06f317c16..a92f9b96602 100644 --- a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StateHandlerHolder.kt +++ b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StateHandlerHolder.kt @@ -2,13 +2,25 @@ package dev.inmo.micro_utils.fsm.common import kotlin.reflect.KClass +/** + * Default realization of [StatesHandler]. It will incapsulate checking of [State] type in [checkHandleable] and class + * casting in [handleState] + */ class StateHandlerHolder( private val inputKlass: KClass, private val strict: Boolean = false, private val delegateTo: StatesHandler ) : StatesHandler { + /** + * 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)) + /** + * 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? { return delegateTo.run { handleState(state as I) } } diff --git a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesHandler.kt b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesHandler.kt index b152b38dea6..0dd89843a27 100644 --- a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesHandler.kt +++ b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesHandler.kt @@ -1,5 +1,11 @@ package dev.inmo.micro_utils.fsm.common +/** + * Default realization of states handler + */ fun interface StatesHandler { + /** + * + */ suspend fun StatesMachine.handleState(state: I): State? } diff --git a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesMachine.kt b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesMachine.kt index dde2cdc11b2..11170c5b030 100644 --- a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesMachine.kt +++ b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/StatesMachine.kt @@ -13,8 +13,20 @@ private suspend fun 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 { + /** + * Starts handling of [State]s + */ fun start(scope: CoroutineScope): Job + + /** + * Start chain of [State]s witn [state] + */ suspend fun startChain(state: State) companion object { @@ -28,12 +40,25 @@ interface StatesMachine : StatesHandler { } } +/** + * Default realization of [StatesMachine]. It uses [statesManager] for incapsulation of [State]s storing and contexts + * resolving, and uses [launchStateHandling] for [State] handling + */ class DefaultStatesMachine ( private val statesManager: StatesManager, private val handlers: List> ) : StatesMachine { + /** + * Will call [launchStateHandling] for state handling + */ 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 { val statePerformer: suspend (State) -> Unit = { state: State -> val newState = launchStateHandling(state, handlers) @@ -55,6 +80,9 @@ class DefaultStatesMachine ( } } + /** + * Just calls [StatesManager.startChain] of [statesManager] + */ override suspend fun startChain(state: State) { statesManager.startChain(state) } diff --git a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/managers/DefaultStatesManager.kt b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/managers/DefaultStatesManager.kt index 3479ff53637..3488e0ac7d3 100644 --- a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/managers/DefaultStatesManager.kt +++ b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/managers/DefaultStatesManager.kt @@ -6,6 +6,9 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock +/** + * Implement this repo if you want to use some custom repo for [DefaultStatesManager] + */ interface DefaultStatesManagerRepo { /** * Must save [state] as current state of chain with [State.context] of [state] @@ -29,18 +32,19 @@ interface DefaultStatesManagerRepo { /** * @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] * 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 - * @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( - private val repo: DefaultStatesManagerRepo, + private val repo: DefaultStatesManagerRepo = InMemoryDefaultStatesManagerRepo(), private val onContextsConflictResolver: suspend (old: State, new: State, currentNew: State) -> Boolean = { _, _, _ -> true } ) : StatesManager { private val _onChainStateUpdated = MutableSharedFlow>(0) diff --git a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/managers/InMemoryDefaultStatesManagerRepo.kt b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/managers/InMemoryDefaultStatesManagerRepo.kt index 211d3f5370d..70051e14d07 100644 --- a/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/managers/InMemoryDefaultStatesManagerRepo.kt +++ b/fsm/common/src/commonMain/kotlin/dev/inmo/micro_utils/fsm/common/managers/InMemoryDefaultStatesManagerRepo.kt @@ -2,6 +2,10 @@ package dev.inmo.micro_utils.fsm.common.managers import dev.inmo.micro_utils.fsm.common.State +/** + * Simple [DefaultStatesManagerRepo] for [DefaultStatesManager] which will store data in [map] and use primitive + * functionality + */ class InMemoryDefaultStatesManagerRepo( private val map: MutableMap = mutableMapOf() ) : DefaultStatesManagerRepo {