CommentId.kt
package com.example.realworldkotlinspringbootjdbc.domain.comment
import arrow.core.Option
import arrow.core.Validated
import arrow.core.ValidatedNel
import arrow.core.invalid
import arrow.core.invalidNel
import arrow.core.valid
import com.example.realworldkotlinspringbootjdbc.util.MyError
interface CommentId {
val value: Int
/**
* 実装
*/
private data class ValidatedCommentId(override val value: Int) : CommentId
private data class CommentIdWithoutValidation(override val value: Int) : CommentId
/**
* Factory メソッド
*/
companion object {
fun newWithoutValidation(id: Int): CommentId = CommentIdWithoutValidation(id)
fun new(id: Int?): ValidatedNel<ValidationError, CommentId> {
return when (val result = ValidationError.Required.check(id)) {
is Validated.Invalid -> result.value.invalidNel()
is Validated.Valid -> ValidationError.MustBeNaturalNumber.check(result.value)
.map { ValidatedCommentId(result.value) }
}
}
}
/**
* ドメインルール
*/
sealed interface ValidationError : MyError.ValidationError {
override val key: String get() = CommentId::class.simpleName.toString()
/**
* 必須
*/
object Required : ValidationError {
override val message: String
get() = "id を入力してください"
fun check(id: Int?): Validated<Required, Int> =
Option.fromNullable(id).fold(
{ Required.invalid() },
{ it.valid() }
)
}
/**
* 自然数(0より大きい整数)
*/
data class MustBeNaturalNumber(val id: Int) : ValidationError {
companion object {
fun check(id: Int): ValidatedNel<ValidationError, Int> =
if (id > 0) {
id.valid()
} else {
MustBeNaturalNumber(id).invalidNel()
}
}
override val message: String get() = "id は0より大きい整数にしてください"
}
}
}