Lift DomainMessage subtypes to top-level declarations in example
This commit is contained in:
parent
687c4c9d7f
commit
9d7c5f07f7
@ -1,11 +1,31 @@
|
||||
package com.github.michaelbull.result.example
|
||||
|
||||
import com.github.michaelbull.result.*
|
||||
import com.github.michaelbull.result.Err
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.andThen
|
||||
import com.github.michaelbull.result.example.model.domain.Customer
|
||||
import com.github.michaelbull.result.example.model.domain.CustomerCreated
|
||||
import com.github.michaelbull.result.example.model.domain.CustomerId
|
||||
import com.github.michaelbull.result.example.model.domain.CustomerIdMustBePositive
|
||||
import com.github.michaelbull.result.example.model.domain.CustomerNotFound
|
||||
import com.github.michaelbull.result.example.model.domain.CustomerRequired
|
||||
import com.github.michaelbull.result.example.model.domain.DatabaseError
|
||||
import com.github.michaelbull.result.example.model.domain.DatabaseTimeout
|
||||
import com.github.michaelbull.result.example.model.domain.DomainMessage
|
||||
import com.github.michaelbull.result.example.model.domain.EmailAddressChanged
|
||||
import com.github.michaelbull.result.example.model.domain.EmailInvalid
|
||||
import com.github.michaelbull.result.example.model.domain.EmailRequired
|
||||
import com.github.michaelbull.result.example.model.domain.EmailTooLong
|
||||
import com.github.michaelbull.result.example.model.domain.FirstNameRequired
|
||||
import com.github.michaelbull.result.example.model.domain.FirstNameTooLong
|
||||
import com.github.michaelbull.result.example.model.domain.LastNameRequired
|
||||
import com.github.michaelbull.result.example.model.domain.LastNameTooLong
|
||||
import com.github.michaelbull.result.example.model.domain.SqlCustomerInvalid
|
||||
import com.github.michaelbull.result.example.model.dto.CustomerDto
|
||||
import com.github.michaelbull.result.example.service.CustomerService
|
||||
import com.github.michaelbull.result.mapBoth
|
||||
import com.github.michaelbull.result.mapError
|
||||
import io.ktor.application.Application
|
||||
import io.ktor.application.call
|
||||
import io.ktor.application.install
|
||||
@ -72,36 +92,36 @@ fun Application.main() {
|
||||
|
||||
private fun readId(values: ValuesMap): Result<Long, DomainMessage> {
|
||||
val id = values["id"]?.toLongOrNull()
|
||||
return if (id != null) Ok(id) else Err(DomainMessage.CustomerRequired)
|
||||
return if (id != null) Ok(id) else Err(CustomerRequired)
|
||||
}
|
||||
|
||||
private fun messageToResponse(message: DomainMessage) = when (message) {
|
||||
DomainMessage.CustomerRequired,
|
||||
DomainMessage.CustomerIdMustBePositive,
|
||||
DomainMessage.FirstNameRequired,
|
||||
DomainMessage.FirstNameTooLong,
|
||||
DomainMessage.LastNameRequired,
|
||||
DomainMessage.LastNameTooLong,
|
||||
DomainMessage.EmailRequired,
|
||||
DomainMessage.EmailTooLong,
|
||||
DomainMessage.EmailInvalid ->
|
||||
CustomerRequired,
|
||||
CustomerIdMustBePositive,
|
||||
FirstNameRequired,
|
||||
FirstNameTooLong,
|
||||
LastNameRequired,
|
||||
LastNameTooLong,
|
||||
EmailRequired,
|
||||
EmailTooLong,
|
||||
EmailInvalid ->
|
||||
Pair(HttpStatusCode.BadRequest, "There is an error in your request")
|
||||
|
||||
// events
|
||||
DomainMessage.CustomerCreated ->
|
||||
CustomerCreated ->
|
||||
Pair(HttpStatusCode.Created, "Customer created")
|
||||
|
||||
is DomainMessage.EmailAddressChanged ->
|
||||
is EmailAddressChanged ->
|
||||
Pair(HttpStatusCode.OK, "Email address changed from ${message.old} to ${message.new}")
|
||||
|
||||
// exposed errors
|
||||
DomainMessage.CustomerNotFound ->
|
||||
CustomerNotFound ->
|
||||
Pair(HttpStatusCode.NotFound, "Unknown customer")
|
||||
|
||||
// internal errors
|
||||
DomainMessage.SqlCustomerInvalid,
|
||||
DomainMessage.DatabaseTimeout,
|
||||
is DomainMessage.DatabaseError ->
|
||||
SqlCustomerInvalid,
|
||||
DatabaseTimeout,
|
||||
is DatabaseError ->
|
||||
Pair(HttpStatusCode.InternalServerError, "Internal server error occurred")
|
||||
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ import com.github.michaelbull.result.Ok
|
||||
data class CustomerId(val id: Long) {
|
||||
companion object {
|
||||
fun create(id: Long?) = when {
|
||||
id == null -> Err(DomainMessage.CustomerRequired)
|
||||
id < 1 -> Err(DomainMessage.CustomerIdMustBePositive)
|
||||
id == null -> Err(CustomerRequired)
|
||||
id < 1 -> Err(CustomerIdMustBePositive)
|
||||
else -> Ok(CustomerId(id))
|
||||
}
|
||||
}
|
||||
|
@ -3,35 +3,34 @@ package com.github.michaelbull.result.example.model.domain
|
||||
/**
|
||||
* All possible things that can happen in the use-cases
|
||||
*/
|
||||
sealed class DomainMessage {
|
||||
sealed class DomainMessage
|
||||
|
||||
/* validation errors */
|
||||
/* validation errors */
|
||||
|
||||
object CustomerRequired : DomainMessage()
|
||||
object CustomerIdMustBePositive : DomainMessage()
|
||||
object CustomerRequired : DomainMessage()
|
||||
object CustomerIdMustBePositive : DomainMessage()
|
||||
|
||||
object FirstNameRequired : DomainMessage()
|
||||
object FirstNameTooLong : DomainMessage()
|
||||
object FirstNameRequired : DomainMessage()
|
||||
object FirstNameTooLong : DomainMessage()
|
||||
|
||||
object LastNameRequired : DomainMessage()
|
||||
object LastNameTooLong : DomainMessage()
|
||||
object LastNameRequired : DomainMessage()
|
||||
object LastNameTooLong : DomainMessage()
|
||||
|
||||
object EmailRequired : DomainMessage()
|
||||
object EmailTooLong : DomainMessage()
|
||||
object EmailInvalid : DomainMessage()
|
||||
object EmailRequired : DomainMessage()
|
||||
object EmailTooLong : DomainMessage()
|
||||
object EmailInvalid : DomainMessage()
|
||||
|
||||
/* events */
|
||||
/* events */
|
||||
|
||||
object CustomerCreated : DomainMessage()
|
||||
class EmailAddressChanged(val old: String, val new: String) : DomainMessage()
|
||||
object CustomerCreated : DomainMessage()
|
||||
class EmailAddressChanged(val old: String, val new: String) : DomainMessage()
|
||||
|
||||
/* exposed errors */
|
||||
/* exposed errors */
|
||||
|
||||
object CustomerNotFound : DomainMessage()
|
||||
object CustomerNotFound : DomainMessage()
|
||||
|
||||
/* internal errors */
|
||||
/* internal errors */
|
||||
|
||||
object SqlCustomerInvalid : DomainMessage()
|
||||
object DatabaseTimeout : DomainMessage()
|
||||
class DatabaseError(val reason: String?) : DomainMessage()
|
||||
}
|
||||
object SqlCustomerInvalid : DomainMessage()
|
||||
object DatabaseTimeout : DomainMessage()
|
||||
class DatabaseError(val reason: String?) : DomainMessage()
|
||||
|
@ -10,9 +10,9 @@ data class EmailAddress(
|
||||
private val pattern = ".+@.+\\..+".toRegex() // crude validation
|
||||
|
||||
fun create(address: String?) = when {
|
||||
address == null || address.isBlank() -> Err(DomainMessage.EmailRequired)
|
||||
address.length > 20 -> Err(DomainMessage.EmailTooLong)
|
||||
!address.matches(pattern) -> Err(DomainMessage.EmailInvalid)
|
||||
address == null || address.isBlank() -> Err(EmailRequired)
|
||||
address.length > 20 -> Err(EmailTooLong)
|
||||
!address.matches(pattern) -> Err(EmailInvalid)
|
||||
else -> Ok(EmailAddress(address))
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ data class PersonalName(
|
||||
) {
|
||||
companion object {
|
||||
fun create(first: String?, last: String?) = when {
|
||||
first == null || first.isBlank() -> Err(DomainMessage.FirstNameRequired)
|
||||
last == null || last.isBlank() -> Err(DomainMessage.LastNameRequired)
|
||||
first.length > 10 -> Err(DomainMessage.FirstNameTooLong)
|
||||
last.length > 10 -> Err(DomainMessage.LastNameTooLong)
|
||||
first == null || first.isBlank() -> Err(FirstNameRequired)
|
||||
last == null || last.isBlank() -> Err(LastNameRequired)
|
||||
first.length > 10 -> Err(FirstNameTooLong)
|
||||
last.length > 10 -> Err(LastNameTooLong)
|
||||
else -> Ok(PersonalName(first, last))
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,13 @@ import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.andThen
|
||||
import com.github.michaelbull.result.example.model.domain.Customer
|
||||
import com.github.michaelbull.result.example.model.domain.CustomerCreated
|
||||
import com.github.michaelbull.result.example.model.domain.CustomerId
|
||||
import com.github.michaelbull.result.example.model.domain.CustomerNotFound
|
||||
import com.github.michaelbull.result.example.model.domain.DatabaseError
|
||||
import com.github.michaelbull.result.example.model.domain.DatabaseTimeout
|
||||
import com.github.michaelbull.result.example.model.domain.DomainMessage
|
||||
import com.github.michaelbull.result.example.model.domain.EmailAddressChanged
|
||||
import com.github.michaelbull.result.example.model.entity.CustomerEntity
|
||||
import com.github.michaelbull.result.map
|
||||
import com.github.michaelbull.result.mapBoth
|
||||
@ -49,24 +54,24 @@ object CustomerService {
|
||||
|
||||
private fun createCustomer(entity: CustomerEntity) =
|
||||
Result.of { repository.insert(entity) }
|
||||
.map { DomainMessage.CustomerCreated }
|
||||
.map { CustomerCreated }
|
||||
.mapError(::exceptionToDomainMessage)
|
||||
|
||||
private fun findCustomer(customers: Collection<Customer>, id: CustomerId): Result<Customer, DomainMessage.CustomerNotFound> {
|
||||
private fun findCustomer(customers: Collection<Customer>, id: CustomerId): Result<Customer, CustomerNotFound> {
|
||||
val customer = customers.find { it.id == id }
|
||||
return if (customer != null) Ok(customer) else Err(DomainMessage.CustomerNotFound)
|
||||
return if (customer != null) Ok(customer) else Err(CustomerNotFound)
|
||||
}
|
||||
|
||||
private fun differenceBetween(old: Customer, new: Customer): DomainMessage.EmailAddressChanged? {
|
||||
private fun differenceBetween(old: Customer, new: Customer): EmailAddressChanged? {
|
||||
return if (new.email != old.email) {
|
||||
DomainMessage.EmailAddressChanged(old.email.address, new.email.address)
|
||||
EmailAddressChanged(old.email.address, new.email.address)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun exceptionToDomainMessage(t: Throwable) = when (t) {
|
||||
is SQLTimeoutException -> DomainMessage.DatabaseTimeout
|
||||
else -> DomainMessage.DatabaseError(t.message)
|
||||
is SQLTimeoutException -> DatabaseTimeout
|
||||
else -> DatabaseError(t.message)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.github.michaelbull.result.example.service
|
||||
|
||||
import com.github.michaelbull.result.example.model.entity.CustomerEntity
|
||||
import com.github.michaelbull.result.example.model.domain.repository.CustomerRepository
|
||||
import com.github.michaelbull.result.example.model.entity.CustomerEntity
|
||||
import java.sql.SQLException
|
||||
import java.sql.SQLTimeoutException
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user