Add account implement

This commit is contained in:
Sambo Chea 2021-10-23 15:34:42 +07:00
parent 01a3be5616
commit e281ec16dd
Signed by: sombochea
GPG Key ID: 3C7CF22A05D95490
14 changed files with 181 additions and 11 deletions

View File

@ -1,7 +1,9 @@
package com.cubetiqs.hexagonal package com.cubetiqs.hexagonal
import com.cubetiqs.hexagonal.infrastructure.adapter.cli.ArticleCli import com.cubetiqs.hexagonal.infrastructure.adapter.account.cli.AccountCli
import com.cubetiqs.hexagonal.infrastructure.adapter.persistence.ArticleImMemoryDataAdapter 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.slf4j.LoggerFactory
import org.springframework.boot.CommandLineRunner import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.SpringBootApplication
@ -12,19 +14,37 @@ class HexagonalArchitectApplication : CommandLineRunner {
private val logger = LoggerFactory.getLogger(HexagonalArchitectApplication::class.java) private val logger = LoggerFactory.getLogger(HexagonalArchitectApplication::class.java)
override fun run(vararg args: String?) { override fun run(vararg args: String?) {
// create cli instance // create account cli instance
val cli = ArticleCli(ArticleImMemoryDataAdapter()) 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 // 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) logger.info("Article created: {}", article)
// retrieve article via cli // retrieve article via cli
val articleRetrieve = cli.retrieve(1L) val articleRetrieve = articleCli.retrieve(accountId)
logger.info("Article retrieved: {}", articleRetrieve) logger.info("Article retrieved: {}", articleRetrieve)
// query articles via cli // query articles via cli
val articleQuery = cli.query(1L) val articleQuery = articleCli.query(accountId)
logger.info("Query found articles: {}", articleQuery) logger.info("Query found articles: {}", articleQuery)
} }
} }

View File

@ -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)
}
}

View File

@ -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<Account> {
return accountPort.query(useCase)
}
}

View File

@ -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)
}
}

View File

@ -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)"
}
}

View File

@ -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<Account>
}

View File

@ -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')"
}
}

View File

@ -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)"
}
}

View File

@ -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)"
}
}

View File

@ -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<Account> {
return accountPort.query(AccountQuery(search))
}
}

View File

@ -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<Long, Account>()
}
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<Account> {
return accounts.values.filter { it.name?.contains(useCase.search, ignoreCase = true) == true }
}
}

View File

@ -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.model.Article
import com.cubetiqs.hexagonal.domain.article.port.ArticlePort import com.cubetiqs.hexagonal.domain.article.port.ArticlePort

View File

@ -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.model.Article
import com.cubetiqs.hexagonal.domain.article.port.ArticlePort 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 com.cubetiqs.hexagonal.domain.article.usecase.ArticleQuery
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
class ArticleImMemoryDataAdapter : ArticlePort { class ArticleIMemoryDataAdapter : ArticlePort {
companion object { companion object {
private val articles = ConcurrentHashMap<Long, Article>() private val articles = ConcurrentHashMap<Long, Article>()
} }

View File

@ -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.model.Article
import com.cubetiqs.hexagonal.domain.article.port.ArticlePort import com.cubetiqs.hexagonal.domain.article.port.ArticlePort