Merge branch 'PSC-2' of PostsSystem/PostsSystemCore into master
This commit is contained in:
commit
93c3ebd870
@ -1,17 +1,30 @@
|
||||
package com.insanusmokrassar.postssystem.core.content
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
typealias ContentId = String
|
||||
|
||||
/**
|
||||
* Content which is planned to be registered in database
|
||||
*/
|
||||
interface Content
|
||||
sealed class Content
|
||||
|
||||
@Serializable
|
||||
data class SimpleSpecialContent(
|
||||
val internalId: ContentId
|
||||
) : Content()
|
||||
|
||||
@Serializable
|
||||
data class SimpleTextContent(
|
||||
val text: String
|
||||
) : Content()
|
||||
|
||||
/**
|
||||
* Content which is already registered in database. Using its [id] you can retrieve all known
|
||||
* [com.insanusmokrassar.postssystem.core.post.RegisteredPost]s by using
|
||||
* [com.insanusmokrassar.postssystem.core.post.api.ReadPostsAPI.getPostsByContent]
|
||||
*/
|
||||
interface RegisteredContent : Content {
|
||||
val id: ContentId
|
||||
}
|
||||
data class RegisteredContent(
|
||||
val id: ContentId,
|
||||
val content: Content
|
||||
)
|
||||
|
@ -1,31 +0,0 @@
|
||||
package com.insanusmokrassar.postssystem.core.content
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Special content, which usually better known in some plugin or system, but is not representable in others. For
|
||||
* example, it could be issue in some git system, which is unknown for all other systems.
|
||||
*
|
||||
* @property internalId Represent Id of this content in system which knows exact type and can correctly handle this
|
||||
* content
|
||||
*/
|
||||
interface SpecialContent : Content {
|
||||
val internalId: ContentId
|
||||
}
|
||||
|
||||
/**
|
||||
* As [SpecialContent], but already registered in posts system
|
||||
*/
|
||||
interface SpecialRegisteredContent : RegisteredContent, SpecialContent
|
||||
|
||||
@Serializable
|
||||
data class SimpleSpecialContent(
|
||||
override val internalId: ContentId
|
||||
) : SpecialContent
|
||||
|
||||
@Serializable
|
||||
data class SimpleSpecialRegisteredContent(
|
||||
override val id: ContentId,
|
||||
override val internalId: ContentId
|
||||
) : SpecialRegisteredContent
|
||||
|
@ -1,20 +0,0 @@
|
||||
package com.insanusmokrassar.postssystem.core.content
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
interface TextContent : Content {
|
||||
val text: String
|
||||
}
|
||||
|
||||
interface TextRegisteredContent : RegisteredContent, TextContent
|
||||
|
||||
@Serializable
|
||||
data class SimpleTextContent(
|
||||
override val text: String
|
||||
) : TextContent
|
||||
|
||||
@Serializable
|
||||
data class SimpleTextRegisteredContent(
|
||||
override val id: ContentId,
|
||||
override val text: String
|
||||
) : TextRegisteredContent
|
@ -7,6 +7,6 @@ interface WriteContentAPI {
|
||||
val contentCreatedFlow: Flow<RegisteredContent>
|
||||
val contentDeletedFlow: Flow<RegisteredContent>
|
||||
|
||||
suspend fun createContent(post: Content): RegisteredContent?
|
||||
suspend fun createContent(content: Content): RegisteredContent?
|
||||
suspend fun deleteContent(id: ContentId): Boolean
|
||||
}
|
||||
|
@ -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)
|
@ -0,0 +1,10 @@
|
||||
package com.insanusmokrassar.postssystem.core.utils
|
||||
|
||||
import com.insanusmokrassar.postssystem.core.content.ContentId
|
||||
import com.insanusmokrassar.postssystem.core.post.PostId
|
||||
import java.util.*
|
||||
|
||||
private fun generateId() = UUID.randomUUID().toString()
|
||||
|
||||
internal fun generatePostId(): PostId = generateId()
|
||||
internal fun generateContentId(): ContentId = generateId()
|
@ -1,5 +1,7 @@
|
||||
package com.insanusmokrassar.postssystem.core.utils.pagination
|
||||
|
||||
import kotlin.math.ceil
|
||||
|
||||
/**
|
||||
* Base interface of pagination
|
||||
*
|
||||
@ -33,3 +35,15 @@ val Pagination.firstIndex: Int
|
||||
*/
|
||||
val Pagination.lastIndex: Int
|
||||
get() = firstIndex + size - 1
|
||||
|
||||
/**
|
||||
* Calculates pages count for given [datasetSize]
|
||||
*/
|
||||
fun calculatePagesNumber(datasetSize: Int, pageSize: Int): Int {
|
||||
return ceil(datasetSize.toDouble() / pageSize).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates pages count for given [datasetSize]
|
||||
*/
|
||||
inline fun Pagination.calculatePagesNumber(datasetSize: Int): Int = calculatePagesNumber(datasetSize, size)
|
||||
|
@ -1,14 +1,18 @@
|
||||
package com.insanusmokrassar.postssystem.core.utils.pagination
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
|
||||
@Serializable
|
||||
data class PaginationResult<T>(
|
||||
override val page: Int,
|
||||
val pagesNumber: Int,
|
||||
val results: List<T>
|
||||
) : Pagination {
|
||||
@Transient
|
||||
val results: List<T>,
|
||||
override val size: Int = results.size
|
||||
}
|
||||
) : Pagination
|
||||
|
||||
fun <T> Pagination.createResult(
|
||||
commonObjectsNumber: Int,
|
||||
results: List<T>
|
||||
) = PaginationResult(
|
||||
page,
|
||||
calculatePagesNumber(commonObjectsNumber),
|
||||
results,
|
||||
size
|
||||
)
|
||||
|
@ -0,0 +1,54 @@
|
||||
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.generateContentId
|
||||
import com.insanusmokrassar.postssystem.core.utils.pagination.*
|
||||
import kotlinx.coroutines.channels.BroadcastChannel
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||
|
||||
@ImplicitReflectionSerializer
|
||||
class InMemoryContentAPI(
|
||||
initialContent: List<RegisteredContent> = emptyList()
|
||||
): ContentAPI {
|
||||
private val contentCreatedBroadcastChannel = BroadcastChannel<RegisteredContent>(Channel.BUFFERED)
|
||||
private val contentDeletedBroadcastChannel = BroadcastChannel<RegisteredContent>(Channel.BUFFERED)
|
||||
|
||||
override val contentCreatedFlow: Flow<RegisteredContent>
|
||||
get() = contentCreatedBroadcastChannel.asFlow()
|
||||
|
||||
override val contentDeletedFlow: Flow<RegisteredContent>
|
||||
get() = contentDeletedBroadcastChannel.asFlow()
|
||||
|
||||
private val contents: MutableMap<ContentId, RegisteredContent> = initialContent
|
||||
.associateBy(RegisteredContent::id)
|
||||
.toMutableMap()
|
||||
|
||||
override suspend fun createContent(content: Content): RegisteredContent? {
|
||||
return RegisteredContent(
|
||||
generateContentId(),
|
||||
content
|
||||
).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<out RegisteredContent> {
|
||||
return pagination.createResult(
|
||||
commonObjectsNumber = contents.size,
|
||||
results = contents.values.asSequence().drop(pagination.firstIndex).take(pagination.size).toList()
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun deleteContent(id: ContentId): Boolean {
|
||||
return contents.remove(id)?.also { content ->
|
||||
contentDeletedBroadcastChannel.send(content)
|
||||
} != null
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package com.insanusmokrassar.postssystem.core.api
|
||||
import com.insanusmokrassar.postssystem.core.content.ContentId
|
||||
import com.insanusmokrassar.postssystem.core.post.*
|
||||
import com.insanusmokrassar.postssystem.core.post.api.PostsAPI
|
||||
import com.insanusmokrassar.postssystem.core.utils.generatePostId
|
||||
import com.insanusmokrassar.postssystem.core.utils.pagination.*
|
||||
import kotlinx.coroutines.channels.BroadcastChannel
|
||||
import kotlinx.coroutines.channels.Channel.Factory.BUFFERED
|
||||
@ -10,10 +11,6 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
@ImplicitReflectionSerializer
|
||||
private fun generateId(): PostId = UUID.randomUUID().toString()
|
||||
|
||||
/**
|
||||
* Thread-unsafe sample realization of [PostsAPI]
|
||||
@ -39,7 +36,7 @@ class InMemoryPostsAPI(
|
||||
|
||||
override suspend fun createPost(post: Post): RegisteredPost? {
|
||||
return SimpleRegisteredPost(
|
||||
generateId(),
|
||||
generatePostId(),
|
||||
post.content
|
||||
).also { newPost ->
|
||||
posts[newPost.id] = newPost
|
||||
|
Loading…
Reference in New Issue
Block a user