From 0ba93d0e60807396849721a00f83d4ad3efa43fa Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Wed, 14 Oct 2020 14:22:58 +0600 Subject: [PATCH] add in memory map based crud implementation --- .../pagination/utils/IterableExtensions.kt | 35 ++++++++ repos/inmemory/build.gradle | 17 ++++ .../inmo/micro_utils/repos/HashMapCRUDRepo.kt | 89 +++++++++++++++++++ settings.gradle | 1 + 4 files changed, 142 insertions(+) create mode 100644 pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/IterableExtensions.kt create mode 100644 repos/inmemory/build.gradle create mode 100644 repos/inmemory/src/commonMain/kotlin/dev/inmo/micro_utils/repos/HashMapCRUDRepo.kt diff --git a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/IterableExtensions.kt b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/IterableExtensions.kt new file mode 100644 index 00000000000..4b6a5d97240 --- /dev/null +++ b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/IterableExtensions.kt @@ -0,0 +1,35 @@ +package dev.inmo.micro_utils.pagination.utils + +import dev.inmo.micro_utils.pagination.* + +fun Iterable.paginate(with: Pagination): PaginationResult { + var i = 0 + val result = mutableListOf() + val lowerIndex = with.firstIndex + val greatestIndex = with.lastIndex + for (item in this) { + when { + i < lowerIndex || i > greatestIndex -> i++ + else -> { + result.add(item) + i++ + } + } + } + + return result.createPaginationResult(with, i.toLong()) +} + +fun List.paginate(with: Pagination): PaginationResult { + return subList(with.firstIndex, with.lastIndex + 1).createPaginationResult( + with, + size.toLong() + ) +} + +fun Set.paginate(with: Pagination): PaginationResult { + return this.drop(with.firstIndex).take(with.size).createPaginationResult( + with, + size.toLong() + ) +} diff --git a/repos/inmemory/build.gradle b/repos/inmemory/build.gradle new file mode 100644 index 00000000000..162e4af700e --- /dev/null +++ b/repos/inmemory/build.gradle @@ -0,0 +1,17 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" +} + +apply from: "$mppProjectWithSerializationPresetPath" + +kotlin { + sourceSets { + commonMain { + dependencies { + api internalProject("micro_utils.repos.common") + api internalProject("micro_utils.coroutines") + } + } + } +} \ No newline at end of file diff --git a/repos/inmemory/src/commonMain/kotlin/dev/inmo/micro_utils/repos/HashMapCRUDRepo.kt b/repos/inmemory/src/commonMain/kotlin/dev/inmo/micro_utils/repos/HashMapCRUDRepo.kt new file mode 100644 index 00000000000..9815088d9ca --- /dev/null +++ b/repos/inmemory/src/commonMain/kotlin/dev/inmo/micro_utils/repos/HashMapCRUDRepo.kt @@ -0,0 +1,89 @@ +package dev.inmo.micro_utils.repos + +import dev.inmo.micro_utils.coroutines.BroadcastFlow +import dev.inmo.micro_utils.pagination.* +import kotlinx.coroutines.flow.Flow + +class MapCRUDRepo( + private val map: Map = emptyMap() +) : ReadStandardCRUDRepo { + override suspend fun getByPagination(pagination: Pagination): PaginationResult { + return map.keys.drop(pagination.firstIndex).take(pagination.size).mapNotNull { + map[it] + }.createPaginationResult( + pagination, + map.size.toLong() + ) + } + + override suspend fun getById(id: IdType): ObjectType? = map[id] + + override suspend fun contains(id: IdType): Boolean = map.containsKey(id) +} + +abstract class MutableMapCRUDRepo( + private val map: MutableMap = mutableMapOf() +) : WriteStandardCRUDRepo { + private val _newObjectsFlow: BroadcastFlow = BroadcastFlow() + override val newObjectsFlow: Flow + get() = _newObjectsFlow + private val _updatedObjectsFlow: BroadcastFlow = BroadcastFlow() + override val updatedObjectsFlow: Flow + get() = _updatedObjectsFlow + private val _deletedObjectsIdsFlow: BroadcastFlow = BroadcastFlow() + override val deletedObjectsIdsFlow: Flow + get() = _deletedObjectsIdsFlow + + protected abstract suspend fun updateObject(newValue: InputValueType, id: IdType, old: ObjectType): ObjectType + protected abstract suspend fun createObject(newValue: InputValueType): Pair + + override suspend fun create(values: List): List { + return values.map { + val (id, newObject) = createObject(it) + map[id] = newObject + newObject.also { _ -> + _newObjectsFlow.send(newObject) + } + } + } + + override suspend fun update(id: IdType, value: InputValueType): ObjectType? { + val newValue = updateObject(value, id, map[id] ?: return null) + + return newValue.also { + map[id] = it + _updatedObjectsFlow.send(it) + } + } + + override suspend fun update(values: List>): List { + return values.mapNotNull { update(it.first, it.second) } + } + + override suspend fun deleteById(ids: List) { + ids.forEach { + map.remove(it) ?.also { _ -> _deletedObjectsIdsFlow.send(it) } + } + } + +} + +abstract class HashMapCRUDRepo( + map: MutableMap +) : StandardCRUDRepo, + ReadStandardCRUDRepo by MapCRUDRepo(map), + MutableMapCRUDRepo(map) + +fun HashMapCRUDRepo( + map: MutableMap, + updateCallback: suspend (newValue: InputValueType, id: IdType, old: ObjectType) -> ObjectType, + createCallback: suspend (newValue: InputValueType) -> Pair +) = object : HashMapCRUDRepo(map) { + override suspend fun updateObject( + newValue: InputValueType, + id: IdType, + old: ObjectType + ): ObjectType = updateCallback(newValue, id, old) + + override suspend fun createObject(newValue: InputValueType): Pair = createCallback(newValue) +} diff --git a/settings.gradle b/settings.gradle index 333d1080497..54fb4ed3371 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,6 +9,7 @@ String[] includes = [ ":mime_types", ":repos:common", ":repos:exposed", + ":repos:inmemory", ":repos:ktor:client", ":repos:ktor:common", ":repos:ktor:server",