Skip to content

Instantly share code, notes, and snippets.

@seamusv
Created November 25, 2019 16:42
Show Gist options
  • Save seamusv/76ae7f72d59412d8fd6b10d491d19e93 to your computer and use it in GitHub Desktop.
Save seamusv/76ae7f72d59412d8fd6b10d491d19e93 to your computer and use it in GitHub Desktop.
package ca.yk.gov.cfs.fm.common
object validators {
import rules._
val centreCodeRule: RuleOp[String] = nonEmpty && maxLength(10)
val accountCodeOp: ValidatorOp[String] = define("ACCOUNT_CODE", nonEmpty && maxLength(22))
val billingCentreCodeOp: ValidatorOp[String] = define("BILLING_CODE", centreCodeRule || startsWith("B"))
val orderNumberPrefixOp: ValidatorOp[String] = define("ORDER_NUMBER_PREFIX", (nonEmpty && maxLength(2)) || pattern("^[a-zA-Z]+$".r))
val organisationOp: ValidatorOp[String] = define("ORGANISATION", nonEmpty && maxLength(6))
val shippingCentreCodeOp: ValidatorOp[String] = define("SHIPPING_CODE", centreCodeRule || startsWith("S"))
val vendorCodeOp: ValidatorOp[String] = define("VENDOR_CODE", nonEmpty && maxLength(12))
}
object CatsValidated {
import cats.data.ValidatedNec
import cats.implicits._
import rules._
type ValidationResult[A] = ValidatedNec[DomainErrors, A]
def validate[A](argument: A, validator: ValidatorOp[A]): ValidationResult[A] = {
def loopRule(fieldName: String, rule: RuleOp[A]): ValidationResult[A] = rule match {
case RuleOp.MaxLengthRuleOp(maxLength) =>
Option(argument) match {
case Some(s: String) if s.trim.length > maxLength => MaxLengthExceeded(fieldName, maxLength).invalidNec
case _ => argument.validNec
}
case RuleOp.NonEmptyRuleOp =>
Option(argument) match {
case Some(s: String) if s.trim.nonEmpty => argument.validNec
case _ => NonEmptyRequired(fieldName).invalidNec
}
case RuleOp.RegexRuleOp(regex) =>
Option(argument) match {
case Some(s: String) if regex.findAllIn(s).hasNext => argument.validNec
case _ => PatternMismatch(fieldName).invalidNec
}
case RuleOp.StartsWithRuleOp(startsWith) =>
Option(argument) match {
case Some(s: String) if s.trim.toUpperCase.startsWith(startsWith) => argument.validNec
case _ => StartsWithMismatch(fieldName, startsWith).invalidNec
}
case RuleOp.AndRuleOp(left, right) =>
List(loopRule(fieldName, left), loopRule(fieldName, right)).sequence_.as(argument)
case RuleOp.OrRuleOp(left, right) =>
loopRule(fieldName, left).andThen(_ => loopRule(fieldName, right))
}
def loop(validator: ValidatorOp[A]): ValidationResult[A] = validator match {
case ValidatorOp.Definition(fieldName, rules) => loopRule(fieldName, rules)
}
loop(validator)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment