From 0e917f6a3dd0281d281bcf43ecf287b6b8f0c931 Mon Sep 17 00:00:00 2001 From: Sambo Chea Date: Fri, 22 Oct 2021 21:10:59 +0700 Subject: [PATCH] Add basis domain logic and adapter for article impls --- .../HexagonalArchitectApplication.kt | 25 +++++++++++++++- .../domain/article/ArticleCreateUseCase.kt | 13 ++++++++ .../domain/article/ArticleQueryUseCase.kt | 13 ++++++++ .../domain/article/ArticleRetrieveUseCase.kt | 13 ++++++++ .../hexagonal/domain/article/model/Article.kt | 12 ++++++++ .../domain/article/port/ArticlePort.kt | 11 +++++++ .../domain/article/usecase/ArticleCreate.kt | 11 +++++++ .../domain/article/usecase/ArticleQuery.kt | 15 ++++++++++ .../domain/article/usecase/ArticleRetrieve.kt | 15 ++++++++++ .../infrastructure/adapter/cli/ArticleCli.kt | 23 ++++++++++++++ .../persistence/ArticleImMemoryDataAdapter.kt | 30 +++++++++++++++++++ src/main/resources/application.properties | 1 - src/main/resources/application.yaml | 2 ++ 13 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleCreateUseCase.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleQueryUseCase.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleRetrieveUseCase.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/article/model/Article.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/article/port/ArticlePort.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleCreate.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleQuery.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleRetrieve.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/cli/ArticleCli.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleImMemoryDataAdapter.kt delete mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/application.yaml diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/HexagonalArchitectApplication.kt b/src/main/kotlin/com/cubetiqs/hexagonal/HexagonalArchitectApplication.kt index 19c0ccc..f219e14 100644 --- a/src/main/kotlin/com/cubetiqs/hexagonal/HexagonalArchitectApplication.kt +++ b/src/main/kotlin/com/cubetiqs/hexagonal/HexagonalArchitectApplication.kt @@ -1,10 +1,33 @@ package com.cubetiqs.hexagonal +import com.cubetiqs.hexagonal.infrastructure.adapter.cli.ArticleCli +import com.cubetiqs.hexagonal.infrastructure.adapter.persistence.ArticleImMemoryDataAdapter +import org.slf4j.LoggerFactory +import org.springframework.boot.CommandLineRunner import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @SpringBootApplication -class HexagonalArchitectApplication +class HexagonalArchitectApplication : CommandLineRunner { + private val logger = LoggerFactory.getLogger(HexagonalArchitectApplication::class.java) + + override fun run(vararg args: String?) { + // create cli instance + val cli = ArticleCli(ArticleImMemoryDataAdapter()) + + // create new article object via cli + val article = cli.create(1L, "Article 1", "Description 1") + logger.info("Article created: {}", article) + + // retrieve article via cli + val articleRetrieve = cli.retrieve(1L) + logger.info("Article retrieved: {}", articleRetrieve) + + // query articles via cli + val articleQuery = cli.query(1L) + logger.info("Query found articles: {}", articleQuery) + } +} fun main(args: Array) { runApplication(*args) diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleCreateUseCase.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleCreateUseCase.kt new file mode 100644 index 0000000..cfa2bb3 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleCreateUseCase.kt @@ -0,0 +1,13 @@ +package com.cubetiqs.hexagonal.domain.article + +import com.cubetiqs.hexagonal.domain.article.model.Article +import com.cubetiqs.hexagonal.domain.article.port.ArticlePort +import com.cubetiqs.hexagonal.domain.article.usecase.ArticleCreate + +class ArticleCreateUseCase constructor( + private val articlePort: ArticlePort, +) { + fun create(useCase: ArticleCreate): Article { + return articlePort.create(useCase) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleQueryUseCase.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleQueryUseCase.kt new file mode 100644 index 0000000..fdc0e0e --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleQueryUseCase.kt @@ -0,0 +1,13 @@ +package com.cubetiqs.hexagonal.domain.article + +import com.cubetiqs.hexagonal.domain.article.model.Article +import com.cubetiqs.hexagonal.domain.article.port.ArticlePort +import com.cubetiqs.hexagonal.domain.article.usecase.ArticleQuery + +class ArticleQueryUseCase constructor( + private val articlePort: ArticlePort, +) { + fun query(useCase: ArticleQuery): Collection
{ + return articlePort.query(useCase) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleRetrieveUseCase.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleRetrieveUseCase.kt new file mode 100644 index 0000000..0782205 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/ArticleRetrieveUseCase.kt @@ -0,0 +1,13 @@ +package com.cubetiqs.hexagonal.domain.article + +import com.cubetiqs.hexagonal.domain.article.model.Article +import com.cubetiqs.hexagonal.domain.article.port.ArticlePort +import com.cubetiqs.hexagonal.domain.article.usecase.ArticleRetrieve + +class ArticleRetrieveUseCase constructor( + private val articlePort: ArticlePort, +) { + fun retrieve(useCase: ArticleRetrieve): Article { + return articlePort.retrieve(useCase.id) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/model/Article.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/model/Article.kt new file mode 100644 index 0000000..73bdd9d --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/model/Article.kt @@ -0,0 +1,12 @@ +package com.cubetiqs.hexagonal.domain.article.model + +open class Article ( + var id: Long? = null, + var accountId: Long? = null, + var title: String? = null, + var body: String? = null, +) { + override fun toString(): String { + return "Article(id=$id, accountId=$accountId, title=$title, body=$body)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/port/ArticlePort.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/port/ArticlePort.kt new file mode 100644 index 0000000..0182d29 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/port/ArticlePort.kt @@ -0,0 +1,11 @@ +package com.cubetiqs.hexagonal.domain.article.port + +import com.cubetiqs.hexagonal.domain.article.model.Article +import com.cubetiqs.hexagonal.domain.article.usecase.ArticleCreate +import com.cubetiqs.hexagonal.domain.article.usecase.ArticleQuery + +interface ArticlePort { + fun create(article: ArticleCreate): Article + fun retrieve(id: Long): Article + fun query(query: ArticleQuery): Collection
+} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleCreate.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleCreate.kt new file mode 100644 index 0000000..acf8250 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleCreate.kt @@ -0,0 +1,11 @@ +package com.cubetiqs.hexagonal.domain.article.usecase + +open class ArticleCreate( + var accountId: Long? = null, + var title: String? = null, + var body: String? = null, +) { + override fun toString(): String { + return "ArticleCreate(accountId=$accountId, title=$title, body=$body)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleQuery.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleQuery.kt new file mode 100644 index 0000000..e04c137 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleQuery.kt @@ -0,0 +1,15 @@ +package com.cubetiqs.hexagonal.domain.article.usecase + +open class ArticleQuery( + var accountId: Long, +) { + companion object { + fun from(accountId: Long): ArticleQuery { + return ArticleQuery(accountId) + } + } + + override fun toString(): String { + return "ArticleQuery(accountId=$accountId)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleRetrieve.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleRetrieve.kt new file mode 100644 index 0000000..f32ea2f --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/article/usecase/ArticleRetrieve.kt @@ -0,0 +1,15 @@ +package com.cubetiqs.hexagonal.domain.article.usecase + +open class ArticleRetrieve( + var id: Long, +) { + companion object { + fun from(id: Long): ArticleRetrieve { + return ArticleRetrieve(id) + } + } + + override fun toString(): String { + return "ArticleRetrieve(id=$id)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/cli/ArticleCli.kt b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/cli/ArticleCli.kt new file mode 100644 index 0000000..afb0bdc --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/cli/ArticleCli.kt @@ -0,0 +1,23 @@ +package com.cubetiqs.hexagonal.infrastructure.adapter.cli + +import com.cubetiqs.hexagonal.domain.article.model.Article +import com.cubetiqs.hexagonal.domain.article.port.ArticlePort +import com.cubetiqs.hexagonal.domain.article.usecase.ArticleCreate +import com.cubetiqs.hexagonal.domain.article.usecase.ArticleQuery + +class ArticleCli constructor( + private val articlePort: ArticlePort, +) { + fun create(accountId: Long, title: String, body: String): Article { + val article = ArticleCreate(accountId, title, body) + return articlePort.create(article) + } + + fun retrieve(id: Long): Article { + return articlePort.retrieve(id) + } + + fun query(accountId: Long): Collection
{ + return articlePort.query(ArticleQuery.from(accountId)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleImMemoryDataAdapter.kt b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleImMemoryDataAdapter.kt new file mode 100644 index 0000000..98fc8b7 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleImMemoryDataAdapter.kt @@ -0,0 +1,30 @@ +package com.cubetiqs.hexagonal.infrastructure.adapter.persistence + +import com.cubetiqs.hexagonal.domain.article.model.Article +import com.cubetiqs.hexagonal.domain.article.port.ArticlePort +import com.cubetiqs.hexagonal.domain.article.usecase.ArticleCreate +import com.cubetiqs.hexagonal.domain.article.usecase.ArticleQuery +import java.util.concurrent.ConcurrentHashMap + +class ArticleImMemoryDataAdapter : ArticlePort { + companion object { + private val articles = ConcurrentHashMap() + } + + override fun create(article: ArticleCreate): Article { + val id = (articles.size + 1).toLong() + val entity = Article(id, article.accountId, article.title, article.body) + articles[id] = entity + return entity + } + + override fun retrieve(id: Long): Article { + return articles[id] ?: throw IllegalArgumentException("Article not found") + } + + override fun query(query: ArticleQuery): Collection
{ + return articles.values.filter { + it.accountId == query.accountId + } + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000..47fbb02 --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,2 @@ +server: + port: 8080 \ No newline at end of file