Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of https://github.com/mongodb/casbah

  • Loading branch information...
commit 5d0d43095a989e90a43c607df4ebf5aee89e662f 2 parents 1fdc0d9 + e5b44eb
@teigen teigen authored
Showing with 585 additions and 262 deletions.
  1. +20 −0 casbah-commons/src/main/scala/MongoDBObject.scala
  2. +6 −3 casbah-commons/src/main/scala/test/MongoDBSpecification.scala
  3. +2 −2 casbah-commons/src/test/scala/MongoDBListSpec.scala
  4. +23 −2 casbah-commons/src/test/scala/MongoDBObjectSpec.scala
  5. +6 −0 casbah-core/src/main/scala/Implicits.scala
  6. +33 −15 casbah-core/src/main/scala/MongoURI.scala
  7. +2 −2 casbah-core/src/test/scala/ConversionsSpec.scala
  8. +2 −2 casbah-core/src/test/scala/CoreWrappersSpec.scala
  9. +2 −2 casbah-core/src/test/scala/GroupSpec.scala
  10. +3 −3 casbah-core/src/test/scala/LazyDecodingSpec.scala
  11. +2 −2 casbah-core/src/test/scala/MapReduceSpec.scala
  12. +2 −2 casbah-core/src/test/scala/RawMapReduceSpec.scala
  13. +2 −2 casbah-gridfs/src/test/scala/GridFSSpec.scala
  14. +167 −132 casbah-query/src/main/scala/BarewordOperators.scala
  15. +2 −2 casbah-query/src/main/scala/CoreOperators.scala
  16. +14 −10 casbah-query/src/main/scala/Implicits.scala
  17. +63 −20 casbah-query/src/test/scala/BarewordOperatorsSpec.scala
  18. +4 −3 casbah-query/src/test/scala/DSLCoreOperatorsSpec.scala
  19. +56 −46 casbah-util/src/main/scala/bson/{ → primitive}/BSONPrimitive.scala
  20. +1 −1  casbah-util/src/main/scala/bson/{ → primitive}/BSONType.scala
  21. +154 −0 casbah-util/src/main/scala/bson/primitive/Builtins.scala
  22. +15 −6 project/CasbahBuild.scala
  23. +1 −1  project/build.properties
  24. +3 −4 tutorial_src/source/tutorial.rst
