Skip to content

Commit

Permalink
Change mongodb.fields' type param to BsonRecord
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Nelson committed Apr 20, 2011
1 parent d7daee7 commit cad135a
Show file tree
Hide file tree
Showing 13 changed files with 219 additions and 42 deletions.
Expand Up @@ -31,7 +31,7 @@ import com.mongodb._
import scala.xml._ import scala.xml._


/** Field that contains an entire record represented as an inline object value. Inspired by JSONSubRecordField */ /** Field that contains an entire record represented as an inline object value. Inspired by JSONSubRecordField */
class BsonRecordField[OwnerType <: MongoRecord[OwnerType], SubRecordType <: BsonRecord[SubRecordType]] class BsonRecordField[OwnerType <: BsonRecord[OwnerType], SubRecordType <: BsonRecord[SubRecordType]]
(rec: OwnerType, valueMeta: BsonMetaRecord[SubRecordType])(implicit subRecordType: Manifest[SubRecordType]) (rec: OwnerType, valueMeta: BsonMetaRecord[SubRecordType])(implicit subRecordType: Manifest[SubRecordType])
extends Field[SubRecordType, OwnerType] extends Field[SubRecordType, OwnerType]
with MandatoryTypedField[SubRecordType] with MandatoryTypedField[SubRecordType]
Expand Down Expand Up @@ -75,7 +75,7 @@ class BsonRecordField[OwnerType <: MongoRecord[OwnerType], SubRecordType <: Bson
/* /*
* List of BsonRecords * List of BsonRecords
*/ */
class BsonRecordListField[OwnerType <: MongoRecord[OwnerType], SubRecordType <: BsonRecord[SubRecordType]] class BsonRecordListField[OwnerType <: BsonRecord[OwnerType], SubRecordType <: BsonRecord[SubRecordType]]
(rec: OwnerType, valueMeta: BsonMetaRecord[SubRecordType]) (rec: OwnerType, valueMeta: BsonMetaRecord[SubRecordType])
extends MongoListField[OwnerType, SubRecordType](rec: OwnerType) { extends MongoListField[OwnerType, SubRecordType](rec: OwnerType) {


Expand Down
Expand Up @@ -32,7 +32,7 @@ import org.bson.types.ObjectId
/* /*
* Field for storing a DBRef * Field for storing a DBRef
*/ */
class DBRefField[OwnerType <: MongoRecord[OwnerType], RefType <: MongoRecord[RefType]](rec: OwnerType, ref: RefType) class DBRefField[OwnerType <: BsonRecord[OwnerType], RefType <: MongoRecord[RefType]](rec: OwnerType, ref: RefType)
extends Field[DBRef, OwnerType] with MandatoryTypedField[DBRef] { extends Field[DBRef, OwnerType] with MandatoryTypedField[DBRef] {


/* /*
Expand Down
Expand Up @@ -32,7 +32,7 @@ import net.liftweb.util.Helpers._
/* /*
* Since MongoDB only stores UTC dates, Calendar data is not necessary. * Since MongoDB only stores UTC dates, Calendar data is not necessary.
*/ */
class DateField[OwnerType <: MongoRecord[OwnerType]](rec: OwnerType) class DateField[OwnerType <: BsonRecord[OwnerType]](rec: OwnerType)
extends Field[Date, OwnerType] extends Field[Date, OwnerType]
with MandatoryTypedField[Date] with MandatoryTypedField[Date]
{ {
Expand Down
Expand Up @@ -28,7 +28,7 @@ import net.liftweb.util.Helpers.tryo


import com.mongodb.DBObject import com.mongodb.DBObject


abstract class JsonObjectField[OwnerType <: MongoRecord[OwnerType], JObjectType <: JsonObject[JObjectType]] abstract class JsonObjectField[OwnerType <: BsonRecord[OwnerType], JObjectType <: JsonObject[JObjectType]]
(rec: OwnerType, valueMeta: JsonObjectMeta[JObjectType]) (rec: OwnerType, valueMeta: JsonObjectMeta[JObjectType])
extends Field[JObjectType, OwnerType] with MandatoryTypedField[JObjectType] with MongoFieldFlavor[JObjectType] { extends Field[JObjectType, OwnerType] with MandatoryTypedField[JObjectType] with MongoFieldFlavor[JObjectType] {


Expand Down
Expand Up @@ -37,7 +37,7 @@ import org.bson.types.ObjectId
* List field. Compatible with most object types, * List field. Compatible with most object types,
* including Pattern, ObjectId, Date, and UUID. * including Pattern, ObjectId, Date, and UUID.
*/ */
class MongoListField[OwnerType <: MongoRecord[OwnerType], ListType](rec: OwnerType) class MongoListField[OwnerType <: BsonRecord[OwnerType], ListType](rec: OwnerType)
extends Field[List[ListType], OwnerType] extends Field[List[ListType], OwnerType]
with MandatoryTypedField[List[ListType]] with MandatoryTypedField[List[ListType]]
with MongoFieldFlavor[List[ListType]] with MongoFieldFlavor[List[ListType]]
Expand Down Expand Up @@ -112,14 +112,14 @@ class MongoListField[OwnerType <: MongoRecord[OwnerType], ListType](rec: OwnerTy
* List of Dates. Use MongListField[OwnerType, Date] instead. * List of Dates. Use MongListField[OwnerType, Date] instead.
*/ */
@deprecated("Use MongListField[OwnerType, Date] instead") @deprecated("Use MongListField[OwnerType, Date] instead")
class MongoDateListField[OwnerType <: MongoRecord[OwnerType]](rec: OwnerType) class MongoDateListField[OwnerType <: BsonRecord[OwnerType]](rec: OwnerType)
extends MongoListField[OwnerType, Date](rec: OwnerType) { extends MongoListField[OwnerType, Date](rec: OwnerType) {
} }


/* /*
* List of JsonObject case classes * List of JsonObject case classes
*/ */
class MongoJsonObjectListField[OwnerType <: MongoRecord[OwnerType], JObjectType <: JsonObject[JObjectType]] class MongoJsonObjectListField[OwnerType <: BsonRecord[OwnerType], JObjectType <: JsonObject[JObjectType]]
(rec: OwnerType, valueMeta: JsonObjectMeta[JObjectType]) (rec: OwnerType, valueMeta: JsonObjectMeta[JObjectType])
extends MongoListField[OwnerType, JObjectType](rec: OwnerType) { extends MongoListField[OwnerType, JObjectType](rec: OwnerType) {


Expand Down
Expand Up @@ -30,7 +30,7 @@ import net.liftweb.util.Helpers.tryo


import com.mongodb._ import com.mongodb._


class MongoMapField[OwnerType <: MongoRecord[OwnerType], MapValueType](rec: OwnerType) class MongoMapField[OwnerType <: BsonRecord[OwnerType], MapValueType](rec: OwnerType)
extends Field[Map[String, MapValueType], OwnerType] with MandatoryTypedField[Map[String, MapValueType]] extends Field[Map[String, MapValueType], OwnerType] with MandatoryTypedField[Map[String, MapValueType]]
with MongoFieldFlavor[Map[String, MapValueType]] { with MongoFieldFlavor[Map[String, MapValueType]] {


Expand Down
Expand Up @@ -43,7 +43,7 @@ object MongoPasswordField {
def encrypt(s: String, salt: String) = hash("{"+s+"} salt={" + salt + "}") def encrypt(s: String, salt: String) = hash("{"+s+"} salt={" + salt + "}")
} }


class MongoPasswordField[OwnerType <: MongoRecord[OwnerType]](rec: OwnerType, minLen: Int) extends JsonObjectField[OwnerType, Password](rec, Password) { class MongoPasswordField[OwnerType <: BsonRecord[OwnerType]](rec: OwnerType, minLen: Int) extends JsonObjectField[OwnerType, Password](rec, Password) {


def this(rec: OwnerType) = { def this(rec: OwnerType) = {
this(rec, 3) this(rec, 3)
Expand Down
Expand Up @@ -34,7 +34,7 @@ import org.bson.types.ObjectId
/* /*
* Field for storing an ObjectId * Field for storing an ObjectId
*/ */
class ObjectIdField[OwnerType <: MongoRecord[OwnerType]](rec: OwnerType) class ObjectIdField[OwnerType <: BsonRecord[OwnerType]](rec: OwnerType)
extends Field[ObjectId, OwnerType] extends Field[ObjectId, OwnerType]
with MandatoryTypedField[ObjectId] with MandatoryTypedField[ObjectId]
{ {
Expand Down
Expand Up @@ -26,7 +26,7 @@ import net.liftweb.mongodb.record._
import net.liftweb.record.{Field, FieldHelpers, MandatoryTypedField} import net.liftweb.record.{Field, FieldHelpers, MandatoryTypedField}
import net.liftweb.util.Helpers.tryo import net.liftweb.util.Helpers.tryo


class PatternField[OwnerType <: MongoRecord[OwnerType]](rec: OwnerType) class PatternField[OwnerType <: BsonRecord[OwnerType]](rec: OwnerType)
extends Field[Pattern, OwnerType] extends Field[Pattern, OwnerType]
with MandatoryTypedField[Pattern] with MandatoryTypedField[Pattern]
{ {
Expand Down
Expand Up @@ -29,7 +29,7 @@ import net.liftweb.mongodb.record._
import net.liftweb.record.{Field, FieldHelpers, MandatoryTypedField} import net.liftweb.record.{Field, FieldHelpers, MandatoryTypedField}
import net.liftweb.util.Helpers._ import net.liftweb.util.Helpers._


class UUIDField[OwnerType <: MongoRecord[OwnerType]](rec: OwnerType) class UUIDField[OwnerType <: BsonRecord[OwnerType]](rec: OwnerType)
extends Field[UUID, OwnerType] extends Field[UUID, OwnerType]
with MandatoryTypedField[UUID] with MandatoryTypedField[UUID]
{ {
Expand Down
Expand Up @@ -298,17 +298,39 @@ class SubRecord extends BsonRecord[SubRecord] {
def meta = SubRecord def meta = SubRecord


object name extends StringField(this, 12) object name extends StringField(this, 12)
object subsub extends BsonRecordField(this, SubSubRecord)
object subsublist extends BsonRecordListField(this, SubSubRecord)
object when extends DateField(this)
object slist extends MongoListField[SubRecord, String](this)
object smap extends MongoMapField[SubRecord, String](this)
object oid extends ObjectIdField(this)
object pattern extends PatternField(this)
object uuid extends UUIDField(this)


override def equals(other: Any): Boolean = other match { override def equals(other: Any): Boolean = other match {
case that:SubRecord => case that:SubRecord => this.toString == that.toString
this.name.value == that.name.value
case _ => false case _ => false
} }
} }
object SubRecord extends SubRecord with BsonMetaRecord[SubRecord] { object SubRecord extends SubRecord with BsonMetaRecord[SubRecord] {
override def formats = allFormats override def formats = allFormats
} }


class SubSubRecord extends BsonRecord[SubSubRecord] {
def meta = SubSubRecord

object name extends StringField(this, 12)

override def equals(other: Any): Boolean = other match {
case that:SubSubRecord =>
this.name.value == that.name.value
case _ => false
}
}
object SubSubRecord extends SubSubRecord with BsonMetaRecord[SubSubRecord] {
override def formats = allFormats
}

class SubRecordTestRecord extends MongoRecord[SubRecordTestRecord] with MongoId[SubRecordTestRecord] { class SubRecordTestRecord extends MongoRecord[SubRecordTestRecord] with MongoId[SubRecordTestRecord] {
def meta = SubRecordTestRecord def meta = SubRecordTestRecord


Expand All @@ -323,12 +345,7 @@ class SubRecordTestRecord extends MongoRecord[SubRecordTestRecord] with MongoId[
} }


override def equals(other: Any): Boolean = other match { override def equals(other: Any): Boolean = other match {
case that:SubRecordTestRecord => case that:SubRecordTestRecord => this.toString == that.toString
this.id == that.id &&
this.mandatoryBsonRecordField.value == that.mandatoryBsonRecordField.value &&
this.legacyOptionalBsonRecordField.valueBox == that.legacyOptionalBsonRecordField.valueBox &&
this.mandatoryBsonRecordListField.value == that.mandatoryBsonRecordListField.value &&
this.legacyOptionalBsonRecordListField.valueBox == that.legacyOptionalBsonRecordListField.valueBox
case _ => false case _ => false
} }


Expand Down
Expand Up @@ -28,7 +28,7 @@ import org.bson.types.ObjectId
import org.specs.Specification import org.specs.Specification


import common._ import common._
import json.JsonAST._ import json.{Num => JsonNum, _}
import util.FieldError import util.FieldError
import util.Helpers.randomString import util.Helpers.randomString
import http.{LiftSession, S} import http.{LiftSession, S}
Expand All @@ -43,14 +43,12 @@ import net.liftweb.record._
object MongoFieldSpec extends Specification("MongoField Specification") with MongoTestKit { object MongoFieldSpec extends Specification("MongoField Specification") with MongoTestKit {
import fixtures._ import fixtures._


def passBasicTests[A](example: A, mandatory: MandatoryTypedField[A], legacyOptional: MandatoryTypedField[A])(implicit m: scala.reflect.Manifest[A]): Unit = { def passBasicTests[A](

example: A,
val canCheckDefaultValues = mandatory: MandatoryTypedField[A],
!mandatory.defaultValue.isInstanceOf[Date] && // don't try to use the default value of date/time typed fields, because it changes from moment to moment! legacyOptional: MandatoryTypedField[A],
!mandatory.defaultValue.isInstanceOf[ObjectId] && // same with ObjectId canCheckDefaultValues: Boolean = true
!mandatory.defaultValue.isInstanceOf[Pattern] && )(implicit m: scala.reflect.Manifest[A]): Unit = {
!mandatory.defaultValue.isInstanceOf[UUID] &&
!mandatory.defaultValue.isInstanceOf[DBRef]


def commonBehaviorsForAllFlavors(field: MandatoryTypedField[A]) = { def commonBehaviorsForAllFlavors(field: MandatoryTypedField[A]) = {


Expand Down Expand Up @@ -180,7 +178,7 @@ object MongoFieldSpec extends Specification("MongoField Specification") with Mon
val rec = MongoFieldTypeTestRecord.createRecord val rec = MongoFieldTypeTestRecord.createRecord
val now = new Date val now = new Date
val nowStr = rec.meta.formats.dateFormat.format(now) val nowStr = rec.meta.formats.dateFormat.format(now)
passBasicTests(now, rec.mandatoryDateField, rec.legacyOptionalDateField) passBasicTests(now, rec.mandatoryDateField, rec.legacyOptionalDateField, false)
passConversionTests( passConversionTests(
now, now,
rec.mandatoryDateField, rec.mandatoryDateField,
Expand All @@ -196,7 +194,7 @@ object MongoFieldSpec extends Specification("MongoField Specification") with Mon
if (isMongoRunning) { // Even if this gets skipped, the vals still get set. if (isMongoRunning) { // Even if this gets skipped, the vals still get set.
val rec = MongoFieldTypeTestRecord.createRecord val rec = MongoFieldTypeTestRecord.createRecord
val dbref = DBRefTestRecord.createRecord.getRef // This makes a call to MongoDB.use and needs a MongoDB connection. val dbref = DBRefTestRecord.createRecord.getRef // This makes a call to MongoDB.use and needs a MongoDB connection.
passBasicTests(dbref, rec.mandatoryDBRefField, rec.legacyOptionalDBRefField) passBasicTests(dbref, rec.mandatoryDBRefField, rec.legacyOptionalDBRefField, false)
} }
} }


Expand All @@ -216,7 +214,7 @@ object MongoFieldSpec extends Specification("MongoField Specification") with Mon
"ObjectIdField" should { "ObjectIdField" should {
val rec = MongoFieldTypeTestRecord.createRecord val rec = MongoFieldTypeTestRecord.createRecord
val oid = ObjectId.get val oid = ObjectId.get
passBasicTests(oid, rec.mandatoryObjectIdField, rec.legacyOptionalObjectIdField) passBasicTests(oid, rec.mandatoryObjectIdField, rec.legacyOptionalObjectIdField, false)
passConversionTests( passConversionTests(
oid, oid,
rec.mandatoryObjectIdField, rec.mandatoryObjectIdField,
Expand All @@ -229,7 +227,7 @@ object MongoFieldSpec extends Specification("MongoField Specification") with Mon
"PatternField" should { "PatternField" should {
val rec = MongoFieldTypeTestRecord.createRecord val rec = MongoFieldTypeTestRecord.createRecord
val ptrn = Pattern.compile("^Mo", Pattern.CASE_INSENSITIVE) val ptrn = Pattern.compile("^Mo", Pattern.CASE_INSENSITIVE)
passBasicTests(ptrn, rec.mandatoryPatternField, rec.legacyOptionalPatternField) passBasicTests(ptrn, rec.mandatoryPatternField, rec.legacyOptionalPatternField, false)
passConversionTests( passConversionTests(
ptrn, ptrn,
rec.mandatoryPatternField, rec.mandatoryPatternField,
Expand All @@ -242,7 +240,7 @@ object MongoFieldSpec extends Specification("MongoField Specification") with Mon
"UUIDField" should { "UUIDField" should {
val rec = MongoFieldTypeTestRecord.createRecord val rec = MongoFieldTypeTestRecord.createRecord
val uuid = UUID.randomUUID val uuid = UUID.randomUUID
passBasicTests(uuid, rec.mandatoryUUIDField, rec.legacyOptionalUUIDField) passBasicTests(uuid, rec.mandatoryUUIDField, rec.legacyOptionalUUIDField, false)
passConversionTests( passConversionTests(
uuid, uuid,
rec.mandatoryUUIDField, rec.mandatoryUUIDField,
Expand Down Expand Up @@ -369,5 +367,105 @@ object MongoFieldSpec extends Specification("MongoField Specification") with Mon
) )
} }
} }

"BsonRecordField" should {
"function correctly" in {
val rec = SubRecordTestRecord.createRecord
val subRec = SubRecord.createRecord.name("subrecord")

val srJson =
JObject(List(
JField("name", JString("subrecord")),
JField("subsub", JObject(List(
JField("name", JString(""))
))),
JField("subsublist", JArray(List())),
JField("when", JObject(List(
JField("$dt", JString(rec.meta.formats.dateFormat.format(subRec.when.value)))
))),
JField("slist", JArray(List())),
JField("smap", JObject(List())),
JField("oid", JObject(List(JField("$oid", JString(subRec.oid.value.toString))))),
JField("pattern", JObject(List(
JField("$regex", JString(subRec.pattern.value.pattern)),
JField("$flags", JInt(subRec.pattern.value.flags))
))),
JField("uuid", JObject(List(JField("$uuid", JString(subRec.uuid.value.toString)))))
))

val srJsExp = new JsExp {
def toJsCmd = Printer.compact(render(srJson))
}

passBasicTests(subRec, rec.mandatoryBsonRecordField, rec.legacyOptionalBsonRecordField, false)
passConversionTests(
subRec,
rec.mandatoryBsonRecordField,
srJsExp,
srJson,
Empty
)
}
}

"BsonRecordListField" should {
"function correctly" in {
val rec = SubRecordTestRecord.createRecord
val lst = List(SubRecord.createRecord.name("subrec1"), SubRecord.createRecord.name("subrec2"))
val sr1Json =
JObject(List(
JField("name", JString("subrec1")),
JField("subsub", JObject(List(
JField("name", JString(""))
))),
JField("subsublist", JArray(List())),
JField("when", JObject(List(
JField("$dt", JString(rec.meta.formats.dateFormat.format(lst(0).when.value)))
))),
JField("slist", JArray(List())),
JField("smap", JObject(List())),
JField("oid", JObject(List(JField("$oid", JString(lst(0).oid.value.toString))))),
JField("pattern", JObject(List(
JField("$regex", JString(lst(0).pattern.value.pattern)),
JField("$flags", JInt(lst(0).pattern.value.flags))
))),
JField("uuid", JObject(List(JField("$uuid", JString(lst(0).uuid.value.toString)))))
))
val sr2Json =
JObject(List(
JField("name", JString("subrec2")),
JField("subsub", JObject(List(
JField("name", JString(""))
))),
JField("subsublist", JArray(List())),
JField("when", JObject(List(
JField("$dt", JString(rec.meta.formats.dateFormat.format(lst(1).when.value)))
))),
JField("slist", JArray(List())),
JField("smap", JObject(List())),
JField("oid", JObject(List(JField("$oid", JString(lst(1).oid.value.toString))))),
JField("pattern", JObject(List(
JField("$regex", JString(lst(1).pattern.value.pattern)),
JField("$flags", JInt(lst(1).pattern.value.flags))
))),
JField("uuid", JObject(List(JField("$uuid", JString(lst(1).uuid.value.toString)))))
))
val sr1JsExp = new JsExp {
def toJsCmd = compact(render(sr1Json))
}
val sr2JsExp = new JsExp {
def toJsCmd = compact(render(sr2Json))
}

passBasicTests(lst, rec.mandatoryBsonRecordListField, rec.legacyOptionalBsonRecordListField)
passConversionTests(
lst,
rec.mandatoryBsonRecordListField,
JsArray(sr1JsExp, sr2JsExp),
JArray(List(sr1Json, sr2Json)),
Empty
)
}
}
} }


0 comments on commit cad135a

Please sign in to comment.