playframework scalaのリフレクション

先のブログのプロジェクトの機能追加として、CSVファイルから、部品表(PartsStructureテーブル)を登録する機能について検討。
CVSファイルを、play.api.mvc.MultipartFormData.FilePartで取り込む。
取り込んだファイルをjava.io.FileInputStream,scala.io.Source.fromInputStreamでscala.io.BufferedSourceに取り込み、getLineメソッドでIteratorへ。

    val file = atach.ref.file
    val fis = new FileInputStream(file)
    val src = Source.fromInputStream(fis)
    val itr = src.getLines

Iterator[String]の各行と変換後のBean名をパラメータで受け取り、Any型を戻り値とする変換クラス(CastBean.scala)を製作。
大雑把な仕様は、
第2パラメータで受けたbeanクラス名(String)から、beanの属性を取得。
第1パラメータで受けたStringをカンマで区切り、順に取得した属性にセットする。
参考にしたページ
scala.reflect.runtime.{universe= ru}のruntimeMirrorを生成。
beanクラス名から、classSymbolを生成。
Class.forName(clsName).newInstance()にてインスタンス取得後、
runtimeMirror.reflectメソッドで、インスタンスミラー取得。
classSymbolのdeclarationメソッドを利用して各fieldSymbolを取得。
その際、field名が必要になる。
field名の取得は、Class.forName(clsName).getDeclaredFields()にて、フィールド名のコレクション
を取得し、各フィールドに対しruntimeMirror.newTermNameメソッドでフィールドシンボルを取得。
インスタンスミラーのreflectFieldメソッドにてフィールドミラー取得。
あとは、setterメソッドでCSVで切り分けた値をセット。

def stringToBean(it: String , clsName: String):Any = {
  import scala.reflect.runtime.{universe => ru}
  val runtimeMirror=ru.runtimeMirror(Thread.currentThread.getContextClassLoader)
  val beanClassSymbol = runtimeMirror.staticClass(clsName).toType
  val bcm = Class.forName(clsName).newInstance()
  val bim = runtimeMirror.reflect(bcm)
  var i:Int=0
  if(it!="") {
    for(f<-Class.forName(clsName).getDeclaredFields()){
       val fieldSymbol= beanClassSymbol.declaration(ru.newTermName(f.getName())).asTerm
       val fm =bim.reflectField(fieldSymbol)
       fm.set(
         f.getType().getName() match {
            case "long" => it.split(",").apply(i) match{
               case "" => 0
               case _ => it.split(",").apply(i).toInt
            }
            case _ => it.split(",").apply(i) match{
              case "" => " "
              case _ => it.split(",").apply(i)
            }
         }
       )
       i += 1
    }
  }
  bcm
}

呼び出し元では、Any型を、asInstanceメソッドで、テーブルの型へ変換する。
クラスネーム(String)をパラメータで受けることにより、PSテーブルとの依存度を下げれた。
他のテーブルへの出力にも利用可能。