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)) } } }