All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kdux.DefaultStore.kt Maven / Gradle / Ivy

package org.mattshoe.shoebox.kdux

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

val __internalstateOverride = mutableMapOf>()

/**
 * Default implementation of the [Store] interface that manages the state and handles
 * dispatched actions by passing them through the middleware chain and then reducing them into a new state.
 * The store updates its state flow, allowing observers to track state changes over time.
 *
 * @param State The type of state that this store holds. It must be a non-nullable type (`Any`).
 * @param Action The type of actions that can be dispatched to the store. It must be a non-nullable type (`Any`).
 * @property initialState The initial state of the store when it is created.
 * @property reducer The reducer function that determines how the state should change when an action is dispatched.
 * @property middlewares A list of middlewares that intercept and process the actions before they reach the reducer.
 */
internal class DefaultStore(
    customName: String? = null,
    private val initialState: State,
    private val reducer: Reducer,
    private val middlewares: List> = emptyList()
) : Store {
    private val _state = MutableStateFlow(initialState)

    override val name = customName ?: super.toString()
    override val state: Flow = _state.asStateFlow()
    override val currentState: State
        get() = _state.value

    init {
        __internalstateOverride[name] = _state
    }

    override suspend fun dispatch(action: Action) {
        processMiddleware(0, action)
    }

    override fun toString(): String {
        return name
    }

    /**
     * Recursively processes the middleware chain. Each middleware can intercept, modify, or block
     * the action before it is passed to the next middleware or the reducer.
     *
     * This function is called recursively to process each middleware in sequence. Once all middleware
     * has been processed, the action is passed to the reducer to update the state.
     *
     * @param index The current index in the middleware list. Used to determine which middleware to apply next.
     * @param action The action currently being processed by the middleware chain.
     */
    private suspend fun processMiddleware(index: Int, action: Action) {
        if (index < middlewares.size) {
            val nextMiddleware = middlewares[index]
            nextMiddleware.apply(this, action) { nextAction ->
                processMiddleware(index + 1, nextAction)
            }
        } else {
            // No more middleware, reduce the action and update the state
            reduceAndUpdate(action)
        }
    }

    /**
     * Reduces the current state based on the dispatched action using the provided reducer function.
     * The reducer is responsible for determining how the state should change based on the given action.
     *
     * This method updates the internal state and notifies any observers of the new state.
     *
     * @param action The action to be reduced. This action determines how the state will be updated.
     */
    private suspend fun reduceAndUpdate(action: Action) {
        _state.update {
            reducer.reduce(_state.value, action)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy