From e281ec16dd962732028fce0853498323433cc727 Mon Sep 17 00:00:00 2001 From: Sambo Chea Date: Sat, 23 Oct 2021 15:34:42 +0700 Subject: [PATCH] Add account implement --- .../HexagonalArchitectApplication.kt | 34 +++++++++++++++---- .../domain/account/AccountCreateUseCase.kt | 13 +++++++ .../domain/account/AccountQueryUseCase.kt | 13 +++++++ .../domain/account/AccountRetrieveUseCase.kt | 13 +++++++ .../hexagonal/domain/account/model/Account.kt | 12 +++++++ .../domain/account/port/AccountPort.kt | 12 +++++++ .../domain/account/usecase/AccountCreate.kt | 11 ++++++ .../domain/account/usecase/AccountQuery.kt | 9 +++++ .../domain/account/usecase/AccountRetrieve.kt | 9 +++++ .../adapter/account/cli/AccountCli.kt | 29 ++++++++++++++++ .../persistence/AccountInMemoryDataAdapter.kt | 29 ++++++++++++++++ .../adapter/{ => article}/cli/ArticleCli.kt | 2 +- .../persistence/ArticleIMemoryDataAdapter.kt} | 4 +-- .../persistence/ArticleJpaDataAdapter.kt | 2 +- 14 files changed, 181 insertions(+), 11 deletions(-) create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountCreateUseCase.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountQueryUseCase.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountRetrieveUseCase.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/account/model/Account.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/account/port/AccountPort.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountCreate.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountQuery.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountRetrieve.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/account/cli/AccountCli.kt create mode 100644 src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/account/persistence/AccountInMemoryDataAdapter.kt rename src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/{ => article}/cli/ArticleCli.kt (91%) rename src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/{persistence/ArticleImMemoryDataAdapter.kt => article/persistence/ArticleIMemoryDataAdapter.kt} (88%) rename src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/{ => article}/persistence/ArticleJpaDataAdapter.kt (88%) diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/HexagonalArchitectApplication.kt b/src/main/kotlin/com/cubetiqs/hexagonal/HexagonalArchitectApplication.kt index f219e14..add112b 100644 --- a/src/main/kotlin/com/cubetiqs/hexagonal/HexagonalArchitectApplication.kt +++ b/src/main/kotlin/com/cubetiqs/hexagonal/HexagonalArchitectApplication.kt @@ -1,7 +1,9 @@ package com.cubetiqs.hexagonal -import com.cubetiqs.hexagonal.infrastructure.adapter.cli.ArticleCli -import com.cubetiqs.hexagonal.infrastructure.adapter.persistence.ArticleImMemoryDataAdapter +import com.cubetiqs.hexagonal.infrastructure.adapter.account.cli.AccountCli +import com.cubetiqs.hexagonal.infrastructure.adapter.account.persistence.AccountInMemoryDataAdapter +import com.cubetiqs.hexagonal.infrastructure.adapter.article.cli.ArticleCli +import com.cubetiqs.hexagonal.infrastructure.adapter.article.persistence.ArticleIMemoryDataAdapter import org.slf4j.LoggerFactory import org.springframework.boot.CommandLineRunner import org.springframework.boot.autoconfigure.SpringBootApplication @@ -12,19 +14,37 @@ 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 account cli instance + val accountCli = AccountCli(AccountInMemoryDataAdapter()) + + // create new account object via cli + val account = accountCli.create("Sambo Chea", "sombochea@cubetiqs.com", "123456") + logger.info("Account created: {}", account) + + // get created account id + val accountId = account.id!! + + // retrieve account via cli + val accountRetrieved = accountCli.retrieve(accountId) + logger.info("Account retrieved: {}", accountRetrieved) + + // query account via cli + val accountQuery = accountCli.query("sambo") + logger.info("Account query found: {}", accountQuery) + + // create article cli instance + val articleCli = ArticleCli(ArticleIMemoryDataAdapter()) // create new article object via cli - val article = cli.create(1L, "Article 1", "Description 1") + val article = articleCli.create(accountId, "Article 1", "Description 1") logger.info("Article created: {}", article) // retrieve article via cli - val articleRetrieve = cli.retrieve(1L) + val articleRetrieve = articleCli.retrieve(accountId) logger.info("Article retrieved: {}", articleRetrieve) // query articles via cli - val articleQuery = cli.query(1L) + val articleQuery = articleCli.query(accountId) logger.info("Query found articles: {}", articleQuery) } } diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountCreateUseCase.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountCreateUseCase.kt new file mode 100644 index 0000000..de058b5 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountCreateUseCase.kt @@ -0,0 +1,13 @@ +package com.cubetiqs.hexagonal.domain.account + +import com.cubetiqs.hexagonal.domain.account.model.Account +import com.cubetiqs.hexagonal.domain.account.port.AccountPort +import com.cubetiqs.hexagonal.domain.account.usecase.AccountCreate + +class AccountCreateUseCase constructor( + private val accountPort: AccountPort, +) { + fun create(useCase: AccountCreate): Account { + return accountPort.create(useCase) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountQueryUseCase.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountQueryUseCase.kt new file mode 100644 index 0000000..d5a7cfa --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountQueryUseCase.kt @@ -0,0 +1,13 @@ +package com.cubetiqs.hexagonal.domain.account + +import com.cubetiqs.hexagonal.domain.account.model.Account +import com.cubetiqs.hexagonal.domain.account.port.AccountPort +import com.cubetiqs.hexagonal.domain.account.usecase.AccountQuery + +class AccountQueryUseCase constructor( + private val accountPort: AccountPort, +) { + fun query(useCase: AccountQuery): Collection { + return accountPort.query(useCase) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountRetrieveUseCase.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountRetrieveUseCase.kt new file mode 100644 index 0000000..6809077 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/AccountRetrieveUseCase.kt @@ -0,0 +1,13 @@ +package com.cubetiqs.hexagonal.domain.account + +import com.cubetiqs.hexagonal.domain.account.model.Account +import com.cubetiqs.hexagonal.domain.account.port.AccountPort +import com.cubetiqs.hexagonal.domain.account.usecase.AccountRetrieve + +class AccountRetrieveUseCase constructor( + private val accountPort: AccountPort, +) { + fun retrieve(useCase: AccountRetrieve): Account { + return accountPort.retrieve(useCase) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/model/Account.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/model/Account.kt new file mode 100644 index 0000000..eb27efd --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/model/Account.kt @@ -0,0 +1,12 @@ +package com.cubetiqs.hexagonal.domain.account.model + +open class Account ( + var id: Long? = null, + var name: String? = null, + var email: String? = null, + var password: String? = null, +) { + override fun toString(): String { + return "Account(id=$id, name=$name, password=$password, email=$email)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/port/AccountPort.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/port/AccountPort.kt new file mode 100644 index 0000000..fc5f842 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/port/AccountPort.kt @@ -0,0 +1,12 @@ +package com.cubetiqs.hexagonal.domain.account.port + +import com.cubetiqs.hexagonal.domain.account.model.Account +import com.cubetiqs.hexagonal.domain.account.usecase.AccountCreate +import com.cubetiqs.hexagonal.domain.account.usecase.AccountQuery +import com.cubetiqs.hexagonal.domain.account.usecase.AccountRetrieve + +interface AccountPort { + fun create(useCase: AccountCreate): Account + fun retrieve(useCase: AccountRetrieve): Account + fun query(useCase: AccountQuery): Collection +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountCreate.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountCreate.kt new file mode 100644 index 0000000..43b8944 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountCreate.kt @@ -0,0 +1,11 @@ +package com.cubetiqs.hexagonal.domain.account.usecase + +open class AccountCreate ( + var name: String, + var email: String, + var password: String, +) { + override fun toString(): String { + return "AccountCreate(name='$name', email='$email', password='$password')" + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountQuery.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountQuery.kt new file mode 100644 index 0000000..7b3deec --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountQuery.kt @@ -0,0 +1,9 @@ +package com.cubetiqs.hexagonal.domain.account.usecase + +open class AccountQuery( + var search: String, +) { + override fun toString(): String { + return "AccountQuery(search=$search)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountRetrieve.kt b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountRetrieve.kt new file mode 100644 index 0000000..efa8253 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/domain/account/usecase/AccountRetrieve.kt @@ -0,0 +1,9 @@ +package com.cubetiqs.hexagonal.domain.account.usecase + +open class AccountRetrieve( + var id: Long, +) { + override fun toString(): String { + return "AccountRetrieve(id=$id)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/account/cli/AccountCli.kt b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/account/cli/AccountCli.kt new file mode 100644 index 0000000..87bc55d --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/account/cli/AccountCli.kt @@ -0,0 +1,29 @@ +package com.cubetiqs.hexagonal.infrastructure.adapter.account.cli + +import com.cubetiqs.hexagonal.domain.account.model.Account +import com.cubetiqs.hexagonal.domain.account.port.AccountPort +import com.cubetiqs.hexagonal.domain.account.usecase.AccountCreate +import com.cubetiqs.hexagonal.domain.account.usecase.AccountQuery +import com.cubetiqs.hexagonal.domain.account.usecase.AccountRetrieve + +class AccountCli constructor( + private val accountPort: AccountPort, +) { + fun create(name: String, email: String, password: String): Account { + return accountPort.create( + AccountCreate( + name = name, + email = email, + password = password, + ) + ) + } + + fun retrieve(accountId: Long): Account { + return accountPort.retrieve(AccountRetrieve(accountId)) + } + + fun query(search: String): Collection { + return accountPort.query(AccountQuery(search)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/account/persistence/AccountInMemoryDataAdapter.kt b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/account/persistence/AccountInMemoryDataAdapter.kt new file mode 100644 index 0000000..87aa261 --- /dev/null +++ b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/account/persistence/AccountInMemoryDataAdapter.kt @@ -0,0 +1,29 @@ +package com.cubetiqs.hexagonal.infrastructure.adapter.account.persistence + +import com.cubetiqs.hexagonal.domain.account.model.Account +import com.cubetiqs.hexagonal.domain.account.port.AccountPort +import com.cubetiqs.hexagonal.domain.account.usecase.AccountCreate +import com.cubetiqs.hexagonal.domain.account.usecase.AccountQuery +import com.cubetiqs.hexagonal.domain.account.usecase.AccountRetrieve +import java.util.concurrent.ConcurrentHashMap + +class AccountInMemoryDataAdapter : AccountPort { + companion object { + private val accounts = ConcurrentHashMap() + } + + override fun create(useCase: AccountCreate): Account { + val id = (accounts.size + 1).toLong() + val account = Account(id, useCase.name, useCase.email, useCase.password) + accounts[id] = account + return account + } + + override fun retrieve(useCase: AccountRetrieve): Account { + return accounts[useCase.id] ?: throw IllegalArgumentException("Account not found") + } + + override fun query(useCase: AccountQuery): Collection { + return accounts.values.filter { it.name?.contains(useCase.search, ignoreCase = true) == true } + } +} \ 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/article/cli/ArticleCli.kt similarity index 91% rename from src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/cli/ArticleCli.kt rename to src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/article/cli/ArticleCli.kt index afb0bdc..b4c048f 100644 --- a/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/cli/ArticleCli.kt +++ b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/article/cli/ArticleCli.kt @@ -1,4 +1,4 @@ -package com.cubetiqs.hexagonal.infrastructure.adapter.cli +package com.cubetiqs.hexagonal.infrastructure.adapter.article.cli import com.cubetiqs.hexagonal.domain.article.model.Article import com.cubetiqs.hexagonal.domain.article.port.ArticlePort diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleImMemoryDataAdapter.kt b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/article/persistence/ArticleIMemoryDataAdapter.kt similarity index 88% rename from src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleImMemoryDataAdapter.kt rename to src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/article/persistence/ArticleIMemoryDataAdapter.kt index 98fc8b7..d8e8b1e 100644 --- a/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleImMemoryDataAdapter.kt +++ b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/article/persistence/ArticleIMemoryDataAdapter.kt @@ -1,4 +1,4 @@ -package com.cubetiqs.hexagonal.infrastructure.adapter.persistence +package com.cubetiqs.hexagonal.infrastructure.adapter.article.persistence import com.cubetiqs.hexagonal.domain.article.model.Article import com.cubetiqs.hexagonal.domain.article.port.ArticlePort @@ -6,7 +6,7 @@ import com.cubetiqs.hexagonal.domain.article.usecase.ArticleCreate import com.cubetiqs.hexagonal.domain.article.usecase.ArticleQuery import java.util.concurrent.ConcurrentHashMap -class ArticleImMemoryDataAdapter : ArticlePort { +class ArticleIMemoryDataAdapter : ArticlePort { companion object { private val articles = ConcurrentHashMap() } diff --git a/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleJpaDataAdapter.kt b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/article/persistence/ArticleJpaDataAdapter.kt similarity index 88% rename from src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleJpaDataAdapter.kt rename to src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/article/persistence/ArticleJpaDataAdapter.kt index 0967ddc..0e04ff5 100644 --- a/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/persistence/ArticleJpaDataAdapter.kt +++ b/src/main/kotlin/com/cubetiqs/hexagonal/infrastructure/adapter/article/persistence/ArticleJpaDataAdapter.kt @@ -1,4 +1,4 @@ -package com.cubetiqs.hexagonal.infrastructure.adapter.persistence +package com.cubetiqs.hexagonal.infrastructure.adapter.article.persistence import com.cubetiqs.hexagonal.domain.article.model.Article import com.cubetiqs.hexagonal.domain.article.port.ArticlePort