Skip to content

Instantly share code, notes, and snippets.

@kxbmap
Created March 24, 2011 09:33
Show Gist options
  • Save kxbmap/884797 to your computer and use it in GitHub Desktop.
Save kxbmap/884797 to your computer and use it in GitHub Desktop.
LiftでMongoDBにEnumeration#ValueをキーにしたMapを格納する net.liftweb.mongodb.Metaがprivate[mongodb]なのでLiftのパッケージ。。
object RoboPartsType extends Enumeration {
val BD = Value("BD")
val HD = Value("HD")
val BS = Value("BS")
val AM = Value("AM")
val LG = Value("LG")
}
class RoboParts extends MongoRecord[RoboParts] with MongoId[RoboParts] {
def meta = RoboParts
object name extends StringField(this, 32)
object partsType extends EnumNameField(this, RoboPartsType)
object joints extends MongoEnumNameMapField[RoboParts, RoboPartsType.type, Int](this, RoboPartsType)
}
object RoboParts extends RoboParts with MongoMetaRecord[RoboParts]
def test() {
import RoboPartsType._
RoboParts.createRecord
.name("test")
.partsType(BD)
.joints(Map(
HD -> 1, BS -> 1, AM -> 2, LG -> 1
))
.save
RoboParts where (_.name eqs "test") fetch(1) foreach { p =>
println(p)
println(p.joints.is(AM))
}
}
package net.liftweb.mongodb.record.field
import _root_.net.liftweb.common.{Failure, Empty, Box, Full}
import _root_.net.liftweb.json.JsonAST.{JValue, JObject, JField, JNothing, JNull}
import _root_.net.liftweb.json.JsonParser
import _root_.net.liftweb.record.{Field, MandatoryTypedField, FieldHelpers}
import _root_.net.liftweb.mongodb.record.MongoRecord
import _root_.net.liftweb.util.Helpers.tryo
import _root_.com.mongodb.{BasicDBObject, DBObject}
class MongoEnumNameMapField[OwnerType <: MongoRecord[OwnerType], EnumType <: Enumeration, MapValueType](rec: OwnerType, enum: EnumType)
extends Field[Map[EnumType#Value, MapValueType], OwnerType]
with MandatoryTypedField[Map[EnumType#Value, MapValueType]]
with MongoFieldFlavor[Map[EnumType#Value, MapValueType]] {
import _root_.net.liftweb.mongodb.Meta.Reflection._
def owner = rec
def defaultValue = Map[EnumType#Value, MapValueType]()
def setFromAny(in: Any): Box[Map[EnumType#Value, MapValueType]] = in match {
case dbo: DBObject => setFromDBObject(dbo)
case map: Map[EnumType#Value, MapValueType] => setBox(Full(map))
case Some(map: Map[EnumType#Value, MapValueType]) => setBox(Full(map))
case Full(map: Map[EnumType#Value, MapValueType]) => setBox(Full(map))
case (map: Map[EnumType#Value, MapValueType]) :: _ => setBox(Full(map))
case s: String => setFromString(s)
case Some(s: String) => setFromString(s)
case Full(s: String) => setFromString(s)
case null | None | Empty => setBox(defaultValueBox)
case f: Failure => setBox(f)
case o => setFromString(o.toString)
}
def setFromJValue(jvalue: JValue): Box[Map[EnumType#Value, MapValueType]] = jvalue match {
case JNothing | JNull if optional_? => setBox(Empty)
case JObject(obj) => setBox(Full(
Map() ++ obj.collect {
case jf if enum.values.exists(_.toString == jf.name) =>
(enum.values.find(_.toString == jf.name).get, jf.value.values.asInstanceOf[MapValueType])
}
))
case other => setBox(FieldHelpers.expectedA("JObject", other))
}
def setFromString(in: String): Box[Map[EnumType#Value, MapValueType]] = tryo(JsonParser.parse(in)) match {
case Full(jv: JValue) => setFromJValue(jv)
case f: Failure => setBox(f)
case other => setBox(Failure("Error parsing String into a JValue: "+in))
}
def toForm = Empty // FIXME
def asJValue = JObject(value.keys.map {
k =>
JField(k.toString, value(k).asInstanceOf[AnyRef] match {
case x if primitive_?(x.getClass) => primitive2jvalue(x)
case x if mongotype_?(x.getClass) => mongotype2jvalue(x)(owner.meta.formats)
case x if datetype_?(x.getClass) => datetype2jvalue(x)(owner.meta.formats)
case _ => JNothing
})
}.toList)
/*
* Convert this field's value into a DBObject so it can be stored in Mongo.
*/
def asDBObject: DBObject = {
val dbo = new BasicDBObject
value.keys.foreach { k =>
dbo.put(k.toString, value.getOrElse(k, ""))
}
dbo
}
// set this field's value using a DBObject returned from Mongo.
def setFromDBObject(dbo: DBObject): Box[Map[EnumType#Value, MapValueType]] = {
import scala.collection.JavaConversions._
setBox(Full(
Map() ++ dbo.keySet.collect {
case k if enum.values.exists(_.toString == k) =>
(enum.values.find(_.toString == k).get, dbo.get(k).asInstanceOf[MapValueType])
}
))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment