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

commonMain.dev.inmo.micro_utils.repos.KeyValueRepo.kt Maven / Gradle / Ivy

There is a newer version: 0.22.2
Show newest version
package dev.inmo.micro_utils.repos

import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.doAllWithCurrentPaging
import dev.inmo.micro_utils.pagination.utils.getAllByWithNextPaging
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
import dev.inmo.micro_utils.pagination.utils.paginate
import dev.inmo.micro_utils.repos.pagination.maxPagePagination
import kotlinx.coroutines.flow.Flow

/**
 * Read part of [KeyValueRepo]
 *
 * @param Key This type will be used as key in all operations related to searches of data
 * @param Value This type will be used as returning data in most "get" operations
 */
interface ReadKeyValueRepo : Repo {
    /**
     * @return Result [Value] in case when it is presented in repo by its [k] or null otherwise
     */
    suspend fun get(k: Key): Value?

    /**
     * This method should use sorted by [Key]s search and return the [PaginationResult]. By default, it should use
     * ascending sort for [Key]s
     */
    suspend fun values(pagination: Pagination, reversed: Boolean = false): PaginationResult

    /**
     * This method should use sorted by [Key]s search and return the [PaginationResult]. By default, it should use
     * ascending sort for [Key]s
     */
    suspend fun keys(pagination: Pagination, reversed: Boolean = false): PaginationResult

    /**
     * This method should use sorted by [Key]s search and return the [PaginationResult]. By default, it should use
     * ascending sort for [Key]s.
     *
     * **DEFAULT REALIZATION IS NOT OPTIMAL AND HAS BEEN ADDED TO COVER CASES OF DIFFERENT COMMON MAPPINGS AND TRANSFORMATIONS**
     *
     * @param v This value should be used to exclude from search the items with different [Value]s
     */
    suspend fun keys(v: Value, pagination: Pagination, reversed: Boolean = false): PaginationResult {
        return getAllWithNextPaging {
            keys(it)
        }.filter {
            get(it) == v
        }.paginate(pagination, reversed)
    }

    /**
     * @return true if [key] is presented in current collection or false otherwise
     */
    suspend fun contains(key: Key): Boolean

    suspend fun getAll(): Map = getAllByWithNextPaging(maxPagePagination()) {
        keys(it).let {
            it.changeResultsUnchecked(
                it.results.mapNotNull {
                    it to (get(it) ?: return@mapNotNull null)
                }
            )
        }
    }.toMap()

    /**
     * @return count of all collection objects
     */
    suspend fun count(): Long
}
typealias ReadStandardKeyValueRepo = ReadKeyValueRepo

/**
 * Write part of [KeyValueRepo]
 *
 * @param Key This type will be used as key in all operations related to changes of data
 * @param Value This type will be used as incoming data in most operations
 */
interface WriteKeyValueRepo : Repo {
    /**
     * This flow must emit data each time when data by [Key] has been changed with [set] method or in any other way
     * excluding cases of data removing
     *
     * @see onValueRemoved
     */
    val onNewValue: Flow>

    /**
     * This flow must emit data each time when data by [Key] has been removed with [unset]/[unsetWithValues] methods or
     * in any other way
     *
     * @see onNewValue
     */
    val onValueRemoved: Flow

    /**
     * Will set as batch [toSet] data in current repo. Must pass the data which were successfully updated in repo to
     * [onNewValue]
     */
    suspend fun set(toSet: Map)
    /**
     * Will unset as batch data with keys from [toUnset]. Must pass the [Key]s which were successfully removed in repo to
     * [onValueRemoved]
     */
    suspend fun unset(toUnset: List)
    /**
     * Will unset as batch data with values from [toUnset]. Must pass the [Key]s which were successfully removed in repo
     * to [onValueRemoved]
     */
    suspend fun unsetWithValues(toUnset: List)
}
typealias WriteStandardKeyValueRepo = WriteKeyValueRepo

suspend inline fun  WriteKeyValueRepo.set(
    vararg toSet: Pair
) = set(toSet.toMap())

suspend inline fun  WriteKeyValueRepo.set(
    toSet: List>
) = set(toSet.toMap())

suspend inline fun  WriteKeyValueRepo.set(
    k: Key, v: Value
) = set(k to v)

suspend inline fun  WriteKeyValueRepo.unset(
    vararg k: Key
) = unset(k.toList())

suspend inline fun  WriteKeyValueRepo.unsetWithValues(
    vararg v: Value
) = unsetWithValues(v.toList())

/**
 * Full version of standard key-value repository with all set/unset/clear/get methods
 */
interface KeyValueRepo : ReadKeyValueRepo, WriteKeyValueRepo {
    /**
     * By default, will walk throw all the [keys] with [Value]s from [toUnset] and run [doAllWithCurrentPaging] with
     * [unset] of found data [Key]s
     */
    override suspend fun unsetWithValues(toUnset: List) = toUnset.forEach { v ->
        doAllWithCurrentPaging {
            keys(v, it).also {
                unset(it.results)
            }
        }
    }

    /**
     * By default, will remove all the data of current repo using [doAllWithCurrentPaging], [keys] and [unset]
     */
    suspend fun clear() {
        var count: Int
        do {
            count = count().takeIf { it < Int.MAX_VALUE } ?.toInt() ?: Int.MAX_VALUE
            keys(FirstPagePagination(count)).also { unset(it.results) }
        } while(count > 0)
    }
}
typealias StandardKeyValueRepo = KeyValueRepo

class DelegateBasedKeyValueRepo(
    readDelegate: ReadKeyValueRepo,
    writeDelegate: WriteKeyValueRepo
) : KeyValueRepo,
    ReadKeyValueRepo by readDelegate,
    WriteKeyValueRepo by writeDelegate




© 2015 - 2024 Weber Informatics LLC | Privacy Policy