add businessContentRepo

This commit is contained in:
InsanusMokrassar 2020-11-26 02:39:57 +06:00
parent f7d60fa672
commit 20e3fd6934
4 changed files with 129 additions and 27 deletions

View File

@ -11,8 +11,7 @@ typealias ContentId = String
/**
* Content which is planned to be registered in database
*/
@Serializable
sealed class Content
interface Content
/**
* It is content, which was added by some external source to use inside of some plugins. For example, you can use
@ -21,12 +20,12 @@ sealed class Content
@Serializable
data class SpecialContent(
val internalId: ContentId
) : Content()
) : Content
@Serializable
data class TextContent(
val text: String
) : Content()
) : Content
@Serializable
data class BinaryContent(
@ -34,7 +33,7 @@ data class BinaryContent(
val originalFileName: String,
@Serializable(ByteArrayAllocatorSerializer::class)
val dataAllocator: ByteArrayAllocator
) : Content()
) : Content
val BinaryContent.isImage: Boolean
get() = mimeType is KnownMimeTypes.Image

View File

@ -0,0 +1,120 @@
package dev.inmo.postssystem.core.content.api
import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.Repo
import dev.inmo.micro_utils.repos.UpdatedValuePair
import dev.inmo.postssystem.core.content.*
import dev.inmo.postssystem.core.generateContentId
import kotlinx.coroutines.flow.*
interface BusinessContentRepoReadHelpInterface : Repo {
suspend fun getKeysByPagination(pagination: Pagination): PaginationResult<ContentId>
suspend fun contains(contentId: ContentId): Boolean
suspend fun getType(contentId: ContentId): AdapterType?
suspend fun count(): Long
}
interface BusinessContentRepoWriteHelpInterface : Repo {
suspend fun deleteContentId(contentId: ContentId)
suspend fun saveType(contentId: ContentId, type: AdapterType): Boolean
}
interface BusinessContentRepoHelpInterface : BusinessContentRepoReadHelpInterface, BusinessContentRepoWriteHelpInterface
typealias AdapterType = String
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: BusinessContentRepoReadHelpInterface,
) : 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: BusinessContentRepoHelpInterface
) : 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 ->
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: BusinessContentRepoHelpInterface
) : ContentRepo, ReadContentRepo by BusinessReadContentRepo(
adapters,
helperRepo
), WriteContentRepo by BusinessWriteContentRepo(
adapters,
helperRepo
)

View File

@ -4,22 +4,10 @@ import dev.inmo.postssystem.core.content.ContentId
import dev.inmo.postssystem.core.content.RegisteredContent
import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
import dev.inmo.micro_utils.repos.pagination.getAll
/**
* Simple read API by different properties of [dev.inmo.postssystem.core.content.Content].
*/
interface ReadContentRepo {
/**
* @return [Set] of [ContentId] wich currently known in this instance of API
*/
suspend fun getContentsIds(): Set<ContentId>
/**
* @return [RegisteredContent] if it is available by [id]
*/
suspend fun getContentById(id: ContentId): RegisteredContent?
/**
* @return all [RegisteredContent] by pages basing on their creation date
*/
suspend fun getContentByPagination(pagination: Pagination): PaginationResult<RegisteredContent>
}
interface ReadContentRepo : ReadStandardCRUDRepo<RegisteredContent, ContentId>

View File

@ -1,12 +1,7 @@
package dev.inmo.postssystem.core.content.api
import dev.inmo.micro_utils.repos.WriteStandardCRUDRepo
import dev.inmo.postssystem.core.content.*
import kotlinx.coroutines.flow.Flow
interface WriteContentRepo {
val contentCreatedFlow: Flow<RegisteredContent>
val contentDeletedFlow: Flow<RegisteredContent>
suspend fun registerContent(content: Content): RegisteredContent?
suspend fun deleteContent(id: ContentId): Boolean
}
interface WriteContentRepo : WriteStandardCRUDRepo<RegisteredContent, ContentId, Content>