ちょっと思い立って、Apache Velocity向けのScalaラッパーライブラリを書いてみました。
Velocity4s
https://github.com/kazuhira-r/velocity4s
名前に、何のひねりもありません。あと、単にソースをGitHubに置いているだけなので、あんまり意味ないでしょうけど。使い方はREADMEを参照。
こういったテンプレートに対して、
val templateAsString = """|$person.name |$person.age | |#foreach ($e in $list) |$e |#end | |#foreach ($k in $map.keys()) |$map[$k] |#end | |#foreach ($v in $some) |some($v) |#end |#foreach ($v in $none) |none |#end | |""".stripMargin val templateName = "template.vm"
ScalaのコレクションやOptionをforeachが解釈できるようにしたり
val context = new VelocityContext context.put("person", Person("Taro", 20)) context.put("list", List("Java", "Scala", "Groovy", "Clojure")) context.put("map", Map("key1" -> "value1", "key2" -> "value2")) context.put("some", Some("hello")) context.put("none", None)
(結果)
Taro 20 Java Scala Groovy Clojure value1 value2 some(hello)
Mapに対するキーアクセスを、JavaのMapのように扱えます。
val templateAsString = """$map["key"]"""
裏では、Map#getOrElse(key, null)に置き換わっていますが…。
プロパティアクセスも、一応OKです。
val templateAsString = "Hi, My name is $person.name!, $person.age years old"
マッピングするCase Class。
case class CasePerson(name: String, age: Int)
これで、Case Classのメンバーにアクセスできます。通常のクラスのvalなども同様です。
が、なんとなく思い立って書いてみたはいいものの、Velocityテンプレート上ではScalaで使えるはずの表現力がかなり落ちてしまうため、まあ難しいですね。それにこのアプローチ自体も、ScalaのライブラリをJavaに寄せるという形ですので。
需要なさそう(笑)。
まあ、個人的な練習を兼ねていますので、適当にメンテしてるかもしれません。
ちなみに最初の元ネタはここでした。
Velocity Plugin for Play2 framework
https://github.com/Furyu/play-velocity-plugin
が、Playのプラグインになっているし、いざ書いてみるともうちょっといろいろ書いてみたくなって結果こんな感じになりました。個人的にはFreemarkerよりもVelocityの方が見通しやすいです。