Add basis domain logic and adapter for article impls

This commit is contained in:
Sambo Chea 2021-10-22 21:10:59 +07:00
parent 9355f913fd
commit 0e917f6a3d
Signed by: sombochea
GPG Key ID: 3C7CF22A05D95490
13 changed files with 182 additions and 2 deletions

View File

@ -1,10 +1,33 @@
package com.cubetiqs.hexagonal 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.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication import org.springframework.boot.runApplication
@SpringBootApplication @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<String>) { fun main(args: Array<String>) {
runApplication<HexagonalArchitectApplication>(*args) runApplication<HexagonalArchitectApplication>(*args)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Article> {
return articlePort.query(ArticleQuery.from(accountId))
}
}

View File

@ -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<Long, Article>()
}
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<Article> {
return articles.values.filter {
it.accountId == query.accountId
}
}
}

View File

@ -1 +0,0 @@

View File

@ -0,0 +1,2 @@
server:
port: 8080