View
20 casbah-commons/src/main/scala/MongoDBObject.scala
@@ -91,6 +91,26 @@ class MongoDBObject(val underlying: DBObject = new BasicDBObject) extends scala.
super.++(other: DBObject)
}
+ /**
+ * Returns a new list with this MongoDBObject at the *end*
+ * Currently only supports composing with other DBObjects, primarily for
+ * the use of the Query DSL; if you want heterogenous lists, use
+ * MongoDBList directly.
+ * @see MongoDBList
+ *
+ */
+ def ::[A <% DBObject](elem: A): Seq[DBObject] = Seq(elem: DBObject, this)
+
+ /**
+ * Returns a new list with this MongoDBObject at the *end*
+ * Currently only supports composing with other DBObjects, primarily for
+ * the use of the Query DSL; if you want heterogenous lists, use
+ * MongoDBList directly.
+ * @see MongoDBList
+ *
+ */
+ def ::(elem: (String, Any)): Seq[DBObject] = Seq(MongoDBObject(elem), this)
+
/** Lazy utility method to allow typing without conflicting with Map's required get() method and causing ambiguity */
def getAs[A <: Any: Manifest](key: String): Option[A] = {
require(manifest[A] != manifest[scala.Nothing],
View
9 casbah-commons/src/main/scala/test/MongoDBSpecification.scala
@@ -18,19 +18,22 @@
package com.mongodb.casbah.commons
package test
-import org.specs2.mutable._
+import org.specs2._
import org.specs2.data.Sized
import org.specs2.matcher.{ Expectable, Matcher, MapMatchers }
import org.specs2.matcher.Matchers._
import com.mongodb.casbah.util.Logging
import com.mongodb.casbah.commons.MongoDBObject
-import javax.management.remote.rmi._RMIConnection_Stub
object `package` {
}
-trait CasbahSpecification extends Specification with DBObjectMatchers with Logging {
+trait CasbahMutableSpecification extends mutable.Specification with CasbahSpecificationBase
+
+trait CasbahSpecification extends Specification with CasbahSpecificationBase
+
+trait CasbahSpecificationBase extends DBObjectMatchers with Logging {
implicit val sizedOptDBObj = new Sized[Option[DBObject]] {
def size(t: Option[DBObject]) = t.getOrElse(MongoDBObject.empty).size
}
View
4 casbah-commons/src/test/scala/MongoDBListSpec.scala
@@ -23,9 +23,9 @@
package com.mongodb.casbah.test.commons
import com.mongodb.casbah.commons._
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
-class MongoDBListSpec extends CasbahSpecification {
+class MongoDBListSpec extends CasbahMutableSpecification {
val x = Seq(5, 9, 212, "x", "y", 22.98)
val y = Seq("spam", "eggs", "foo", "bar")
View
25 casbah-commons/src/test/scala/MongoDBObjectSpec.scala
@@ -23,9 +23,9 @@
package com.mongodb.casbah.test.commons
import com.mongodb.casbah.commons._
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
-class MongoDBObjectSpec extends CasbahSpecification {
+class MongoDBObjectSpec extends CasbahMutableSpecification {
"MongoDBObject expand operations" should {
@@ -249,6 +249,27 @@ class MongoDBObjectSpec extends CasbahSpecification {
explicit.hashCode must beEqualTo(control.hashCode())
explicit.equals(explicit) must beEqualTo(control.equals(control))
}
+
+ "Support list creation operators" in {
+ "Prepend to end of a new list" in {
+ "With explicitly created Elements" in {
+ val list = MongoDBObject("x" -> "y") :: MongoDBObject("foo" -> "bar")
+ list must haveSize(2)
+ list(0) must beDBObject
+ (list(0): DBObject) must haveEntries("x" -> "y")
+ list(1) must beDBObject
+ (list(1): DBObject) must haveEntries("foo" -> "bar")
+ }
+ "With implicitly created Elements with an explicit" in {
+ val list = ("x" -> "y") :: MongoDBObject("foo" -> "bar")
+ list must haveSize(2)
+ list(0) must beDBObject
+ (list(0): DBObject) must haveEntries("x" -> "y")
+ list(1) must beDBObject
+ (list(1): DBObject) must haveEntries("foo" -> "bar")
+ }
+ }
+ }
}
}
View
6 casbah-core/src/main/scala/Implicits.scala
@@ -117,6 +117,12 @@ object Imports extends Imports with commons.Imports with commons.Exports with qu
trait Imports extends BaseImports with TypeImports with Implicits
package core {
+ /**
+ * You can import core to get "just" Casbah core; no commons, query, etc.
+ * This is useful to pick which QueryDSL type you want, etc.
+ */
+ object `package` extends Imports
+
trait Exports {
type MongoCursor = com.mongodb.casbah.MongoCursor
type MongoCollection = com.mongodb.casbah.MongoCollection
View
48 casbah-core/src/main/scala/MongoURI.scala
@@ -44,7 +44,7 @@ object MongoURI {
*
* @param uri (String)
*/
- def apply(uri: String) = new MongoURI(new com.mongodb.MongoURI(uri))
+ def apply(uri: String): MongoURI = new MongoURI(new com.mongodb.MongoURI(uri))
}
/**
@@ -60,20 +60,38 @@ object MongoURI {
* @since 2.0
*/
class MongoURI(val underlying: com.mongodb.MongoURI) {
- def username = underlying.getUsername
- def password = underlying.getPassword
- def hosts = underlying.getHosts.asScala
- def database = underlying.getDatabase
- def collection = underlying.getCollection
- def options = underlying.getOptions
- def connect = underlying.connect.asScala
- def connectDB = underlying.connectDB.asScala
- def connectDB(m: MongoConnection) =
- underlying.connectDB(m.underlying).asScala
- def connectCollection(db: MongoDB) =
- underlying.connectCollection(db.underlying).asScala
- def connectCollection(m: MongoConnection) =
- underlying.connectCollection(m.underlying).asScala
+ def username: Option[String] = Option(underlying.getUsername)
+ def password: Option[Array[Char]] = Option(underlying.getPassword)
+ def hosts: Seq[String] = underlying.getHosts.asScala
+ def database: Option[String] = Option(underlying.getDatabase)
+ def collection: Option[String] = Option(underlying.getCollection)
+ def options: MongoOptions = underlying.getOptions
+ def connect: Either[Throwable, MongoConnection] = try {
+ Right(underlying.connect.asScala)
+ } catch {
+ case t => Left(t)
+ }
+ def connectDB: Either[Throwable, MongoDB] = {
+ try {
+ require(database.isDefined, "Cannot connect to Database as none is defined.")
+ Right(underlying.connectDB.asScala)
+ } catch {
+ case t => Left(t)
+ }
+ }
+ def connectCollection: Either[Throwable, MongoCollection] = {
+ try {
+ require(collection.isDefined, "Cannot connect to Collection as none is defined.")
+ connectDB match {
+ case Right(db) =>
+ Right(db(collection.get))
+ case Left(t) => Left(t)
+ }
+ } catch {
+ case t => Left(t)
+ }
+
+ }
override def toString = underlying.toString
}
View
4 casbah-core/src/test/scala/ConversionsSpec.scala
@@ -27,11 +27,11 @@ import com.mongodb.casbah.commons.conversions.scala._
import com.mongodb.casbah._
import org.scala_tools.time.Imports._
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
import org.specs2.specification.BeforeExample
import org.bson.BSON
-class ConversionsSpec extends CasbahSpecification with BeforeExample {
+class ConversionsSpec extends CasbahMutableSpecification with BeforeExample {
type JDKDate = java.util.Date
View
4 casbah-core/src/test/scala/CoreWrappersSpec.scala
@@ -24,9 +24,9 @@ package com.mongodb.casbah
import com.mongodb.casbah._
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
-class CoreWrappersSpec extends CasbahSpecification {
+class CoreWrappersSpec extends CasbahMutableSpecification {
"Casbah behavior between Scala and Java versions of Objects" should {
View
4 casbah-core/src/test/scala/GroupSpec.scala
@@ -26,9 +26,9 @@ import com.mongodb.casbah.util.Logging
import com.mongodb.casbah.commons.conversions.scala._
import org.scala_tools.time.Imports._
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
-class GroupSpec extends CasbahSpecification {
+class GroupSpec extends CasbahMutableSpecification {
"Casbah's Group Interfaces" should {
implicit val mongoDB = MongoConnection()("casbahIntegration")
View
6 casbah-core/src/test/scala/LazyDecodingSpec.scala
@@ -21,14 +21,14 @@
*/
package com.mongodb.casbah.test
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
import com.mongodb.casbah._
import com.mongodb.casbah.util.bson.decoding.OptimizedLazyDBObject
import java.util.{UUID , Date}
import org.bson.types.{MinKey, MaxKey, BSONTimestamp, Binary}
import java.util.regex.Pattern
-class LazyDecodingSpec extends CasbahSpecification {
+class LazyDecodingSpec extends CasbahMutableSpecification {
implicit val mongoInt = MongoConnection()("casbahIntegration")
implicit val mongoTest = MongoConnection()("casbahTest_Lazy")
@@ -163,7 +163,7 @@ class LazyDecodingSpec extends CasbahSpecification {
doc must haveEntry("double245_6289" -> 245.6289 )
doc must haveEntry("oid" -> testOid )
doc must haveEntry("str" -> "foobarbaz" )
- //doc.getAs[DBRef]("ref") must beSome( new DBRef(mongoInt.underlying, "books", testRefOid) )
+ doc must haveEntry("uuid" -> testUUID)
doc must haveEntry("object.abc" -> testDoc.get("abc") )
doc.getAs[Pattern]("regex").get.pattern() must_==( testRE.pattern.pattern() )
}
View
4 casbah-core/src/test/scala/MapReduceSpec.scala
@@ -27,10 +27,10 @@ import com.mongodb.casbah.util.Logging
import com.mongodb.casbah.commons.conversions.scala._
import org.scala_tools.time.Imports._
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
@SuppressWarnings(Array("deprecation"))
-class MapReduceSpec extends CasbahSpecification {
+class MapReduceSpec extends CasbahMutableSpecification {
"Casbah's Map/Reduce Engine" should {
View
4 casbah-core/src/test/scala/RawMapReduceSpec.scala
@@ -27,10 +27,10 @@ import com.mongodb.casbah.util.Logging
import com.mongodb.casbah.commons.conversions.scala._
import org.scala_tools.time.Imports._
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
@SuppressWarnings(Array("deprecation"))
-class RawMapReduceSpec extends CasbahSpecification {
+class RawMapReduceSpec extends CasbahMutableSpecification {
"MongoDB 1.7+ Map/Reduce functionality" should {
implicit val mongoDB = MongoConnection()("casbahIntegration")
View
4 casbah-gridfs/src/test/scala/GridFSSpec.scala
@@ -29,10 +29,10 @@ import com.mongodb.casbah.gridfs._
import java.security.MessageDigest
import java.io._
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
-class GridFSSpec extends CasbahSpecification {
+class GridFSSpec extends CasbahMutableSpecification {
/* override def is = args(sequential = true) ^ super.is*/
implicit val mongo = MongoConnection()("casbah_test")
View
299 casbah-query/src/main/scala/BarewordOperators.scala
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2010 10gen, Inc. <http://10gen.com>
+ * Copyright (c) 2010, 2011 10gen, Inc. <http://10gen.com>
* Copyright (c) 2009, 2010 Novus Partners, Inc. <http://novus.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,12 +41,12 @@ import scalaj.collection.Imports._
* @since 1.0
* @see SetOp
*/
-trait BarewordQueryOperator extends Logging {
+trait BarewordQueryOperator {
/*
* TODO - Implicit filtering of 'valid' (aka convertible) types for [A]
*/
- def apply[A](oper: String)(fields: (String, A)*) = {
+ def apply[A](oper: String)(fields: (String, A)*): DBObject = {
val bldr = MongoDBObject.newBuilder
for ((k, v) <- fields) bldr += k -> v
MongoDBObject(oper -> bldr.result.asDBObject)
@@ -54,6 +54,22 @@ trait BarewordQueryOperator extends Logging {
}
+class NestedBarewordListOperator(oper: String) {
+
+ def apply[A : ValidBarewordExpressionArgType](fields: A*): DBObject = {
+ val b = Seq.newBuilder[DBObject]
+ fields.foreach(x => b += implicitly[ValidBarewordExpressionArgType[A]].toDBObject(x))
+ apply(b.result(): Seq[DBObject])
+ }
+
+ def apply(list: Seq[DBObject]): DBObject = {
+ MongoDBObject(oper -> list)
+ }
+
+}
+
+
+
/**
* Aggregation object for Bareword Operators.
* Bareword operators stand on their own - they lack the requirement for an LValue.
@@ -70,23 +86,39 @@ trait FluidQueryBarewordOps extends SetOp
with UnsetOp
with IncOp
with OrOp
+ with AndOp
with RenameOp
with ArrayOps
with NorOp
with BitOp
+trait ArrayOps extends PushOp
+ with PushAllOp
+ with AddToSetOp
+ with PopOp
+ with PullOp
+ with PullAllOp
+
+trait SetOpBase extends BarewordQueryOperator {
+ protected def _set = apply[Any]("$set")_
+}
+
/**
* Trait to provide the $set (Set) Set method as a bareword operator.
- *
+ *
* $set ("Foo" -> "bar")
*
- * Targets an RValue of (String, Any)* to be converted to a DBObject
+ * Targets an RValue of (String, Any)* to be converted to a DBObject
*
* @author Brendan W. McAdams <brendan@10gen.com>
* @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24set
*/
-trait SetOp extends BarewordQueryOperator {
- def $set = apply[Any]("$set")_
+trait SetOp extends SetOpBase {
+ def $set = _set
+}
+
+trait UnsetOpBase extends BarewordQueryOperator {
+ protected def _unset(args: String*): DBObject = apply("$unset")(args.map(_ -> 1): _*)
}
/**
@@ -94,70 +126,61 @@ trait SetOp extends BarewordQueryOperator {
*
* $unset ("foo")
*
- * Targets an RValue of String*, where String are field names to be converted to a DBObject
+ * Targets an RValue of String*, where String are field names to be converted to a DBObject
*
* @author Brendan W. McAdams <brendan@10gen.com>
* @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24unset
*/
-trait UnsetOp extends BarewordQueryOperator {
- def $unset(args: String*) = apply("$unset")(args.map(_ -> 1): _*)
+trait UnsetOp extends UnsetOpBase {
+ def $unset = _unset _
}
-/**
+trait IncOpBase extends BarewordQueryOperator {
+ protected def _inc[T: ValidNumericType](args: (String, T)*): DBObject = apply[T]("$inc")(args: _*)
+}
+
+/**
* Trait to provide the $inc (inc) method as a bareword operator..
*
* $inc ("foo" -> 5)
*
- * Targets an RValue of (String, ValidNumericType)* to be converted to a DBObject
+ * Targets an RValue of (String, ValidNumericType)* to be converted to a DBObject
*
* Due to a quirk in the way I implemented type detection this fails if you mix ValidNumericType types. E.g. floats work, but not mixing floats and ints.
* This can be easily circumvented if you want 'ints' with floats by making your ints floats with .0:
- *
+ *
* $inc ("foo" -> 5.0, "bar" -> 1.6)
*
* @author Brendan W. McAdams <brendan@10gen.com>
* @since 1.0
* @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24inc
*/
-trait IncOp extends BarewordQueryOperator {
- def $inc[T: ValidNumericType](args: (String, T)*) = apply[T]("$inc")(args: _*)
+trait IncOp extends IncOpBase {
+ def $inc[T: ValidNumericType](args: (String, T)*): DBObject = _inc(args: _*)
}
-trait ArrayOps extends PushOp
- with PushAllOp
- with AddToSetOp
- with PopOp
- with PullOp
- with PullAllOp
+
+trait PushOpBase extends BarewordQueryOperator {
+ protected def _push = apply[Any]("$push")_
+}
/*
* Trait to provide the $push (push) method as a bareword operator.
*
- * Targets an RValue of (String, Any)* to be converted to a DBObject
+ * Targets an RValue of (String, Any)* to be converted to a DBObject
*
* If Field exists but is not an array an error will occur
- *
+ *
* @author Brendan W. McAdams <brendan@10gen.com>
* @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24push
- *
+ *
*/
-trait PushOp extends BarewordQueryOperator {
- def $push = apply[Any]("$push")_
+trait PushOp extends PushOpBase {
+ def $push = _push
}
-/*
- * Trait to provide the $pushAll (pushAll) method as a bareword operator..
- *
- * Targets an RValue of (String, Array[Any])* to be converted to a DBObject
- *
- * RValue MUST Be an array - otherwise use push.
- *
- *
- * @author Brendan W. McAdams <brendan@10gen.com>
- * @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24pushAll
- */
-trait PushAllOp extends BarewordQueryOperator {
- def $pushAll[A <: Any: Manifest](args: (String, A)*): DBObject =
+trait PushAllOpBase extends BarewordQueryOperator {
+ protected def _pushAll[A <: Any: Manifest](args: (String, A)*): DBObject =
if (manifest[A] <:< manifest[Iterable[_]])
apply("$pushAll")(args.map(z => z._1 -> z._2.asInstanceOf[Iterable[_]]): _*)
else if (manifest[A] <:< manifest[Product])
@@ -169,32 +192,34 @@ trait PushAllOp extends BarewordQueryOperator {
}
/*
- * Trait to provide the $addToSet (addToSet) method as a bareword operator..
+ * Trait to provide the $pushAll (pushAll) method as a bareword operator..
*
- * Targets an RValue of (String, Any)* to be converted to a DBObject
+ * Targets an RValue of (String, Array[Any])* to be converted to a DBObject
*
- * Can also combined with the $each operator for adding many values:
+ * RValue MUST Be an array - otherwise use push.
*
- * scala> $addToSet ("foo") $each (5, 10, 15, "20"))
- * res6: com.mongodb.casbah.commons.Imports.DBObject = { "$addToSet" : { "foo" : { "$each" : [ 5 , 10 , 15 , "20"]}}}
*
* @author Brendan W. McAdams <brendan@10gen.com>
- * @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24addToSet
+ * @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24pushAll
*/
-trait AddToSetOp extends BarewordQueryOperator {
+trait PushAllOp extends PushAllOpBase {
+ def $pushAll[A <: Any: Manifest](args: (String, A)*): DBObject = _pushAll(args: _*)
+}
- def $addToSet[T <% DBObject](arg: T) =
+trait AddToSetOpBase extends BarewordQueryOperator {
+ protected def _addToSet[T <% DBObject](arg: T): DBObject =
MongoDBObject("$addToSet" -> arg)
+
/* $each-able */
- def $addToSet(field: String) = {
+ protected def _addToSet(field: String) = {
/**
- * Special query operator only available on the right-hand side of an
+ * Special query operator only available on the right-hand side of an
* $addToSet which takes a list of values.
*
* Slightly hacky to prevent it from returning unless completed with a $each
*
- * THIS WILL NOT WORK IN MONGOD ANYWHERE BUT INSIDE AN ADDTOSET
+ * THIS WILL NOT WORK IN MONGOD ANYWHERE BUT INSIDE AN ADDTOSET
*
* @author Brendan W. McAdams <brendan@10gen.com>
* @since 2.0
@@ -214,53 +239,88 @@ trait AddToSetOp extends BarewordQueryOperator {
else op(target(0))
}
}
+ protected def _addToSet = apply[Any]("$addToSet")_
- def $addToSet = apply[Any]("$addToSet")_
}
/*
- * Trait to provide the $pop (pop) method as a bareword operator..
+ * Trait to provide the $addToSet (addToSet) method as a bareword operator..
*
+ * Targets an RValue of (String, Any)* to be converted to a DBObject
+ *
+ * Can also combined with the $each operator for adding many values:
+ *
+ * scala> $addToSet ("foo") $each (5, 10, 15, "20"))
+ * res6: com.mongodb.casbah.commons.Imports.DBObject = { "$addToSet" : { "foo" : { "$each" : [ 5 , 10 , 15 , "20"]}}}
+ *
+ * @author Brendan W. McAdams <brendan@10gen.com>
+ * @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24addToSet
+ */
+trait AddToSetOp extends AddToSetOpBase {
+ def $addToSet[T <% DBObject](arg: T): DBObject = _addToSet(arg)
+ def $addToSet(field: String) = _addToSet(field)
+ def $addToSet = _addToSet
+}
+
+trait PopOpBase extends BarewordQueryOperator {
+ protected def _pop[T: ValidNumericType](args: (String, T)*) = apply[T]("$pop")(args: _*)
+}
+
+/*
+ * Trait to provide the $pop (pop) method as a bareword operator..
*
- * TODO - Restrict to a 'Whole Number' type
- *
* If Field exists but is not an array an error will occurr.
*
* @author Brendan W. McAdams <brendan@10gen.com>
* @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop
*/
-trait PopOp extends BarewordQueryOperator {
- def $pop[T: ValidNumericType](args: (String, T)*) = apply[T]("$pop")(args: _*)
+trait PopOp extends PopOpBase {
+ def $pop[T: ValidNumericType](args: (String, T)*) = _pop(args: _*)
+}
+
+trait PullOpBase extends BarewordQueryOperator {
+ protected def _pull = apply[Any]("$pull")_
+ /** ValueTest enabled version */
+ protected def _pull(inner: => DBObject): DBObject = MongoDBObject("$pull" -> inner)
+ protected def _pull(inner: DBObject): DBObject = MongoDBObject("$pull" -> inner)
}
/*
* Trait to provide the $pull (pull) method as a bareword operator..
*
- * Targets an RValue of (String, Any)* to be converted to a DBObject
+ * Targets an RValue of (String, Any)* to be converted to a DBObject
*
* If Field exists but is not an array an error will occurr.
- *
+ *
* Pull is special as defined in the docs and needs to allow operators on fields.
- *
+ *
* @author Brendan W. McAdams <brendan@10gen.com>
* @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull
*/
-trait PullOp extends BarewordQueryOperator {
+trait PullOp extends PullOpBase {
def $pull = apply[Any]("$pull")_
+ def $pull(inner: => DBObject): DBObject = _pull(inner)
+ def $pull(inner: DBObject): DBObject = _pull(inner)
+}
- /** ValueTest enabled version */
- def $pull(inner: => DBObject) =
- MongoDBObject("$pull" -> inner)
+trait PullAllOpBase extends BarewordQueryOperator {
+ protected def _pullAll[A <: Any: Manifest](args: (String, A)*): DBObject =
+ if (manifest[A] <:< manifest[Iterable[_]])
+ apply("$pullAll")(args.map(z => z._1 -> z._2.asInstanceOf[Iterable[_]]): _*)
+ else if (manifest[A] <:< manifest[Product])
+ apply("$pullAll")(args.map(z => z._1 -> z._2.asInstanceOf[Product].productIterator.toIterable): _*)
+ else if (manifest[A].erasure.isArray)
+ apply("$pullAll")(args.map(z => z._1 -> z._2.asInstanceOf[Array[_]].toIterable): _*)
+ else
+ throw new IllegalArgumentException("$pullAll may only be invoked with a (String, A) where String is the field name and A is an Iterable or Product/Tuple of values (got %s).".format(manifest[A]))
- def $pull(inner: DBObject) =
- MongoDBObject("$pull" -> inner)
}
/*
* Trait to provide the $pullAll (pullAll) method as a bareword operator..
*
- * Targets an RValue of (String, Array[Any])* to be converted to a DBObject
+ * Targets an RValue of (String, Array[Any])* to be converted to a DBObject
*
* RValue MUST Be an array - otherwise use pull.
*
@@ -268,16 +328,12 @@ trait PullOp extends BarewordQueryOperator {
* @author Brendan W. McAdams <brendan@10gen.com>
* @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24pullAll
*/
-trait PullAllOp extends BarewordQueryOperator {
- def $pullAll[A <: Any: Manifest](args: (String, A)*): DBObject =
- if (manifest[A] <:< manifest[Iterable[_]])
- apply("$pullAll")(args.map(z => z._1 -> z._2.asInstanceOf[Iterable[_]]): _*)
- else if (manifest[A] <:< manifest[Product])
- apply("$pullAll")(args.map(z => z._1 -> z._2.asInstanceOf[Product].productIterator.toIterable): _*)
- else if (manifest[A].erasure.isArray)
- apply("$pullAll")(args.map(z => z._1 -> z._2.asInstanceOf[Array[_]].toIterable): _*)
- else
- throw new IllegalArgumentException("$pullAll may only be invoked with a (String, A) where String is the field name and A is an Iterable or Product/Tuple of values (got %s).".format(manifest[A]))
+trait PullAllOp extends PullAllOpBase {
+ def $pullAll[A <: Any: Manifest](args: (String, A)*): DBObject = _pullAll(args: _*)
+}
+
+trait AndOpBase {
+ protected def _and = new NestedBarewordListOperator("$and")
}
/**
@@ -285,27 +341,18 @@ trait PullAllOp extends BarewordQueryOperator {
*
* $and ("Foo" -> "bar")
*
- * Targets an RValue of (String, Any)* to be converted to a DBObject
+ * Targets an RValue of (String, Any)* to be converted to a DBObject
*
- * TODO - Test that rvalue ends up being an array e.g.:
- *
- * scala> $or ("foo" -> "bar", "X" -> 5)
- * res1: com.mongodb.casbah.commons.Imports.DBObject = { "$or" : [ { "foo" : "bar" , "X" : 5}]}
- *
- *
* @author Ben Gamari <bgamari.foss@gmail.com>
- * @since 2.0
+ * @since 3.0
* @see http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24and
*/
+trait AndOp extends AndOpBase {
+ def $and = _and
+}
-trait AndOp extends BarewordQueryOperator {
-
- def $and(fields: (String, Any)*) = {
- val bldr = MongoDBList.newBuilder
- for ((k, v) <- fields) bldr += MongoDBObject(k -> v)
- MongoDBObject("$and" -> bldr.result)
- }
-
+trait OrOpBase {
+ protected def _or = new NestedBarewordListOperator("$or")
}
/**
@@ -313,29 +360,19 @@ trait AndOp extends BarewordQueryOperator {
*
* $or ("Foo" -> "bar")
*
- * Targets an RValue of (String, Any)* to be converted to a DBObject
+ * Targets an RValue of (String, Any)* to be converted to a DBObject
*
- * TODO - Test that rvalue ends up being an array e.g.:
- *
- * scala> $or ("foo" -> "bar", "X" -> 5)
- * res1: com.mongodb.casbah.commons.Imports.DBObject = { "$or" : [ { "foo" : "bar" , "X" : 5}]}
- *
- *
* @author Brendan W. McAdams <brendan@10gen.com>
* @since 2.0
* @see http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24or
*/
+trait OrOp extends OrOpBase {
+ def $or = _or
+}
-trait OrOp extends BarewordQueryOperator {
-
- def $or(fields: (String, Any)*) = {
- val bldr = MongoDBList.newBuilder
- for ((k, v) <- fields) bldr += MongoDBObject(k -> v)
- MongoDBObject("$or" -> bldr.result)
- }
- def $or[A : ValidBarewordExpressionArgType](fields: A*) =
- MongoDBObject("$or" -> implicitly[ValidBarewordExpressionArgType[A]].listify(fields))
+trait RenameOpBase extends BarewordQueryOperator {
+ protected def _rename = apply[Any]("$rename")_
}
/**
@@ -350,8 +387,12 @@ trait OrOp extends BarewordQueryOperator {
* @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24rename
*
*/
-trait RenameOp extends BarewordQueryOperator {
- def $rename = apply[Any]("$rename")_
+trait RenameOp extends RenameOpBase {
+ def $rename = _rename
+}
+
+trait NorOpBase {
+ protected def _nor = new NestedBarewordListOperator("$nor")
}
/**
@@ -365,41 +406,35 @@ trait RenameOp extends BarewordQueryOperator {
* @since 2.0
* @see http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24nor
*/
-trait NorOp extends BarewordQueryOperator {
+trait NorOp extends NorOpBase {
+ def $nor = _nor
+}
- /** ValueTest enabled version */
- def $nor(inner: => DBObject) =
- MongoDBObject("$nor" -> (inner match {
- case obj: BasicDBList => obj.toSeq
- case obj: MongoDBList => obj
- case obj: DBObject => MongoDBList(obj)
- }).asInstanceOf[Seq[Any]])
+trait BitOpBase extends BarewordQueryOperator {
+ protected def _bit(field: String) = {
+ new {
+ protected def op(oper: String, target: Any) =
+ MongoDBObject("$bit" -> MongoDBObject(field -> MongoDBObject(oper -> target)))
+ def and[T: ValidNumericType](target: T) = op("and", target)
+ def or[T: ValidNumericType](target: T) = op("or", target)
+ }
+ }
}
/**
* Trait to provide the $bit (bit) update method as a bareword Operator
- *
+ *
* Bit does a bitwise operation either AND or OR against a given field or set of fields
* with no left anchor.
- *
+ *
* Targets an RValue of {field: {and|or: integer}}.
*
* @author Brendan W. McAdams <brendan@10gen.com>
* @since 2.1.1
* @see http://www.mongodb.org/display/DOCS/Updating#Updating-%24bit
*/
-trait BitOp extends BarewordQueryOperator {
-
- def $bit(field: String) = {
- new {
- protected def op(oper: String, target: Any) =
- MongoDBObject("$bit" -> MongoDBObject(field -> MongoDBObject(oper -> target)))
-
- def and[T: ValidNumericType](target: T) = op("and", target)
- def or[T: ValidNumericType](target: T) = op("or", target)
- }
- }
-
+trait BitOp extends BitOpBase {
+ def $bit(field: String) = _bit(field)
}
// vim: set ts=2 sw=2 sts=2 et:
View
4 casbah-query/src/main/scala/CoreOperators.scala
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2010 10gen, Inc. <http://10gen.com>
+ * Copyright (c) 2010, 2011 10gen, Inc. <http://10gen.com>
* Copyright (c) 2009, 2010 Novus Partners, Inc. <http://novus.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -91,7 +91,7 @@ object QueryExpressionObject {
*
* @author Brendan W. McAdams <brendan@10gen.com>
*/
-sealed trait QueryOperator extends Logging {
+trait QueryOperator extends Logging {
def field: String
protected var dbObj: Option[DBObject] = None
View
24 casbah-query/src/main/scala/Implicits.scala
@@ -26,7 +26,7 @@ package query
import com.mongodb.casbah.query.dsl.QueryExpressionObject
-trait Implicits {// extends FluidQueryBarewordOps {
+trait Implicits {
/**
* Implicit extension methods for String values (e.g. a field name)
@@ -97,14 +97,18 @@ object ValidTypes {
trait JDKDateOk extends ValidDateType[java.util.Date]
trait JodaDateTimeOk extends ValidDateType[org.joda.time.DateTime]
+ trait KVPair[A] extends ValidBarewordExpressionArgType[(String, A)] {
+ def toDBObject(arg: (String, A)): DBObject = MongoDBObject(arg)
+ }
+
// Valid Bareword Query Expression entries
trait CoreOperatorResultObj extends ValidBarewordExpressionArgType[DBObject with QueryExpressionObject] {
- def listify(args: Seq[DBObject with QueryExpressionObject]): Seq[DBObject] = {
- val bldr = MongoDBList.newBuilder
- args.foreach(bldr.+=)
- bldr.result.asInstanceOf[Seq[DBObject]]
+ def toDBObject(arg: DBObject with QueryExpressionObject): DBObject = arg
+ }
+
+ trait ConcreteDBObject extends ValidBarewordExpressionArgType[DBObject] {
+ def toDBObject(arg: DBObject): DBObject = arg
}
-}
// ValidNumericTypes
trait BigIntOk extends ValidNumericType[BigInt] with Numeric.BigIntIsIntegral with Ordering.BigIntOrdering
@@ -118,16 +122,16 @@ object ValidTypes {
}
trait ValidBarewordExpressionArgType[T] {
- def listify(args: Seq[T]): Seq[DBObject]
+ def toDBObject(arg: T): DBObject
}
trait ValidBarewordExpressionArgTypeHolder {
- import com.mongodb.casbah.query.ValidTypes.{CoreOperatorResultObj}
+ import com.mongodb.casbah.query.ValidTypes.{ConcreteDBObject, CoreOperatorResultObj, KVPair}
+ implicit def kvPairOk[A]: KVPair[A] = new KVPair[A] {}
+ implicit object ConcreteDBObjectOk extends ConcreteDBObject
implicit object CoreOperatorResultObjOk extends CoreOperatorResultObj
}
-/*trait ValidTypeClassHolders extends */
-
trait ValidNumericType[T]
trait ValidDateType[T]
View
83 casbah-query/src/test/scala/BarewordOperatorsSpec.scala
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2010 10gen, Inc. <http://10gen.com>
+ * Copyright (c) 2010, 2011 10gen, Inc. <http://10gen.com>
* Copyright (c) 2009, 2010 Novus Partners, Inc. <http://novus.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,11 +23,11 @@
package com.mongodb.casbah.test.query
import com.mongodb.casbah.query._
-import com.mongodb.casbah.commons.test.CasbahSpecification
-import org.bson.types.BasicBSONList
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
+// TODO - Operational/Integration testing with this code
@SuppressWarnings(Array("deprecation"))
-class BarewordOperatorsSpec extends CasbahSpecification {
+class BarewordOperatorsSpec extends CasbahMutableSpecification {
"Casbah's DSL $set Operator" should {
"Accept one or many pairs of values" in {
"A single pair" in {
@@ -74,15 +74,49 @@ class BarewordOperatorsSpec extends CasbahSpecification {
}
}
- "Casbah's DSL $or Operator" should {
+ "Casbah's DSL $or Operator" >> {
"Accept multiple values" in {
- val or = $or("foo" -> "bar", "x" -> "y")
+ val or = $or ( "foo" -> "bar", "x" -> "y" )
or must haveListEntry("$or", Seq(MongoDBObject("foo" -> "bar"), MongoDBObject("x" -> "y")))
}
+ "Accept a mix" in {
+ val or = $or { "foo" -> "bar" :: ("foo" $gt 5 $lt 10) }
+ or must haveListEntry("$or", Seq(MongoDBObject("foo" -> "bar"), MongoDBObject("foo" -> MongoDBObject("$gt" -> 5, "$lt" -> 10))))
+ }
"Work with nested operators" in {
- val or = $or( "foo" $lt 5 $gt 1, "x" $gte 10 $lte 152 )
- or must haveSuperclass[BasicBSONList]
- or must beEqualTo(MongoDBObject("$or" -> MongoDBList(MongoDBObject("foo" -> "bar", "x" -> "y"))))
+ "As a simple list (comma separated)" in {
+ val or = $or( "foo" $lt 5 $gt 1, "x" $gte 10 $lte 152 )
+ or must haveListEntry("$or", Seq(MongoDBObject("foo" -> MongoDBObject("$lt" -> 5, "$gt" -> 1)),
+ MongoDBObject("x" -> MongoDBObject("$gte" -> 10, "$lte" -> 152))))
+ }
+ "As a cons (:: constructed) cell" in {
+ val or = $or( ("foo" $lt 5 $gt 1) :: ("x" $gte 10 $lte 152) )
+ or must haveListEntry("$or", Seq(MongoDBObject("foo" -> MongoDBObject("$lt" -> 5, "$gt" -> 1)),
+ MongoDBObject("x" -> MongoDBObject("$gte" -> 10, "$lte" -> 152))))
+ }
+ }
+ }
+
+ "Casbah's DSL $and Operatand" >> {
+ "Accept multiple values" in {
+ val and = $and ( "foo" -> "bar", "x" -> "y" )
+ and must haveListEntry("$and", Seq(MongoDBObject("foo" -> "bar"), MongoDBObject("x" -> "y")))
+ }
+ "Accept a mix" in {
+ val and = $and { "foo" -> "bar" :: ("foo" $gt 5 $lt 10) }
+ and must haveListEntry("$and", Seq(MongoDBObject("foo" -> "bar"), MongoDBObject("foo" -> MongoDBObject("$gt" -> 5, "$lt" -> 10))))
+ }
+ "Wandk with nested operatands" in {
+ "As a simple list (comma separated)" in {
+ val and = $and( "foo" $lt 5 $gt 1, "x" $gte 10 $lte 152 )
+ and must haveListEntry("$and", Seq(MongoDBObject("foo" -> MongoDBObject("$lt" -> 5, "$gt" -> 1)),
+ MongoDBObject("x" -> MongoDBObject("$gte" -> 10, "$lte" -> 152))))
+ }
+ "As a cons (:: constructed) cell" in {
+ val and = $and( ("foo" $lt 5 $gt 1) :: ("x" $gte 10 $lte 152) )
+ and must haveListEntry("$and", Seq(MongoDBObject("foo" -> MongoDBObject("$lt" -> 5, "$gt" -> 1)),
+ MongoDBObject("x" -> MongoDBObject("$gte" -> 10, "$lte" -> 152))))
+ }
}
}
@@ -205,17 +239,26 @@ class BarewordOperatorsSpec extends CasbahSpecification {
}
- "Casbah's DSL $nor operator" should {
- "Function as expected" in {
- val nor = $nor { "foo" $gte 15 $lt 35.2 $ne 16 }
- nor.getAs[MongoDBList]("$nor") must have size (1)
- nor.as[MongoDBList]("$nor").getAs[DBObject](0) must haveSomeEntries("foo.$gte" -> 15, "foo.$lt" -> 35.2, "foo.$ne" -> 16)
- }
- "Work with multiples" in {
- val nor = $nor { ("foo" $gte 15 $lt 35 $ne 16) + ("x" -> "y") }
- nor.getAs[MongoDBList]("$nor") must have size (1)
- nor.as[MongoDBList]("$nor").getAs[DBObject](0) must haveSomeEntries("foo.$gte" -> 15, "foo.$lt" -> 35,
- "foo.$ne" -> 16, "x" -> "y")
+ "Casbah's DSL $nor operator" >> {
+ "Accept multiple values" in {
+ val nor = $nor ( "foo" -> "bar", "x" -> "y" )
+ nor must haveListEntry("$nor", Seq(MongoDBObject("foo" -> "bar"), MongoDBObject("x" -> "y")))
+ }
+ "Accept a mix" in {
+ val nor = $nor { "foo" -> "bar" :: ("foo" $gt 5 $lt 10) }
+ nor must haveListEntry("$nor", Seq(MongoDBObject("foo" -> "bar"), MongoDBObject("foo" -> MongoDBObject("$gt" -> 5, "$lt" -> 10))))
+ }
+ "Work with nested operators" in {
+ "As a simple list (comma separated)" in {
+ val nor = $nor( "foo" $lt 5 $gt 1, "x" $gte 10 $lte 152 )
+ nor must haveListEntry("$nor", Seq(MongoDBObject("foo" -> MongoDBObject("$lt" -> 5, "$gt" -> 1)),
+ MongoDBObject("x" -> MongoDBObject("$gte" -> 10, "$lte" -> 152))))
+ }
+ "As a cons (:: constructed) cell" in {
+ val nor = $nor( ("foo" $lt 5 $gt 1) :: ("x" $gte 10 $lte 152) )
+ nor must haveListEntry("$nor", Seq(MongoDBObject("foo" -> MongoDBObject("$lt" -> 5, "$gt" -> 1)),
+ MongoDBObject("x" -> MongoDBObject("$gte" -> 10, "$lte" -> 152))))
+ }
}
}
}
View
7 casbah-query/src/test/scala/DSLCoreOperatorsSpec.scala
@@ -28,10 +28,10 @@ import com.mongodb.casbah.query._
import org.scala_tools.time.Imports._
-import com.mongodb.casbah.commons.test.CasbahSpecification
+import com.mongodb.casbah.commons.test.CasbahMutableSpecification
@SuppressWarnings(Array("deprecation"))
-class DSLCoreOperatorsSpec extends CasbahSpecification {
+class LightDSLCoreOperatorsSpec extends CasbahMutableSpecification {
def nonDSL(key: String, oper: String, value: Any) = MongoDBObject(key -> MongoDBObject(oper -> value))
@@ -822,7 +822,7 @@ class DSLCoreOperatorsSpec extends CasbahSpecification {
}
}
"None (null)" in {
- // For some reason you can't use NONE
+ // For some reason you can't use NONE
val typeOper = "foo".$type[Option[Nothing]]
typeOper must haveEntry("foo.$type" -> org.bson.BSON.NULL)
}
@@ -996,3 +996,4 @@ class DSLCoreOperatorsSpec extends CasbahSpecification {
}
}
// vim: set ts=2 sw=2 sts=2 et:
+
View
102 casbah-util/src/main/scala/bson/BSONPrimitive.scala → ...src/main/scala/bson/primitive/BSONPrimitive.scala
@@ -14,26 +14,26 @@
* limitations under the License.
*
*/
-
package com.mongodb.casbah.util.bson
+package primitive
/**
* A Container for BSON Primitive types
*
*/
-sealed trait BSONPrimitive {
+sealed trait BSONPrimitive[Raw] {
/**
* The "container" type for this...
* basically the Scala side primitives
* represented.
- * For example, a BSONDatePrimitive's ContainerType
+ * For example, a BSONDatePrimitive's Primitive
* is a Long , holding the milliseconds
*
* This is, essentially, the MOST RAW type representation
* rather than a specific instantiation.
*/
- type ContainerType <: Any
+ type Primitive <: Any
/**
* The type represented by this primitive
@@ -41,61 +41,71 @@ sealed trait BSONPrimitive {
def typeCode: BSONType.TypeCode
/**
- * The "container" value
+ * The bson "container" value, from the raw type
+ *
+ * e.g. Int -> BSON Representation of an Int
+ *
*/
- def bsonValue: ContainerType
+ def bsonValue(raw: Raw): Primitive
+
+ /**
+ * The "raw" type, read from the BSON Primitive
+ *
+ * e.g. BSON Integer -> JVM Int
+ */
+ def rawValue(bson: Primitive): Raw
}
// EOO is not a valid type container ;)
-trait BSONDoublePrimitive extends BSONPrimitive {
- type ContainerType = Double
+trait BSONDoublePrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Double
val typeCode = BSONType.Double
}
-trait BSONStringPrimitive extends BSONPrimitive {
- type ContainerType = String
+trait BSONStringPrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = String
val typeCode = BSONType.String
}
-trait BSONObjectPrimitive extends BSONPrimitive {
+trait BSONObjectPrimitive[Raw] extends BSONPrimitive[Raw] {
// TODO - Hmm... this could be a Map[String, Any], no?
- type ContainerType = org.bson.BSONObject
+ type Primitive = org.bson.BSONObject
val typeCode = BSONType.Object
}
-trait BSONArrayPrimitive extends BSONPrimitive {
- type ContainerType = Seq[Any]
+trait BSONArrayPrimitive[T, Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Seq[T]
val typeCode = BSONType.Array
}
-sealed trait BSONBinaryPrimitive extends BSONPrimitive {
+sealed trait BSONBinaryPrimitive[Raw] extends BSONPrimitive[Raw] {
val typeCode = BSONType.Binary
def subtypeCode: BSONBinarySubtype.SubtypeCode
}
-trait BSONGenericBinaryPrimitive extends BSONBinaryPrimitive {
- type ContainerType = Array[Byte]
+trait BSONGenericBinaryPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = Array[Byte]
val subtypeCode = BSONBinarySubtype.Generic
}
-trait BSONBinaryFunctionPrimitive extends BSONBinaryPrimitive {
- type ContainerType = Array[Byte] // TODO - Better type repr?
+trait BSONBinaryFunctionPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = Array[Byte] // TODO - Better type repr?
val subtypeCode = BSONBinarySubtype.Function
}
-trait BSONOldBinaryPrimitive extends BSONBinaryPrimitive {
- type ContainerType = Array[Byte]
+trait BSONOldBinaryPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = Array[Byte]
val subtypeCode = BSONBinarySubtype.OldBinary
}
-trait BSONUUIDPrimitive extends BSONBinaryPrimitive {
- type ContainerType = (Long /* most sig bits */, Long /* least sig bits */)
+trait BSONUUIDPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = (Long /* most sig bits */, Long /* least sig bits */)
val subtypeCode = BSONBinarySubtype.UUID
}
-trait BSONNewUUIDPrimitive extends BSONBinaryPrimitive {
- type ContainerType = (Long /* most sig bits */, Long /* least sig bits */)
+trait BSONNewUUIDPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = (Long /* most sig bits */, Long /* least sig bits */)
val subtypeCode = BSONBinarySubtype.NewUUID
}
@@ -107,24 +117,24 @@ trait BSONNewUUIDPrimitive extends BSONBinaryPrimitive {
* Use this for your own custom binarys, BSONBinaryPrimitive is
* sealed for safety/sanity
*/
-trait BSONCustomBinaryPrimitive extends BSONBinaryPrimitive
+trait BSONCustomBinaryPrimitive[Raw] extends BSONBinaryPrimitive[Raw]
-trait BSONObjectIdPrimitive extends BSONPrimitive {
- type ContainerType = (Int /* time */, Int /* machineID */, Int /* Increment */)
+trait BSONObjectIdPrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = (Int /* time */, Int /* machineID */, Int /* Increment */)
val typeCode = BSONType.ObjectId
}
-trait BSONBooleanPrimitive extends BSONPrimitive {
- type ContainerType = Boolean
+trait BSONBooleanPrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Boolean
val typeCode = BSONType.Boolean
}
-trait BSONDatePrimitive extends BSONPrimitive {
- type ContainerType = Long /* the UTC milliseconds since the Unix Epoch. */
+trait BSONDatePrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Long /* the UTC milliseconds since the Unix Epoch. */
val typeCode = BSONType.Date
}
-trait BSONRegexPrimitive extends BSONPrimitive {
+trait BSONRegexPrimitive[Raw] extends BSONPrimitive[Raw] {
val typeCode = BSONType.RegEx
/**
* [Regular expression]
@@ -143,41 +153,41 @@ trait BSONRegexPrimitive extends BSONPrimitive {
* 's' for dotall mode ('.' matches everything),
* 'u' to make \w, \W, etc. match unicode.
*/
- type ContainerType = (String /* pattern */, String /* flags */)
+ type Primitive = (String /* pattern */, String /* flags */)
}
/**
* Skip support for the deprecated DBPointer
*/
-trait BSONCodePrimitive extends BSONPrimitive {
- type ContainerType = String
+trait BSONCodePrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = String
val typeCode = BSONType.Code
}
-trait BSONSymbolPrimitive extends BSONPrimitive {
+trait BSONSymbolPrimitive[Raw] extends BSONPrimitive[Raw] {
/** Stored as a string */
- type ContainerType = String
+ type Primitive = String
val typeCode = BSONType.Symbol
}
-trait BSONScopedCodePrimitive extends BSONPrimitive {
- type ContainerType = (String /* code */, org.bson.BSONObject /* Scope */)
+trait BSONScopedCodePrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = (String /* code */, org.bson.BSONObject /* Scope */)
val typeCode = BSONType.ScopedCode
}
-trait BSONInt32Primitive extends BSONPrimitive {
- type ContainerType = Int
+trait BSONInt32Primitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Int
val typeCode = BSONType.Int32
}
-trait BSONTimestampPrimitive extends BSONPrimitive {
- type ContainerType = (Int /* Time */, Int /* Increment */)
+trait BSONTimestampPrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = (Int /* Time */, Int /* Increment */)
val typeCode = BSONType.Timestamp
}
-trait BSONInt64Primitive extends BSONPrimitive {
- type ContainerType = Long /* Yes, Billy. We represent Longs as Longs! */
+trait BSONInt64Primitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Long /* Yes, Billy. We represent Longs as Longs! */
val typeCode = BSONType.Int64
}
View
2  casbah-util/src/main/scala/bson/BSONType.scala → ...util/src/main/scala/bson/primitive/BSONType.scala
@@ -14,8 +14,8 @@
* limitations under the License.
*
*/
-
package com.mongodb.casbah.util.bson
+package primitive
/**
* Enumerative lookup for BSON Types, as defined in the spec
View
154 casbah-util/src/main/scala/bson/primitive/Builtins.scala
@@ -0,0 +1,154 @@
+/**
+ * Copyright (c) 2008 - 2011 10gen, Inc. <http://10gen.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.mongodb.casbah.util.bson.primitive
+
+import scala.util.matching.Regex
+import java.util.regex.Pattern
+import org.scala_tools.time.Imports._
+import org.bson.BSON
+
+trait Builtins {
+
+ /**
+ * Scala RegEx
+ */
+ trait ScalaRegexPrimitive extends BSONRegexPrimitive[Regex] {
+ def rawValue(bson: (String /* pattern */, String /* flags */)): scala.util.matching.Regex = {
+ // Construct a RegEx
+ "(?%s)%s".format(bson._2, bson._1).r
+ }
+
+ def bsonValue(raw: Regex): (String /* pattern */, String /* flags */) = {
+ // Reduce a Scala Regex to a raw BSON tuple
+ val jPat = raw.pattern
+ (jPat.pattern, BSON.regexFlags(jPat.flags))
+ }
+ }
+
+ /**
+ * Java Regex
+ */
+ trait JavaRegexPrimitive extends BSONRegexPrimitive[java.util.regex.Pattern] {
+ def rawValue(bson: (String /* pattern */, String /* flags */)): java.util.regex.Pattern = {
+ // Construct a RegEx
+ Pattern.compile("(?%s)%s".format(bson._2, bson._1))
+ }
+
+ def bsonValue(raw: Regex): (String /* pattern */, String /* flags */) = {
+ // Reduce a Scala Regex to a raw BSON tuple
+ (raw.pattern.pattern, BSON.regexFlags(raw.pattern.flags))
+ }
+ }
+
+ /**
+ * 'Option' can't be done ... normally. Might need special logic
+ */
+
+ /**
+ * Some Scala collections for fun and profit.
+ *
+ * TODO - Immutable versions
+ */
+ def typedMutableBufferPrimitive[A]: BSONArrayPrimitive[A, scala.collection.mutable.Buffer[A]] = new MutableBufferPrimitive[A] {}
+
+ trait MutableBufferPrimitive[A] extends BSONArrayPrimitive[A, scala.collection.mutable.Buffer[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.mutable.Buffer[A] = {
+ bson.toBuffer
+/* // TODO - This is mostly utterly useless and a bit wasteful, ya?
+ scala.collection.mutable.Buffer(bson: _*)*/
+ }
+
+ def bsonValue(raw: scala.collection.mutable.Buffer[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ def typedMutableSeqPrimitive[A]: BSONArrayPrimitive[A, scala.collection.mutable.Seq[A]] = new MutableSeqPrimitive[A] {}
+
+ trait MutableSeqPrimitive[A] extends BSONArrayPrimitive[A, scala.collection.mutable.Seq[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.mutable.Seq[A] = {
+ // TODO - This is mostly utterly useless and a bit wasteful, ya?
+ scala.collection.mutable.Seq(bson: _*)
+ }
+
+ def bsonValue(raw: scala.collection.mutable.Seq[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ def typedMutableSetPrimitive[A]: BSONArrayPrimitive[A, scala.collection.mutable.Set[A]] = new MutableSetPrimitive[A] {}
+
+ trait MutableSetPrimitive[A] extends BSONArrayPrimitive[A, scala.collection.mutable.Set[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.mutable.Set[A] = {
+ // TODO - This is mostly utterly useless and a bit wasteful, ya?
+ scala.collection.mutable.Set(bson: _*)
+ }
+
+ def bsonValue(raw: scala.collection.mutable.Set[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ def typedIterablePrimitive[A]: BSONArrayPrimitive[A, scala.collection.Iterable[A]] = new IterablePrimitive[A] {}
+
+ trait IterablePrimitive[A] extends BSONArrayPrimitive[A, scala.collection.Iterable[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.Iterable[A] = {
+ bson.toIterable
+ }
+
+ def bsonValue(raw: scala.collection.Iterable[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ def typedIteratorPrimitive[A]: BSONArrayPrimitive[A, scala.collection.Iterator[A]] = new IteratorPrimitive[A] {}
+
+ trait IteratorPrimitive[A] extends BSONArrayPrimitive[A, scala.collection.Iterator[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.Iterator[A] = {
+ bson.iterator
+ }
+
+ def bsonValue(raw: scala.collection.Iterator[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ trait JodaDateTimePrimitive extends BSONDatePrimitive[DateTime] {
+ def rawValue(bson: Long): DateTime = {
+ new DateTime(bson)
+ }
+
+ def bsonValue(raw: DateTime): Long = {
+ raw.getMillis
+ }
+ }
+
+ trait JDKDatePrimitive extends BSONDatePrimitive[java.util.Date] {
+ def rawValue(bson: Long): java.util.Date = {
+ new java.util.Date(bson)
+ }
+
+ def bsonValue(raw: java.util.Date): Long = {
+ raw.getTime
+ }
+ }
+
+
+
+}
+
+
View
21 project/CasbahBuild.scala
@@ -24,7 +24,7 @@ object CasbahBuild extends Build {
override lazy val settings = super.settings ++ buildSettings
lazy val baseSettings = Defaults.defaultSettings ++ Publish.settings ++ Seq(
- resolvers ++= Seq(scalaToolsReleases, scalaToolsSnapshots, mavenOrgRepo),
+ resolvers ++= Seq(scalaToolsReleases, scalaToolsSnapshots, mavenOrgRepo, sonatypeRels),
testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "console", "junitxml")
)
@@ -34,7 +34,16 @@ object CasbahBuild extends Build {
)
lazy val defaultSettings = baseSettings ++ Seq(
- libraryDependencies ++= Seq(scalatest(scalaVersion), specs2, slf4j, slf4jJCL),
+ libraryDependencies ++= Seq(scalatest(scalaVersion), slf4j, slf4jJCL),
+ libraryDependencies <<= (scalaVersion, libraryDependencies) { (sv, deps) =>
+ val versionMap = Map("2.8.0" -> ("specs2_2.8.0", "1.5"),
+ "2.8.1" -> ("specs2_2.8.1", "1.5"),
+ "2.9.0" -> ("specs2_2.9.0", "1.7.1"),
+ "2.9.0-1" -> ("specs2_2.9.0", "1.7.1"),
+ "2.9.1" -> ("specs2_2.9.1", "1.7.1"))
+ val tuple = versionMap.getOrElse(sv, error("Unsupported Scala version for Specs2"))
+ deps :+ ("org.specs2" % tuple._1 % tuple._2)
+ },
autoCompilerPlugins := true,
parallelExecution in Test := true,
testFrameworks += TestFrameworks.Specs2
@@ -85,14 +94,14 @@ object CasbahBuild extends Build {
object Dependencies {
- val mongoJavaDriver = "org.mongodb" % "mongo-java-driver" % "2.7.0"
+ val mongoJavaDriver = "org.mongodb" % "mongo-java-driver" % "2.7.2"
val scalajCollection = "org.scalaj" %% "scalaj-collection" % "1.2"
val slf4j = "org.slf4j" % "slf4j-api" % "1.6.0"
- val specs2 = "org.specs2" %% "specs2" % "1.5" % "provided"
+ val specs2 = "org.specs2" %% "specs2" % "1.5.1" % "provided"
//val specs2 = specs2Compile % "test"
- def specs2ScalazCore(scalaVer: sbt.SettingKey[String]) =
+ def specs2ScalazCore(scalaVer: sbt.SettingKey[String]) =
scalaVersionString(scalaVer) match {
case "2.8.1" => "org.specs2" %% "specs2-scalaz-core" % "5.1-SNAPSHOT" % "test"
case _ => "org.specs2" %% "specs2-scalaz-core" % "6.0.RC2" % "test"
@@ -100,7 +109,7 @@ object Dependencies {
def scalaVersionString(scalaVer: sbt.SettingKey[String]): String = {
var result = ""
- scalaVer { sv => result = sv }
+ scalaVersion { sv => result = sv }
if (result == "") result = "2.8.1"
result
}
View
2  project/build.properties
@@ -1 +1 @@
-sbt.version=0.11.0
+sbt.version=0.11.1
View
7 tutorial_src/source/tutorial.rst
@@ -1,5 +1,4 @@
-
*************************
Tutorial: Using Casbah
*************************
@@ -26,17 +25,17 @@ As we mentioned, as soon as you construct a ``MongoConnection`` object, a few ty
As many Scala developers tend to prefer `Joda time <http://joda-time.sourceforge.net/>`_ over JDK Dates, you can also explicitly enable serialization and deserialization of them (w/ full support for the `Scala-Time wrappers <http://github.com/jorgeortiz85/scala-time>`_) by an explicit call::
- import com.mongodb.casbah.conversions.scala._
+ import com.mongodb.casbah.commons.conversions.scala._
RegisterJodaTimeConversionHelpers()
Once these are loaded, Joda Time (and Scala Time wrappers) will be saved to MongoDB as proper BSON Dates, and on retrieval/deserialization all BSON Dates will be returned as Joda ``DateTime`` instead of a JDK Date (aka `java.util.Date`). Because this can cause problems in some instances, you can explicitly unload the Joda Time helpers::
- import com.mongodb.casbah.conversions.scala._
+ import com.mongodb.casbah.commons.conversions.scala._
DeregisterJodaTimeConversionHelpers()
And reload them later as needed. If you find you need to unload the other helpers as well, you can load and unload them just as easily::
- import com.mongodb.casbah.conversions.scala._
+ import com.mongodb.casbah.commons.conversions.scala._
DeregisterConversionHelpers()
RegisterConversionHelpers()
Please sign in to comment.
Something went wrong with that request. Please try again.