remove all redundant boilerplate

This commit is contained in:
InsanusMokrassar 2019-11-01 09:54:26 +06:00
parent 0c98fe3dfb
commit 2a55bea0ea
24 changed files with 3 additions and 509 deletions

View File

@ -1,44 +0,0 @@
project.version = "$project_public_version"
project.group = "$project_public_group"
buildscript {
repositories {
mavenLocal()
jcenter()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
}
}
apply plugin: 'java-library'
apply plugin: 'kotlin'
apply plugin: 'kotlinx-serialization'
repositories {
mavenLocal()
jcenter()
mavenCentral()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
api project(":Core")
api project(":ClientServerCommon")
api "io.ktor:ktor-client:$ktor_version"
api "io.ktor:ktor-client-websockets:$ktor_version"
api "io.ktor:ktor-client-json-jvm:$ktor_version"
api "io.ktor:ktor-client-serialization-jvm:$ktor_version"
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = [ disableImplicitReflectionSerializerAnnotation ]
}
}

View File

@ -1 +0,0 @@
ktor_version=1.2.4

View File

@ -1 +0,0 @@
rootProject.name = 'postssystem.core.client'

View File

@ -1,40 +0,0 @@
package com.insanusmokrassar.postssystem.core.client
import io.ktor.client.HttpClient
import io.ktor.client.features.websocket.ws
import io.ktor.http.HttpMethod
import io.ktor.http.cio.websocket.Frame
import io.ktor.http.cio.websocket.readText
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
class EventFlow<T>(
private val client: HttpClient,
private val host: String,
private val port: Int,
private val path: String,
private val dataConverter: suspend (String) -> T
) : Flow<T> {
@InternalCoroutinesApi
override suspend fun collect(collector: FlowCollector<T>) {
client.ws(
method = HttpMethod.Get,
host = host,
port = port,
path = path
) {
var frame = incoming.receiveOrClosed()
while (!frame.isClosed) {
val frameVal = frame.value
when (frameVal) {
is Frame.Text -> {
collector.emit(
dataConverter(frameVal.readText())
)
}
}
}
}
}
}

View File

@ -1,11 +0,0 @@
package com.insanusmokrassar.postssystem.core.client
import io.ktor.client.HttpClientConfig
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer
fun HttpClientConfig<*>.installPostsCore() {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
}

View File

@ -1,49 +0,0 @@
package com.insanusmokrassar.postssystem.core.client
import com.insanusmokrassar.postssystem.core.api.ReadPostsAPI
import com.insanusmokrassar.postssystem.core.clientserver.common.models.DateTimeRequest
import com.insanusmokrassar.postssystem.core.clientserver.common.*
import com.insanusmokrassar.postssystem.core.content.ContentId
import com.insanusmokrassar.postssystem.core.post.*
import com.insanusmokrassar.postssystem.core.utils.pagination.Pagination
import com.insanusmokrassar.postssystem.core.utils.pagination.PaginationResult
import io.ktor.client.HttpClient
import io.ktor.client.request.post
import org.joda.time.DateTime
class ReadableHttpPostsAPI(
private val client: HttpClient = HttpClient(),
baseAddress: String
) : ReadPostsAPI {
private val postByIdAddress = "$baseAddress/$getPostByIdAddress"
private val postsByContentIdAddress = "$baseAddress/$getPostsByContentIdAddress"
private val postsByDatesAddress = "$baseAddress/$getPostsByDatesAddress"
private val postsByPaginationAddress = "$baseAddress/$getPostsByPaginationAddress"
override suspend fun getPostById(id: PostId): RegisteredPost? {
return client.post<SimpleRegisteredPost>(postByIdAddress) {
body = id
}
}
override suspend fun getPostsByContent(id: ContentId): List<RegisteredPost> {
return client.post<List<SimpleRegisteredPost>>(postsByContentIdAddress) {
body = id
}
}
override suspend fun getPostsByDates(from: DateTime?, to: DateTime?): List<RegisteredPost> {
return client.post<List<SimpleRegisteredPost>>(postsByDatesAddress) {
body = DateTimeRequest(
from ?.millis,
to ?.millis
)
}
}
override suspend fun getPostsByPagination(pagination: Pagination): PaginationResult<out RegisteredPost> {
return client.post<PaginationResult<SimpleRegisteredPost>>(postsByPaginationAddress) {
body = pagination
}
}
}

