Permalink
Browse files

- Backport of MongoDBObject related changes related to typing from 1.…

…1 development

- Inclusion of Specs, with backport of MongoDBObjectSpec from 1.1 branch
- Improvement of type returns from MongoDBObject
    * Builder and Factory now ALWAYS return a DBObject which makes more sense
  • Loading branch information...
1 parent 8305d63 commit b69511c439318b0c760755dc9c5b97499097d7f7 @bwmcadams bwmcadams committed Aug 29, 2010
@@ -6,6 +6,8 @@ class CasbahProject(info: ProjectInfo) extends DefaultProject(info) with rsync.R
val scalaTime = "org.scala-tools" % "time" % "2.8.0-0.2-SNAPSHOT"
val configgy = "net.lag" % "configgy_2.8.0" % "1.5.2"
+
+ val specs = "org.scala-tools.testing" %% "specs" % "1.6.5" % "test->default"
val scalatest = "org.scalatest" % "scalatest" % "1.2-for-scala-2.8.0.final-SNAPSHOT" % "test"
val scalajCollection = "org.scalaj" % "scalaj-collection_2.8.0" % "1.0"
@@ -41,7 +41,7 @@ import scala.reflect._
* due to conflicts between the java methods and scala methods.
* Implicits and explicit methods allow you to convert to java though.
*
- * This is a very crappy, thin interface and likely to go away. Use it at your own risk.
+ * We will likely reimplement DBObject itself longterm as a pure base. on the wire format
* @author Brendan W. McAdams <bmcadams@novus.com>
* @version 1.0, 06/02/10
* @since 1.0
@@ -63,7 +63,7 @@ trait MongoDBObject extends Map[String, AnyRef] with Logging {
/** Lazy utility method to allow typing without conflicting with Map's required get() method and causing ambiguity */
- def getAs[A <% AnyRef : Manifest](key: String): Option[A] = {
+ def getAs[A <: Any : Manifest](key: String): Option[A] = {
require(manifest[A] != manifest[scala.Nothing], "Type inference failed; getAs[A]() requires an explicit type argument (e.g. dbObject[<ReturnType](\"someKey\") ) to function correctly.")
underlying.get(key) match {
case null => None
@@ -78,12 +78,12 @@ trait MongoDBObject extends Map[String, AnyRef] with Logging {
* Your type parameter must be that of the item at the bottom of the tree you specify...
* If cast fails - it's your own fault.
*/
- def expand[A <% AnyRef : Manifest](key: String): Option[A] = {
+ def expand[A <: Any : Manifest](key: String): Option[A] = {
require(manifest[A] != manifest[scala.Nothing], "Type inference failed; expand[A]() requires an explicit type argument (e.g. dbObject[<ReturnType](\"someKey\") ) to function correctly.")
- @tailrec def _dot(dbObj: DBObject, key: String): Option[DBObject] =
+ @tailrec def _dot(dbObj: MongoDBObject, key: String): Option[_] =
if (key.indexOf('.') < 0) {
log.trace("_dot returning on key '%s'", key)
- dbObj.getAs[DBObject](key)
+ dbObj.getAs[AnyRef](key)
}
else {
val (pfx, sfx) = key.splitAt(key.indexOf('.'))
@@ -139,15 +139,15 @@ trait MongoDBObject extends Map[String, AnyRef] with Logging {
object MongoDBObject {
- def empty = new MongoDBObject { val underlying = new BasicDBObject }
+ def empty: DBObject = new MongoDBObject { val underlying = new BasicDBObject }
- def apply[A <: String, B <: Any](elems: (A, B)*) = (newBuilder[A, B] ++= elems).result
+ def apply[A <: String, B <: Any](elems: (A, B)*): DBObject = (newBuilder[A, B] ++= elems).result
def newBuilder[A <: String, B <: Any]: MongoDBObjectBuilder = new MongoDBObjectBuilder
}
-protected[mongodb] class MongoDBObjectBuilder extends scala.collection.mutable.Builder[(String, Any), MongoDBObject] {
+sealed class MongoDBObjectBuilder extends scala.collection.mutable.Builder[(String, Any), DBObject] {
protected val empty = BasicDBObjectBuilder.start
protected var elems = empty
override def +=(x: (String, Any)) = {
@@ -156,7 +156,7 @@ protected[mongodb] class MongoDBObjectBuilder extends scala.collection.mutable.B
}
def clear() { elems = empty }
- def result = new MongoDBObject { val underlying = elems.get }
+ def result: DBObject = new MongoDBObject { val underlying = elems.get }
}
// vim: set ts=2 sw=2 sts=2 et:
@@ -53,7 +53,7 @@ trait BarewordQueryOperator extends Logging {
log.trace("Apply - %s", fields)
val bldr = MongoDBObject.newBuilder
for ((k, v) <- fields) bldr += k -> v
- MongoDBObject(oper -> bldr.result.asDBObject).asDBObject
+ MongoDBObject(oper -> bldr.result)
}
}
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2009, 2010 Novus Partners, Inc. <http://novus.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.
+ *
+ * For questions and comments about this product, please see the project page at:
+ *
+ * http://github.com/novus/casbah
+ *
+ */
+
+package com.novus.casbah
+package mongodb
+package test
+
+import com.novus.casbah.mongodb.Imports._
+
+
+import org.specs._
+import org.specs.specification.PendingUntilFixed
+
+class MongoDBObjectSpec extends Specification with PendingUntilFixed {
+ "MongoDBObject expand operations" should {
+ shareVariables()
+
+ val x: DBObject = MongoDBObject("A" -> MongoDBObject("B" -> "C"))
+ val y: DBObject = MongoDBObject("A" -> MongoDBObject("B" -> MongoDBObject("C" -> 5)))
+ val z: DBObject = MongoDBObject("A" -> MongoDBObject("B" -> MongoDBObject("C" -> List(5, 4, 3, 2, 1))))
+
+ "Expanding a simple layering should work" in {
+ val b = x.expand[String]("A.B")
+ b must beSome("C")
+
+ "While overexpanding should probably fail" in {
+ lazy val bFail = x.expand[String]("A.B.C")
+ bFail must throwA[ClassCastException]
+ }
+ }
+
+ "Expanding a further layering should work" in {
+ // TODO - This is way broken as far as casting to int
+ val c = y.expand[Int]("A.B.C")
+ c must beSome(5)
+ "While overexpanding should probably fail" in {
+ lazy val cFail = y.expand[String]("A.B.C.D")
+ cFail must throwA[ClassCastException]
+ }
+ }
+
+ "And you can go further and even get a list" in {
+ // TODO - This is way broken as far as casting to int
+ val c = z.expand[List[_]]("A.B.C")
+ c must beSome(List(5, 4, 3, 2, 1))
+ }
+ }
+
+ "MongoDBObject issues reported by users" should {
+ "Not break like tommy chheng reported" in {
+ lazy val universityDB = MongoConnection()("test")("universities")
+
+ val q = MongoDBObject.empty
+
+ val fields = MongoDBObject("name" -> 1)
+ for(university <- universityDB.find(q, fields)) {
+ println(university)
+ }
+
+ // Simple test of Is it a DBObject?
+ q must haveSuperClass[DBObject]
+ fields must haveSuperClass[DBObject]
+ }
+ }
+}
+
+
+// vim: set ts=2 sw=2 sts=2 et:

0 comments on commit b69511c

Please sign in to comment.