MicroUtils/repos/inmemory/src/commonMain/kotlin/dev/inmo/micro_utils/repos/MapCRUDRepo.kt

105 lines
4.5 KiB
Kotlin

package dev.inmo.micro_utils.repos
import dev.inmo.micro_utils.pagination.*
import kotlinx.coroutines.flow.*
class ReadMapCRUDRepo<ObjectType, IdType>(
private val map: Map<IdType, ObjectType> = emptyMap()
) : ReadCRUDRepo<ObjectType, IdType> {
override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> {
return map.keys.drop(pagination.firstIndex).take(pagination.size).mapNotNull {
map[it]
}.createPaginationResult(
pagination,
count()
)
}
override suspend fun getIdsByPagination(pagination: Pagination): PaginationResult<IdType> {
return map.keys.drop(pagination.firstIndex).take(pagination.size).createPaginationResult(
pagination,
count()
)
}
override suspend fun getById(id: IdType): ObjectType? = map[id]
override suspend fun contains(id: IdType): Boolean = map.containsKey(id)
override suspend fun count(): Long = map.size.toLong()
}
abstract class WriteMapCRUDRepo<ObjectType, IdType, InputValueType>(
protected val map: MutableMap<IdType, ObjectType> = mutableMapOf()
) : WriteCRUDRepo<ObjectType, IdType, InputValueType> {
protected val _newObjectsFlow: MutableSharedFlow<ObjectType> = MutableSharedFlow()
override val newObjectsFlow: Flow<ObjectType> = _newObjectsFlow.asSharedFlow()
protected val _updatedObjectsFlow: MutableSharedFlow<ObjectType> = MutableSharedFlow()
override val updatedObjectsFlow: Flow<ObjectType> = _updatedObjectsFlow.asSharedFlow()
protected val _deletedObjectsIdsFlow: MutableSharedFlow<IdType> = MutableSharedFlow()
override val deletedObjectsIdsFlow: Flow<IdType> = _deletedObjectsIdsFlow.asSharedFlow()
protected abstract suspend fun updateObject(newValue: InputValueType, id: IdType, old: ObjectType): ObjectType
protected abstract suspend fun createObject(newValue: InputValueType): Pair<IdType, ObjectType>
override suspend fun create(values: List<InputValueType>): List<ObjectType> {
return values.map {
val (id, newObject) = createObject(it)
map[id] = newObject
newObject.also { _ ->
_newObjectsFlow.emit(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.emit(it)
}
}
override suspend fun update(values: List<UpdatedValuePair<IdType, InputValueType>>): List<ObjectType> {
return values.mapNotNull { update(it.first, it.second) }
}
override suspend fun deleteById(ids: List<IdType>) {
ids.forEach {
map.remove(it) ?.also { _ -> _deletedObjectsIdsFlow.emit(it) }
}
}
}
abstract class MapCRUDRepo<ObjectType, IdType, InputValueType>(
map: MutableMap<IdType, ObjectType>
) : CRUDRepo<ObjectType, IdType, InputValueType>,
ReadCRUDRepo<ObjectType, IdType> by ReadMapCRUDRepo(map),
WriteMapCRUDRepo<ObjectType, IdType, InputValueType>(map)
fun <ObjectType, IdType, InputValueType> MapCRUDRepo(
map: MutableMap<IdType, ObjectType>,
updateCallback: suspend MutableMap<IdType, ObjectType>.(newValue: InputValueType, id: IdType, old: ObjectType) -> ObjectType,
createCallback: suspend MutableMap<IdType, ObjectType>.(newValue: InputValueType) -> Pair<IdType, ObjectType>
) = object : MapCRUDRepo<ObjectType, IdType, InputValueType>(map) {
override suspend fun updateObject(
newValue: InputValueType,
id: IdType,
old: ObjectType
): ObjectType = map.updateCallback(newValue, id, old)
override suspend fun createObject(newValue: InputValueType): Pair<IdType, ObjectType> = map.createCallback(newValue)
}
fun <ObjectType, IdType, InputValueType> MapCRUDRepo(
updateCallback: suspend MutableMap<IdType, ObjectType>.(newValue: InputValueType, id: IdType, old: ObjectType) -> ObjectType,
createCallback: suspend MutableMap<IdType, ObjectType>.(newValue: InputValueType) -> Pair<IdType, ObjectType>
) = MapCRUDRepo(mutableMapOf(), updateCallback, createCallback)
fun <ObjectType, IdType, InputValueType> MutableMap<IdType, ObjectType>.asCrudRepo(
updateCallback: suspend MutableMap<IdType, ObjectType>.(newValue: InputValueType, id: IdType, old: ObjectType) -> ObjectType,
createCallback: suspend MutableMap<IdType, ObjectType>.(newValue: InputValueType) -> Pair<IdType, ObjectType>
) = MapCRUDRepo(this, updateCallback, createCallback)