View File

@ -1,46 +0,0 @@
package com.insanusmokrassar.postssystem.core.client
import com.insanusmokrassar.postssystem.core.api.WritePostsAPI
import com.insanusmokrassar.postssystem.core.clientserver.common.*
import com.insanusmokrassar.postssystem.core.clientserver.common.models.UpdatePostRequest
import com.insanusmokrassar.postssystem.core.post.*
import io.ktor.client.HttpClient
import io.ktor.client.request.post
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.json.Json
class WritableHttpPostsAPI(
private val hostUrl: String,
private val port: Int,
private val client: HttpClient
) : WritePostsAPI {
private inline fun postEventFlow(url: String) = EventFlow(
client,
hostUrl,
port,
"/$url"
) {
Json.plain.parse(SimpleRegisteredPost.serializer(), it)
}
override val postCreatedFlow: Flow<RegisteredPost> = postEventFlow(eventPostsCreatedAddress)
override val postDeletedFlow: Flow<RegisteredPost> = postEventFlow(eventPostsDeletedAddress)
override val postUpdatedFlow: Flow<RegisteredPost> = postEventFlow(eventPostsUpdatedAddress)
override suspend fun createPost(post: Post): RegisteredPost? = client.post<SimpleRegisteredPost>(
createPostAddress
) {
body = post.content
}
override suspend fun deletePost(id: PostId): Boolean = client.post(deletePostAddress) {
body = id
}
override suspend fun updatePostContent(
postId: PostId,
post: Post
): Boolean = client.post(createPostAddress) {
body = UpdatePostRequest(postId, post.content)
}
}

View File

@ -1,38 +0,0 @@
project.version = "$project_public_version"
project.group = "$project_public_group"
buildscript {
repositories {
mavenLocal()
jcenter()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
}
}
apply plugin: 'java-library'
apply plugin: 'kotlin'
apply plugin: 'kotlinx-serialization'
repositories {
mavenLocal()
jcenter()
mavenCentral()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
api project(":Core")
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = [ disableImplicitReflectionSerializerAnnotation ]
}
}

View File

@ -1 +0,0 @@
rootProject.name = 'postssystem.core.clientserver.common'

View File

@ -1,23 +0,0 @@
package com.insanusmokrassar.postssystem.core.clientserver.common
const val getPostByIdAddress = "core/posts/get/id"
const val getPostsByContentIdAddress = "core/posts/get/content_id"
const val getPostsByDatesAddress = "core/posts/get/dates"
const val getPostsByPaginationAddress = "core/posts/get/pagination"
const val eventPostsCreatedAddress = "core/posts/event/created"
const val eventPostsUpdatedAddress = "core/posts/event/updated"
const val eventPostsDeletedAddress = "core/posts/event/deleted"
const val createPostAddress = "core/posts/create"
const val updatePostAddress = "core/posts/update"
const val deletePostAddress = "core/posts/delete"
//class ReadPaths(
// val baseAddress: String
//) {
// val postByIdAddress = "$baseAddress/$getPostByIdAddress"
// val postsByContentIdAddress = "$baseAddress/$getPostsByContentIdAddress"
// val postsByDatesAddress = "$baseAddress/$getPostsByDatesAddress"
// val postsByPaginationAddress = "$baseAddress/$getPostsByPaginationAddress"
//}

View File

@ -1,11 +0,0 @@
package com.insanusmokrassar.postssystem.core.clientserver.common
import com.insanusmokrassar.postssystem.core.post.PostId
import kotlinx.serialization.Serializable
sealed class ReadModel
@Serializable
class ReadPostsById(
val postId: PostId
)

View File

@ -1,9 +0,0 @@
package com.insanusmokrassar.postssystem.core.clientserver.common.models
import kotlinx.serialization.Serializable
@Serializable
data class DateTimeRequest (
val from: Long?,
val to: Long?
)

View File

@ -1,11 +0,0 @@
package com.insanusmokrassar.postssystem.core.clientserver.common.models
import com.insanusmokrassar.postssystem.core.post.PostContents
import com.insanusmokrassar.postssystem.core.post.PostId
import kotlinx.serialization.Serializable
@Serializable
data class UpdatePostRequest(
val id: PostId,
val content: PostContents
)

View File

