core/core/api/src/commonMain/kotlin/dev/inmo/postssystem/core/content/api/business/BusinessContentRepo.kt

118 lines
4.4 KiB
Kotlin

package dev.inmo.postssystem.core.content.api.business
import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.UpdatedValuePair
import dev.inmo.postssystem.core.content.*
import dev.inmo.postssystem.core.content.api.*
import dev.inmo.postssystem.core.generateContentId
import kotlinx.coroutines.flow.*
interface BusinessContentRepoContentAdapter {
val type: AdapterType
suspend fun storeContent(contentId: ContentId, content: Content): Boolean
suspend fun getContent(contentId: ContentId): Content?
suspend fun removeContent(contentId: ContentId)
}
class BusinessReadContentRepo(
adapters: List<BusinessContentRepoContentAdapter>,
private val helperRepo: BusinessContentRepoReadHelper,
) : ReadContentRepo {
private val adaptersMap: Map<String, BusinessContentRepoContentAdapter> = adapters.map {
it.type to it
}.toMap()
override suspend fun contains(id: ContentId): Boolean = helperRepo.contains(id)
override suspend fun count(): Long = helperRepo.count()
override suspend fun getById(id: ContentId): RegisteredContent? = helperRepo.getType(id) ?.let {
adaptersMap[it] ?.getContent(id) ?.let { content ->
RegisteredContent(id, content)
}
}
override suspend fun getByPagination(
pagination: Pagination
): PaginationResult<RegisteredContent> = helperRepo.getKeysByPagination(
pagination
).let {
it.results.mapNotNull {
getById(it)
}.createPaginationResult(
it,
count()
)
}
}
class BusinessWriteContentRepo(
private val adapters: List<BusinessContentRepoContentAdapter>,
private val helperRepo: BusinessContentRepoHelper
) : WriteContentRepo {
private val adaptersMap = adapters.map { it.type to it }.toMap()
private val _deletedObjectsIdsFlow = MutableSharedFlow<ContentId>()
override val deletedObjectsIdsFlow: Flow<ContentId> = _deletedObjectsIdsFlow.asSharedFlow()
private val _newObjectsFlow = MutableSharedFlow<RegisteredContent>()
override val newObjectsFlow: Flow<RegisteredContent> = _newObjectsFlow.asSharedFlow()
private val _updatedObjectsFlow = MutableSharedFlow<RegisteredContent>()
override val updatedObjectsFlow: Flow<RegisteredContent> = _updatedObjectsFlow.asSharedFlow()
override suspend fun create(values: List<Content>): List<RegisteredContent> {
return values.mapNotNull { content ->
if (content is OtherContentLinkContent) {
adapters.forEach {
val existsContent = it.getContent(content.otherId)
if (existsContent != null) {
return@mapNotNull RegisteredContent(
content.otherId,
existsContent
)
}
}
}
val contentId = generateContentId()
val adapter = adapters.firstOrNull { it.storeContent(contentId, content) } ?: return@mapNotNull null
if (!helperRepo.saveType(contentId, adapter.type)) {
adapter.removeContent(contentId)
}
RegisteredContent(contentId, content).also { _newObjectsFlow.emit(it) }
}
}
override suspend fun deleteById(ids: List<ContentId>) {
ids.forEach { contentId ->
adaptersMap[helperRepo.getType(contentId)] ?.removeContent(contentId) ?: adapters.forEach {
it.removeContent(contentId)
}
helperRepo.deleteContentId(contentId)
_deletedObjectsIdsFlow.emit(contentId)
}
}
override suspend fun update(id: ContentId, value: Content): RegisteredContent? {
adaptersMap[helperRepo.getType(id)] ?.removeContent(id) ?: adapters.forEach {
it.removeContent(id)
}
adapters.firstOrNull { it.storeContent(id, value) } ?: return null
return RegisteredContent(id, value).also { _updatedObjectsFlow.emit(it) }
}
override suspend fun update(values: List<UpdatedValuePair<ContentId, Content>>): List<RegisteredContent> {
return values.mapNotNull {
update(it.first, it.second)
}
}
}
class BusinessContentRepo(
adapters: List<BusinessContentRepoContentAdapter>,
helperRepo: BusinessContentRepoHelper
) : ContentRepo, ReadContentRepo by BusinessReadContentRepo(
adapters,
helperRepo
), WriteContentRepo by BusinessWriteContentRepo(
adapters,
helperRepo
)