validation.ValidationResult.scala Maven / Gradle / Ivy
package jap
package validation
trait ValidationResult[VR[_]] {
def getErrors[E](vr: VR[E]): List[E]
def valid[E]: VR[E]
def invalid[E](e: => E): VR[E]
def isValid[E](e: VR[E]): Boolean
def isInvalid[E](e: VR[E]): Boolean
def and[E](e1: => VR[E], e2: => VR[E]): VR[E]
def assert[E](cond: Boolean, error: VR[E]): VR[E] = if (cond) valid[E] else error
def or[E](e1: => VR[E], e2: => VR[E]): VR[E] =
if (this.isValid(e1)) valid
else if (this.isValid(e2)) valid
else this.and(e1, e2)
def sequence[E](results: Iterable[VR[E]]): VR[E] = results.foldLeft(valid[E])(and[E](_, _))
def sequence[E](results: VR[E]*): VR[E] = sequence[E](results)
def invalidPar[E](he: E, te: E*): VR[E] = if (te.isEmpty) invalid(he) else invalidPar(he +: te)
def invalidPar[E](errors: Iterable[E]) = sequence(errors.map(invalid[E](_)))
}
object ValidationResult {
def apply[VR[_]](implicit vr: ValidationResult[VR]): ValidationResult[VR] = vr
implicit class IterableErrorIdOps[E](iterable: Iterable[E]) {
def invalid[VR[_]: ValidationResult]: VR[E] = ValidationResult[VR].invalidPar(iterable)
}
implicit class ErrorIdOps[E](error: E) {
def invalid[VR[_]: ValidationResult]: VR[E] = ValidationResult[VR].invalid(error)
}
implicit class IterableValidationResultOps[VR[_]: ValidationResult, E](iterable: Iterable[VR[E]]) {
def sequence: VR[E] = ValidationResult[VR].sequence(iterable)
}
implicit class ValidationResultOps[VR[_]: ValidationResult, E](vr: => VR[E]) {
def and(that: => VR[E]): VR[E] = ValidationResult[VR].and(vr, that)
def or(that: => VR[E]): VR[E] = ValidationResult[VR].or(vr, that)
def getErrors: List[E] = ValidationResult[VR].getErrors(vr)
}
sealed abstract class Accumulate[+E]
implicit object Accumulate extends ValidationResult[Accumulate] {
case object Valid extends Accumulate[Nothing]
case class Invalid[+E] private[validation] (errorsF: () => List[E]) extends Accumulate[E] {
lazy val errors: List[E] = errorsF()
}
def valid[E]: Accumulate[E] = Accumulate.Valid
def invalid[E](e: => E): Accumulate[E] = Accumulate.Invalid(() => List(e))
def isValid[E](a: Accumulate[E]): Boolean = a == Accumulate.Valid
def isInvalid[E](a: Accumulate[E]): Boolean = a != Accumulate.Valid
def and[E](a: => Accumulate[E], b: => Accumulate[E]): Accumulate[E] =
(a, b) match {
case (Accumulate.Valid, Accumulate.Valid) => Accumulate.Valid
case (aa: Accumulate.Invalid[E], bb: Accumulate.Invalid[E]) => Accumulate.Invalid(() => aa.errors ++ bb.errors)
case (_: Accumulate.Invalid[E], _) => a
case _ => b
}
def getErrors[E](vr: Accumulate[E]): List[E] = vr match {
case e: Accumulate.Invalid[E] => e.errors
case Accumulate.Valid => Nil
}
}
case class FailFast[+E] private (run: () => Either[E, Unit]) {
lazy val either = run()
}
implicit object FailFast extends ValidationResult[FailFast] {
def valid[E]: FailFast[E] = FailFast(() => Right(()))
def invalid[E](e: => E): FailFast[E] = FailFast(() => Left(e))
def isValid[E](e: FailFast[E]): Boolean = e.either.isRight
def isInvalid[E](e: FailFast[E]): Boolean = e.either.isLeft
def and[E](e1: => FailFast[E], e2: => FailFast[E]): FailFast[E] = FailFast(() => e1.either.flatMap(_ => e2.either))
def getErrors[E](vr: FailFast[E]): List[E] = vr.either.left.toSeq.toList
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy