lundi 18 novembre 2019

Instantiating an empty object of parametric type

I'm trying to make a CSV reader that parse a CSV file with a header into a list of "line object". Those "line objects" are of a type given by the caller of the function.

The idea is to be able to use the CSV reader like that:

case class PlayerData(btag: String, team: String, status: String, role: String)
//...
val p = CSV.from_filename("all-team.test.csv").extract[PlayerData]
for(PlayerData(b, t, _, r) <- p) {
  println(s"btag: $b, team: $t, role: $r")
}

I have some issues instantiating the object in the extract function. Currently, the function is the following:

class CSV(data: List[List[String]]) {

  def make_instance[T: ClassTag]: Option[T] = classTag[T].runtimeClass.newInstance match {
    case v: T => Some(v)
    case _ => None
  }

  def get_term[T: TypeTag](term: String) = ru.typeOf[T].decl(ru.TermName(term)).asTerm

  def get_mirror[T: ClassTag] = ru.runtimeMirror(classTag[T].runtimeClass.getClassLoader)

  def extract[T:ClassTag:TypeTag](): List[T] = {
    val header = data.head
    val datas = data.tail
    data.map(row => {
               val res: T = make_instance[T].get
               for(i <- 0 to row.length) {
                 val data_symb = get_term[T](header(i))
                 val m = get_mirror[T]
                 val im = m.reflect(res)
                 val data_mirror = im.reflectField(data_symb)
                 data_mirror.set(datas(i))
               }
               res
             })
  }
}

The code compiles but during execution, I have the following exception:

[error] (run-main-0) java.lang.InstantiationException: CLI$PlayerData
[error] java.lang.InstantiationException: CLI$PlayerData
[error]         at java.base/java.lang.Class.newInstance(Class.java:547)
[error]         at CSV.make_instance(csv.scala:63)
[error] eam-statat CSV.$anonfun$extract$1(csv.scala:79)
[error]     at scala.collection.immutable.List.map(List.scala:286)
[error]     at CSV.extract(csv.scala:78)
[error]     at CLI$.main(test.scala:61)
[error]     at CLI.main(test.scala)
[error]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error]     at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error]     at java.base/java.lang.reflect.Method.invoke(Method.java:564)
[error] Caused by: java.lang.NoSuchMethodException: CLI$PlayerData.<init>()
[error]     at java.base/java.lang.Class.getConstructor0(Class.java:3302)
[error]     at java.base/java.lang.Class.newInstance(Class.java:532)
[error]     at CSV.make_instance(csv.scala:63)
[error]     at CSV.$anonfun$extract$1(csv.scala:79)
[error]     at scala.collection.immutable.List.map(List.scala:286)
[error]     at CSV.extract(csv.scala:78)
[error]     at CLI$.main(test.scala:61)
[error]     at CLI.main(test.scala)
[error]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error]     at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error]     at java.base/java.lang.reflect.Method.invoke(Method.java:564)

How do I create the object I'm trying to fill using the CSV row?





Aucun commentaire:

Enregistrer un commentaire