private[this] def validateCascadedProperty[T]()

in util-validator/src/main/scala/com/twitter/util/validation/ScalaValidator.scala [1029:1096]


  private[this] def validateCascadedProperty[T](
    context: ValidationContext[T],
    propertyDescriptor: PropertyDescriptor,
    clazzInstance: Any,
    groups: Seq[Class[_]]
  ): Set[ConstraintViolation[T]] = propertyDescriptor.cascadedScalaType match {
    case Some(cascadedScalaType) =>
      // Update the found value with the current landscape, for example, the retrieved case class
      // descriptor may be scala type Foo, but this property is a Seq[Foo] or an Option[Foo] and
      // we want to carry that property typing through.
      val caseClassDescriptor =
        descriptorFactory
          .describe[T](cascadedScalaType.erasure.asInstanceOf[Class[T]])
          .copy(scalaType = propertyDescriptor.scalaType)

      val caseClassPath = PathImpl.createCopy(context.path)
      caseClassDescriptor.scalaType match {
        case argType if argType.isCollection =>
          val results = mutable.ListBuffer[ConstraintViolation[T]]()
          val collectionValue: Iterable[_] = clazzInstance.asInstanceOf[Iterable[_]]
          val collectionValueIterator = collectionValue.iterator
          var index = 0
          while (collectionValueIterator.hasNext) {
            val instanceValue = collectionValueIterator.next()
            // apply the index to the parent path, then use this to recompute paths of members and methods
            val indexedPropertyPath = {
              val indexedPath = PathImpl.createCopyWithoutLeafNode(caseClassPath)
              indexedPath.addPropertyNode(
                s"${caseClassPath.getLeafNode.asString()}[${index.toString}]")
              indexedPath
            }
            val violations = validate[T](
              maybeDescriptor = Some(
                caseClassDescriptor
                  .copy(
                    scalaType = caseClassDescriptor.scalaType.typeArgs.head,
                    members = caseClassDescriptor.members,
                    methods = caseClassDescriptor.methods
                  )
              ),
              context = context.copy(path = indexedPropertyPath),
              value = instanceValue,
              groups = groups
            )
            if (violations.nonEmpty) results.appendAll(violations)
            index += 1
          }
          if (results.nonEmpty) results.toSet
          else Set.empty[ConstraintViolation[T]]
        case argType if argType.isOption =>
          val optionValue = clazzInstance.asInstanceOf[Option[_]]
          validate[T](
            maybeDescriptor = Some(
              caseClassDescriptor.copy(scalaType = caseClassDescriptor.scalaType.typeArgs.head)),
            context = context.copy(path = caseClassPath),
            value = optionValue,
            groups = groups
          )
        case _ =>
          validate[T](
            maybeDescriptor = Some(caseClassDescriptor),
            context = context.copy(path = caseClassPath),
            value = clazzInstance,
            groups = groups
          )
      }
    case _ => Set.empty[ConstraintViolation[T]]
  }