in util-validator/src/main/scala/com/twitter/util/validation/ScalaValidator.scala [1165:1244]
private[this] def validate[T](
maybeDescriptor: Option[Descriptor],
context: ValidationContext[T],
value: Any,
groups: Seq[Class[_]]
): Set[ConstraintViolation[T]] = maybeDescriptor match {
case Some(descriptor) =>
descriptor match {
case p: PropertyDescriptor =>
val propertyPath = PathImpl.createCopy(context.path)
context.fieldName.map(propertyPath.addPropertyNode)
// validateField recurses back through validate for cascaded properties
validateField[T](context.copy(path = propertyPath), p, value, groups)
case c: CaseClassDescriptor[_] =>
val memberViolations = {
val results = new mutable.ListBuffer[ConstraintViolation[T]]()
if (c.members.nonEmpty) {
val keys: Iterable[String] = c.members.keys
val keyIterator = keys.iterator
while (keyIterator.hasNext) {
val name = keyIterator.next()
val propertyDescriptor = c.members(name)
val propertyPath = PathImpl.createCopy(context.path)
propertyPath.addPropertyNode(DescriptorFactory.unmangleName(name))
// validateField recurses back through validate here for cascaded properties
val fieldResults =
validateField[T](
context.copy(fieldName = Some(name), path = propertyPath),
propertyDescriptor,
findFieldValue(value, c.clazz, name),
groups)
if (fieldResults.nonEmpty) results.appendAll(fieldResults)
}
}
results.toSet
}
val methodViolations = {
val results = new ListBuffer[ConstraintViolation[T]]()
if (c.methods.nonEmpty) {
var index = 0
val length = c.methods.length
while (index < length) {
val methodResults = value match {
case null | None =>
Set.empty
case Some(obj) =>
validateMethod[T](context.copy(fieldName = None), c.methods(index), obj, groups)
case _ =>
validateMethod[T](
context.copy(fieldName = None),
c.methods(index),
value,
groups)
}
if (methodResults.nonEmpty) results.appendAll(methodResults)
index += 1
}
}
results.toSet
}
val clazzViolations =
validateClazz[T](context, c.asInstanceOf[CaseClassDescriptor[T]], value, groups)
// put them all together
memberViolations ++ methodViolations ++ clazzViolations
}
case _ =>
val clazz: Class[T] = value.getClass.asInstanceOf[Class[T]]
if (ReflectTypes.notCaseClass(clazz))
throw new ValidationException(s"$clazz is not a valid case class.")
val caseClassDescriptor: CaseClassDescriptor[T] = descriptorFactory.describe(clazz)
val context = ValidationContext(
fieldName = None,
rootClazz = Some(clazz),
root = Some(value.asInstanceOf[T]),
leaf = Some(value),
path = PathImpl.createRootPath())
validate[T](Some(caseClassDescriptor), context, value, groups)
}