@ -1,4 +1,3 @@
package com.insanusmokrassar.postssystem.core.api
interface PostsAPI : ReadPostsAPI,
WritePostsAPI
interface PostsAPI : ReadPostsAPI, WritePostsAPI

View File

@ -22,12 +22,10 @@ interface RegisteredPost : Post {
val modificationDate: DateTime
}
@Serializable
data class SimplePost(
override val content: PostContents
) : Post
@Serializable
data class SimpleRegisteredPost(
override val id: PostId,
override val content: RegisteredPostContents,

View File

@ -3,7 +3,7 @@ package com.insanusmokrassar.postssystem.core.utils.pagination
import kotlinx.serialization.Serializable
@Serializable
data class PaginationRequest(
data class SimplePagination(
override val page: Int,
override val size: Int
) : Pagination

View File

@ -1,44 +0,0 @@
project.version = "$project_public_version"
project.group = "$project_public_group"
buildscript {
repositories {
mavenLocal()
jcenter()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
}
}
apply plugin: 'java-library'
apply plugin: 'kotlin'
apply plugin: 'kotlinx-serialization'
repositories {
mavenLocal()
jcenter()
mavenCentral()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
api project(":Core")
api project(":ClientServerCommon")
api "io.ktor:ktor-server:$ktor_version"
api "io.ktor:ktor-server-core:$ktor_version"
api "io.ktor:ktor-websockets:$ktor_version"
api "io.ktor:ktor-serialization:$ktor_version"
}
compileKotlin {
kotlinOptions {
freeCompilerArgs = [ disableImplicitReflectionSerializerAnnotation ]
}
}

View File

@ -1 +0,0 @@
ktor_version=1.2.4

View File

@ -1 +0,0 @@
rootProject.name = 'postssystem.core.server'

View File

@ -1,42 +0,0 @@
package com.insanusmokrassar.postssystem.core.server
import com.insanusmokrassar.postssystem.core.post.Post
import com.insanusmokrassar.postssystem.core.post.SimpleRegisteredPost
import com.insanusmokrassar.postssystem.core.utils.pagination.PaginationResult
import io.ktor.application.ApplicationCall
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.response.respond
import io.ktor.response.respondText
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.internal.ArrayListSerializer
import kotlinx.serialization.internal.NullableSerializer
import kotlinx.serialization.json.Json
internal val postsSerializer = ArrayListSerializer(SimpleRegisteredPost.serializer())
internal val paginationResultSerializer = PaginationResult.serializer(SimpleRegisteredPost.serializer())
internal val List<Post>.asSimplePostList
get() = map { post ->
post.asSimplePost
}
internal val Post.asSimplePost
get() = when (this) {
is SimpleRegisteredPost -> this
else -> SimpleRegisteredPost(id, content, meta)
}
@InternalSerializationApi
internal suspend fun <T : Any> ApplicationCall.answer(
serializer: KSerializer<T>,
answerObject: T?
) = respondText(ContentType.Application.Json) {
Json.plain.stringify(NullableSerializer(serializer), answerObject)
}
internal suspend fun ApplicationCall.answerBadRequest(
mustBeProvided: String
) = respond(HttpStatusCode.BadRequest, "$mustBeProvided must be provided as body of request")

View File

@ -1,24 +0,0 @@
package com.insanusmokrassar.postssystem.core.server
import io.ktor.application.*
import io.ktor.features.ContentNegotiation
import io.ktor.http.ContentType
import io.ktor.serialization.serialization
import io.ktor.websocket.WebSockets
import kotlinx.serialization.json.Json
fun Application.installCorePosts() {
featureOrNull(ContentNegotiation) ?: install(ContentNegotiation) {
serialization(
contentType = ContentType.Application.Json,
json = Json.plain
)
}
}
fun Application.installCorePostsWrite() {
installCorePosts()
featureOrNull(WebSockets) ?: install(WebSockets) {
maxFrameSize = Long.MAX_VALUE
}
}

View File

@ -1,52 +0,0 @@
package com.insanusmokrassar.postssystem.core.server
import com.insanusmokrassar.postssystem.core.api.ReadPostsAPI
import com.insanusmokrassar.postssystem.core.clientserver.common.*
import com.insanusmokrassar.postssystem.core.clientserver.common.models.DateTimeRequest
import com.insanusmokrassar.postssystem.core.content.ContentId
import com.insanusmokrassar.postssystem.core.post.*
import com.insanusmokrassar.postssystem.core.utils.pagination.PaginationRequest
import com.insanusmokrassar.postssystem.core.utils.pagination.PaginationResult
import io.ktor.application.*
import io.ktor.request.receiveOrNull
import io.ktor.routing.Route
import io.ktor.routing.post
import kotlinx.serialization.InternalSerializationApi
import org.joda.time.DateTime
@InternalSerializationApi
fun Route.includePostsCoreReadModules(readPostsAPI: ReadPostsAPI) {
post(getPostByIdAddress) {
call.receiveOrNull<PostId>() ?.also { id ->
val post = readPostsAPI.getPostById(id)
call.answer(SimpleRegisteredPost.serializer(), post ?.asSimplePost)
} ?: call.answerBadRequest("Id of post")
}
post(getPostsByContentIdAddress) {
call.receiveOrNull<ContentId>() ?.also { id ->
val posts = readPostsAPI.getPostsByContent(id)
val simplePosts = posts.asSimplePostList
call.answer(postsSerializer, simplePosts)
} ?: call.answerBadRequest("Id of content")
}
post(getPostsByDatesAddress) {
call.receiveOrNull<DateTimeRequest>() ?.also { (from, to) ->
val posts = readPostsAPI.getPostsByDates(from ?.let { DateTime(it) }, to ?.let { DateTime(it) })
val simplePosts = posts.asSimplePostList
call.answer(postsSerializer, simplePosts)
} ?: call.answerBadRequest("Object \"DateTimeRequest\"")
}
post(getPostsByPaginationAddress) {
call.receiveOrNull<PaginationRequest>() ?.also { pagination ->
val paginationResult = readPostsAPI.getPostsByPagination(pagination).let {
val simplePosts = it.results.asSimplePostList
PaginationResult(
it.page,
it.pagesNumber,
simplePosts
)
}
call.answer(paginationResultSerializer, paginationResult)
} ?: call.answerBadRequest("Object \"PaginationRequest\"")
}
}

View File

@ -1,54 +0,0 @@
package com.insanusmokrassar.postssystem.core.server
import com.insanusmokrassar.postssystem.core.api.WritePostsAPI
import com.insanusmokrassar.postssystem.core.clientserver.common.*
import com.insanusmokrassar.postssystem.core.clientserver.common.models.UpdatePostRequest
import com.insanusmokrassar.postssystem.core.post.*
import io.ktor.application.*
import io.ktor.http.cio.websocket.Frame
import io.ktor.request.receiveOrNull
import io.ktor.routing.Route
import io.ktor.routing.post
import io.ktor.websocket.webSocket
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.internal.BooleanSerializer
import kotlinx.serialization.json.Json
private inline fun Route.createWebsocket(path: String, flow: Flow<Post>) {
webSocket("/$path") {
flow.collect {
val simplePost = it.asSimplePost
outgoing.send(Frame.Text(Json.plain.stringify(SimpleRegisteredPost.serializer(), simplePost)))
}
}
}
@InternalSerializationApi
fun Route.includePostsCoreWriteModules(
writePostsAPI: WritePostsAPI
) {
createWebsocket(eventPostsCreatedAddress, writePostsAPI.postCreatedFlow)
createWebsocket(eventPostsDeletedAddress, writePostsAPI.postDeletedFlow)
createWebsocket(eventPostsUpdatedAddress, writePostsAPI.postUpdatedFlow)
post(createPostAddress) {
call.receiveOrNull<PostContents>() ?.also { contents ->
val post = writePostsAPI.createPost(contents)
call.answer(SimpleRegisteredPost.serializer(), post ?.asSimplePost)
} ?: call.answerBadRequest("Contents (List of Content)")
}
post(deletePostAddress) {
call.receiveOrNull<PostId>() ?.also { postId ->
call.answer(BooleanSerializer, writePostsAPI.deletePost(postId))
} ?: call.answerBadRequest("Post Id (String)")
}
post(deletePostAddress) {
call.receiveOrNull<UpdatePostRequest>() ?.also { (postId, contents) ->
call.answer(BooleanSerializer, writePostsAPI.updatePostContent(postId, contents))
} ?: call.answerBadRequest("Post Id (String)")
}
}