From 7a5fd177c8d4f7578ff45755f83c21981a41a0c5 Mon Sep 17 00:00:00 2001 From: Mikhail Astafyev Date: Mon, 4 Nov 2019 15:00:42 +0500 Subject: [PATCH] PSC-2 added test implementation for ContentAPI --- .../core/content/api/WriteContentAPI.kt | 6 +- .../postssystem/core/utils/DateTimeUtils.kt | 9 +++ .../core/utils/pagination/Pagination.kt | 9 +++ .../core/api/InMemoryContentAPI.kt | 67 +++++++++++++++++++ 4 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 core/src/main/kotlin/com/insanusmokrassar/postssystem/core/utils/DateTimeUtils.kt create mode 100644 core/src/test/kotlin/com/insanusmokrassar/postssystem/core/api/InMemoryContentAPI.kt diff --git a/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/content/api/WriteContentAPI.kt b/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/content/api/WriteContentAPI.kt index 3fbad021..acda8975 100644 --- a/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/content/api/WriteContentAPI.kt +++ b/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/content/api/WriteContentAPI.kt @@ -1,12 +1,14 @@ package com.insanusmokrassar.postssystem.core.content.api -import com.insanusmokrassar.postssystem.core.content.* +import com.insanusmokrassar.postssystem.core.content.Content +import com.insanusmokrassar.postssystem.core.content.ContentId +import com.insanusmokrassar.postssystem.core.content.RegisteredContent import kotlinx.coroutines.flow.Flow interface WriteContentAPI { val contentCreatedFlow: Flow val contentDeletedFlow: Flow - suspend fun createContent(post: Content): RegisteredContent? + suspend fun createContent(content: Content): RegisteredContent? suspend fun deleteContent(id: ContentId): Boolean } diff --git a/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/utils/DateTimeUtils.kt b/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/utils/DateTimeUtils.kt new file mode 100644 index 00000000..3beef0cd --- /dev/null +++ b/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/utils/DateTimeUtils.kt @@ -0,0 +1,9 @@ +package com.insanusmokrassar.postssystem.core.utils + +import org.joda.time.DateTime + +fun DateTime?.orMin(): DateTime = this ?: MIN_DATE +fun DateTime?.orMax(): DateTime = this ?: MAX_DATE + +private val MIN_DATE = DateTime(Long.MIN_VALUE) +private val MAX_DATE = DateTime(Long.MAX_VALUE) diff --git a/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/utils/pagination/Pagination.kt b/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/utils/pagination/Pagination.kt index a8496b9d..c58d4953 100644 --- a/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/utils/pagination/Pagination.kt +++ b/core/src/main/kotlin/com/insanusmokrassar/postssystem/core/utils/pagination/Pagination.kt @@ -1,5 +1,7 @@ package com.insanusmokrassar.postssystem.core.utils.pagination +import kotlin.math.ceil + /** * Base interface of pagination * @@ -33,3 +35,10 @@ val Pagination.firstIndex: Int */ val Pagination.lastIndex: Int get() = firstIndex + size - 1 + +/** + * Calculates pages count for given [datasetSize] + */ +fun Pagination.pagesCount(datasetSize: Int): Int { + return ceil(datasetSize.toDouble() / size).toInt() +} diff --git a/core/src/test/kotlin/com/insanusmokrassar/postssystem/core/api/InMemoryContentAPI.kt b/core/src/test/kotlin/com/insanusmokrassar/postssystem/core/api/InMemoryContentAPI.kt new file mode 100644 index 00000000..795db98d --- /dev/null +++ b/core/src/test/kotlin/com/insanusmokrassar/postssystem/core/api/InMemoryContentAPI.kt @@ -0,0 +1,67 @@ +package com.insanusmokrassar.postssystem.core.api + +import com.insanusmokrassar.postssystem.core.content.* +import com.insanusmokrassar.postssystem.core.content.api.ContentAPI +import com.insanusmokrassar.postssystem.core.utils.pagination.Pagination +import com.insanusmokrassar.postssystem.core.utils.pagination.PaginationResult +import com.insanusmokrassar.postssystem.core.utils.pagination.firstIndex +import com.insanusmokrassar.postssystem.core.utils.pagination.pagesCount +import kotlinx.coroutines.channels.BroadcastChannel +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.asFlow +import kotlinx.serialization.ImplicitReflectionSerializer +import java.util.* + +@ImplicitReflectionSerializer +private fun generateId(): ContentId = UUID.randomUUID().toString() + +@ImplicitReflectionSerializer +class InMemoryContentAPI( + initialContent: List = emptyList() +): ContentAPI { + + override val contentCreatedFlow: Flow + get() = contentCreatedBroadcastChannel.asFlow() + + override val contentDeletedFlow: Flow + get() = contentDeletedBroadcastChannel.asFlow() + + private val contents: MutableMap = initialContent + .associateBy(RegisteredContent::id) + .toMutableMap() + + private val contentCreatedBroadcastChannel = BroadcastChannel(Channel.BUFFERED) + private val contentDeletedBroadcastChannel = BroadcastChannel(Channel.BUFFERED) + + override suspend fun createContent(content: Content): RegisteredContent? { + return content.createRegisteredEntity(generateId())?.also { registeredContent -> + contents[registeredContent.id] = registeredContent + contentCreatedBroadcastChannel.send(registeredContent) + } + } + + override suspend fun getContentById(id: ContentId): RegisteredContent? = contents[id] + + override suspend fun getContentByPagination(pagination: Pagination): PaginationResult { + return PaginationResult( + page = pagination.page, + pagesNumber = pagination.pagesCount(contents.size), + results = contents.values.drop(pagination.firstIndex).take(pagination.size) + ) + } + + override suspend fun deleteContent(id: ContentId): Boolean { + return contents.remove(id)?.also { content -> + contentDeletedBroadcastChannel.send(content) + } != null + } + + private fun Content.createRegisteredEntity(id: ContentId): RegisteredContent? { + return when(this) { + is TextContent -> SimpleTextRegisteredContent(id, text) + is SpecialContent -> SimpleTextRegisteredContent(id, internalId) + else -> null + } + } +} \ No newline at end of file