Skip to content

Instantly share code, notes, and snippets.

@zh012
Created October 24, 2016 19:59
Show Gist options
  • Select an option

  • Save zh012/626dcfd7b7abca39cc6ad7a365e673f3 to your computer and use it in GitHub Desktop.

Select an option

Save zh012/626dcfd7b7abca39cc6ad7a365e673f3 to your computer and use it in GitHub Desktop.
scala validator
package util.validate
import scala.util.{Failure, Success, Try}
object `package` {
class ValidationError(val msg: String) extends Exception(msg)
case object InvalidType extends ValidationError("invalid type")
def typeChecker[T: Manifest](v: Any): Try[Any] = v match {
case v: T => Success(v)
case _ => Failure(InvalidType)
}
def validator[I: Manifest, O](handler: I => O)(v: Any) =
typeChecker[I](v).flatMap(x => Try(handler(v.asInstanceOf[I])))
def checker[T: Manifest](handler: T => Boolean, errmsg: String="invalide value")(v: Any) =
validator[T, T] {i =>
if (handler(i))
i
else
throw new ValidationError(errmsg)
}(v)
def oneOf[T: Manifest](opts: Set[T])(v: Any) =
validator[T, T] {i =>
if (opts.contains(i))
i
else
throw new ValidationError("value should be one of [%s]".format(opts.mkString(",")))
}(v)
def ccToMap(cc: Product): Map[String, Any] = {
val values = cc.productIterator
cc.getClass.getDeclaredFields.map {
_.getName -> (values.next() match {
case p: Product if p.productArity > 0 => ccToMap(p)
case x => x
})
}.toMap
}
def checkErrors(data: Product,
validators: Option[Map[String, Any=>Try[_]]]=None,
defaultValidator: Option[Any=>Try[_]]=None
): Option[Map[String, String]] =
{
val dataMap = ccToMap(data)
val errs = dataMap.foldLeft[Map[String, String]](Map()) {
case (errors, (key, value)) =>
val vl = (validators.flatMap(_.get(key)) orElse defaultValidator).get
vl(value) match {
case Failure(e: ValidationError) => (errors + (key -> e.msg))
case Failure(e) => throw e
case _ => errors
}
}
if (errs.size == 0) None else Some(errs)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment