Manish
Manish

Reputation: 36

How to get all types and column names in nested case class in a Map

case class Address( address :String ,pinCode : Int)      

case class Person (a: String,b:Int ,c: Address)

def getClassDefinition[T:TypeTag] =
  (typeOf[T].members.filter(!_.isMethod).map(r  => (r.name -> r.typeSignature)))

val m  = getClassDefinition[Address]

(pinCode ,scala.Int)
(address ,String)    

val p =getClassDefinition[Person]

(c ,A$A332.this.Address)
(b ,scala.Int)
(a ,String)

I am looking for an nested result instead of just going till Address case class

Upvotes: 0

Views: 286

Answers (1)

richj
richj

Reputation: 7529

If I understand the problem, it is to get a class definition that includes a name -> type signature pair for each of the the non-method members of the type. If the type signature is a standard type, that is all that is required; but for some types a nested definition is required. I've modelled this either/or case with an Either[Definition, NestedDefinition].

In this example I've chosen an isNested(...) rule that matches on the package name, but it could be any rule that identifies a class for deeper inspection.

I'm not sure if the output is in the format that you expected, but you can either modify the example code, or map the result into your own data structure.

import scala.reflect.runtime.universe._

object TypeTags {
  // Define your domain name here for the isNested(...) test!
  val myDomainName: String = ???

  // Define some type aliases
  type Definition = ((AnyRef with SymbolApi)#NameType, Type)
  type EitherDefinitionOrNested = Either[Definition, NestedDefinition]

  // A nested definition contains the original definition and an iterable collection of its member definitions (recursively).
  case class NestedDefinition(t: Definition, m: Iterable[EitherDefinitionOrNested])

  // The test to determine if a nested definition is needed.
  def isNested(r: Symbol): Boolean = {
    r.info.typeSymbol.fullName.startsWith(myDomainName)
  }

  // Obtain a class definition from a Symbol.
  def classDefinition(symbol: Symbol): Iterable[EitherDefinitionOrNested] = {
    symbol.typeSignature.members.filter(!_.isMethod).map {
      case r @ nested if isNested(r) => Right(NestedDefinition(nested.name -> nested.typeSignature, classDefinition(nested)))
      case r                         => Left(r.name -> r.typeSignature)
    }
  }

  // Obtain a class definition from a type.
  def getClassDefinition[T: TypeTag]: Iterable[EitherDefinitionOrNested] = classDefinition(typeOf[T].typeSymbol)

  // The test case
  case class Address(address: String ,pinCode: Int)

  case class Person(a: String, b: Int ,c: Address)

  def main(args: Array[String]): Unit = {
    val m = getClassDefinition[Address]
    val p = getClassDefinition[Person]

    println(s"address: $m")
    println(s"person: $p")
  }
}

Upvotes: 1

Related Questions