Asakusa FrameworkをScalaで記述してみるAfwHS α版のバージョン0.004。
バージョン0.003の考察の結果、バージョン0.004ではケースクラスを手で作るのをやめ、AsakusaFWのDMDLからScalaクラスを生成することにした。
(データモデルドライバーでDMDLからファイルを生成することが出来るのだし)
生成するScalaクラスは、継承関係は持たせず、ラッパークラスとすることにする。
暗黙変換を用いればシームレスに扱うことは出来そうだけれど、一応JavaConvertersを踏襲して、asScala・asJavaで明示的に変換することにする。
Summarizeをどうするか考えないといけない。
と言うのは、Summarizeの定義をケースクラスで行うのではなく、処理の記述の中で行っていたから。
そのままにしておく事も出来るけれども、処理中でも定義しDMDLでも定義するという二重定義は美しくない。
幸い、データモデルクラスにアノテーションで情報が付いていて、実行時に取得することが出来る。素晴らしい!
あと、ついでに、cogroupに渡していた関数の引数も、ScalaのSeqや自前のResultではなく、AsakusaFWで実際の引数となるjava.util.ListやAsakusaFWのResultクラスにしよう。
そうすれば、AsakusaFW上での実行時に変換をする必要が無くなる。(変換したければ各自の関数内でやってね、とw)
//バージョン0.003
def splitText(s1: Seq[LineModel], r1: Result[WordCountModel]): Unit = {
s1.foreach {
_.text.split("[ \t]+").foreach { word => r1.add(WordCountModel(word, 1)) }
}
}
↓
//バージョン0.004(java.util.ListやAsakusaFWのモデルクラスをそのまま使う場合)
def splitText(s1: JList[LineModel], r1: AResult[WordCountModel]): Unit = {
val i = s1.iterator()
while (i.hasNext()) {
i.next().getTextAsString().split("[ \t]+").foreach { word =>
val r = new WordCountModel
r.setWordAsString(word)
r.setCount(1)
r1.add(r)
}
}
}
↓(Scalaのラッパーとの変換を駆使)
def splitText(s1: JList[LineModel], r1: AResult[WordCountModel]): Unit = {
s1.asScala.foreach {
_.asScala.text.split("[ \t]+").foreach { word => r1.add(WordCountModelWrapper(word, 1).asJava) }
}
}
↓(ラッパーとの変換を暗黙変換にするのも良し)
implicit def convertLineModel2Wrapper(m: LineModel) = new LineModelWrapper(m)
implicit def convertWrapper2WordCountModel(w: WordCountModelWrapper) = w.asJava
def splitText(s1: JList[LineModel], r1: AResult[WordCountModel]): Unit = {
s1.asScala.foreach {
_.text.split("[ \t]+").foreach { word => r1.add(WordCountModelWrapper(word, 1)) }
}
}