Skip to content

Instantly share code, notes, and snippets.

@kxbmap
Created March 20, 2011 19:28
Show Gist options
  • Save kxbmap/878580 to your computer and use it in GitHub Desktop.
Save kxbmap/878580 to your computer and use it in GitHub Desktop.
ポリモーフィズムで再帰的なXMLを生成する
package com.example.kvxml2
import _root_.scala.xml.{Elem, MetaData, Node, NodeSeq, Null, Text, TopScope, UnprefixedAttribute}
sealed abstract class Value {
def nodes: NodeSeq
}
case class StringValue(str: String) extends Value {
def nodes = Text(str)
}
case class ValueSeq(seq: Seq[Value]) extends Value {
def nodes = seq flatMap (_.nodes)
}
case class KeyValue(key: String, attributes: Map[String, String], value: Value) extends Value {
def this(key: String, value: Value) = this(key, Map.empty, value)
def xml: Node = Elem(null, key, meta, TopScope, value.nodes: _*)
def meta = ((Null: MetaData) /: attributes){ (meta, attr) =>
new UnprefixedAttribute(attr._1, attr._2, meta)
}
def nodes = xml
}
package com.example.kvxml2
import org.specs2._
import scala.xml.PrettyPrinter
class KeyValueSpec extends Specification { def is =
"ポリモーフィズム版KeyValueのテスト" ^
"XMLリテラルと一致する" ! S.example1 ^
"PrettyPrinterで生成したStringが一致する" ! S.example2 ^
"改行とインデント込みでXMLリテラルに一致する" ! S.example3 ^
end
object S {
implicit def string2value(str: String): Value = StringValue(str)
implicit def seq2value(seq: Seq[Value]): Value = ValueSeq(seq)
val kv =
KeyValue("langs", Map("type" -> "current"), Seq(
new KeyValue("key1", "value1"),
new KeyValue("key2", "value2"),
new KeyValue("key3", Seq(
new KeyValue("key3-1", "value3-1"),
new KeyValue("key3-2", "value3-2")
))
))
def example1 = kv.xml must_==
<langs type="current"><key1>value1</key1><key2>value2</key2><key3><key3-1>value3-1</key3-1><key3-2>value3-2</key3-2></key3></langs>
def example2 = {
val expect = """<langs type="current">
| <key1>value1</key1>
| <key2>value2</key2>
| <key3>
| <key3-1>value3-1</key3-1>
| <key3-2>value3-2</key3-2>
| </key3>
|</langs>""".stripMargin
new PrettyPrinter(80, 2).format(kv.xml) must_== expect
}
val kv2 = {
val nl = "\n"
val indent = " "
KeyValue("langs", Map("type" -> "current"), Seq[Value](
nl + indent,
new KeyValue("key1", "value1"),
nl + indent,
new KeyValue("key2", "value2"),
nl + indent,
new KeyValue("key3", Seq[Value](
nl + indent * 2,
new KeyValue("key3-1", "value3-1"),
nl + indent * 2,
new KeyValue("key3-2", "value3-2"),
nl + indent
)),
nl
))
}
def example3 = kv2.xml must_==
<langs type="current">
<key1>value1</key1>
<key2>value2</key2>
<key3>
<key3-1>value3-1</key3-1>
<key3-2>value3-2</key3-2>
</key3>
</langs>
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment