All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.swagger.scala.converter.ErasureHelper.scala Maven / Gradle / Ivy

package com.github.swagger.scala.converter

import org.slf4j.LoggerFactory

import scala.annotation.tailrec
import scala.reflect.runtime.universe
import scala.util.Try
import scala.util.control.NonFatal

private[converter] object ErasureHelper {
  private val logger = LoggerFactory.getLogger(ErasureHelper.getClass)

  def erasedOptionalPrimitives(cls: Class[_]): Map[String, Class[_]] = {
    try {
      val mirror = universe.runtimeMirror(Thread.currentThread().getContextClassLoader)
      val classSymbol = mirror.classSymbol(cls)
      val ConstructorName = "apply"
      val companion: universe.Symbol = classSymbol.typeSignature.member(universe.TermName(ConstructorName))
      val properties =
        Try(companion.asTerm.alternatives.head.asMethod.paramLists.flatten).getOrElse {
          classSymbol.selfType.members
            .filterNot(_.isMethod)
            .filterNot(_.isClass)
        }

      properties.flatMap { prop: universe.Symbol =>
        val maybeClass: Option[Class[_]] = prop.typeSignature.typeArgs.headOption.flatMap { signature =>
          if (signature.typeSymbol.isClass) {
            signature.typeArgs.headOption match {
              case Some(typeArg) => {
                val resultType: universe.Type = nestedTypeArg(typeArg)
                val resultClass = mirror.runtimeClass(resultType)
                if (resultClass.isPrimitive) Option(resultClass) else None
              }
              case _ => Option(mirror.runtimeClass(signature))
            }
          } else {
            None
          }
        }
        maybeClass.map(prop.name.toString.trim -> _)
      }.toMap
    } catch {
      case NonFatal(t) => {
        if (logger.isDebugEnabled) {
          // use this form because of Scala 2.11 & 2.12 compile issue
          logger.debug(s"Unable to get type info ${Option(cls.getName).getOrElse("null")}", t)
        } else {
          logger.info(s"Unable to get type info ${Option(cls.getName).getOrElse("null")}: $t")
        }
        Map.empty[String, Class[_]]
      }
      case err: NoClassDefFoundError => {
        if (logger.isDebugEnabled) {
          // use this form because of Scala 2.11 & 2.12 compile issue
          logger.debug(s"Unable to get type info ${Option(cls.getName).getOrElse("null")}", err)
        } else {
          logger.info(s"Unable to get type info ${Option(cls.getName).getOrElse("null")}: $err")
        }
        Map.empty[String, Class[_]]
      }
    }
  }

  @tailrec
  private def nestedTypeArg(typeArg: universe.Type): universe.Type = {
    typeArg.typeArgs.headOption match {
      case Some(innerArg) => nestedTypeArg(innerArg)
      case _ => typeArg
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy