Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactor Collection and Cursors using Abstract types, explicit

'DBObject' version is always returned from DB, Collection etc now.
Those wanting to use typed versions must code the flip around by hand.
  • Loading branch information...
commit ef862e46cc267c81def6f89d5c7f88a5abce0f3c 1 parent 30453c4
@bwmcadams bwmcadams authored
View
8 casbah-core/src/main/scala/Implicits.scala
@@ -84,12 +84,12 @@ trait Implicits {
* Return a type-neutral Scala wrapper object for the DBCollection
* @return MongoCollection An instance of the scala wrapper containing the collection object.
*/
- def asScala = new MongoCollection(coll)
+ def asScala: MongoCollection = new MongoCollection(coll)
/**
* Return a GENERIC Scala wrapper object for the DBCollection specific to a given Parameter type.
* @return MongoCollection[A<:DBObject] An instance of the scala wrapper containing the collection object.
*/
- def asScalaTyped[A <: com.mongodb.DBObject](implicit m: scala.reflect.Manifest[A]) = new MongoTypedCollection[A](coll)
+ def asScalaTyped[A <: com.mongodb.DBObject](implicit m: scala.reflect.Manifest[A]) = new MongoGenericTypedCollection[A](coll)
}
/**
@@ -102,12 +102,12 @@ trait Implicits {
* Return a type-neutral Scala wrapper object for the DBCursor
* @return MongoCursor An instance of the scala wrapper containing the cursor object.
*/
- def asScala = new MongoCursor(cursor)
+ def asScala: MongoCursor = new MongoCursor(cursor)
/**
* Return a GENERIC Scala wrapper object for the DBCursor specific to a given Parameter type.
* @return MongoCursor[A<:DBObject] An instance of the scala wrapper containing the cursor object.
*/
- def asScalaTyped[A <: com.mongodb.DBObject: Manifest] = new MongoTypedCursor[A](cursor)
+ def asScalaTyped[A <: com.mongodb.DBObject: Manifest] = new MongoGenericTypedCursor[A](cursor)
}
implicit def stringAsNamedCollectionMROutput(name: String) = map_reduce.MapReduceStandardOutput(name)
View
41 casbah-core/src/main/scala/MongoCollection.scala
@@ -50,7 +50,9 @@ import collection.mutable.ArrayBuffer
*
* @tparam T (DBObject or subclass thereof)
*/
-trait MongoCollectionBase[T <: DBObject] extends Iterable[T] with Logging { self =>
+trait MongoCollectionBase extends Logging { self =>
+ type T <: DBObject
+ type CursorType
/**
* The underlying Java Mongo Driver Collection object we proxy.
*/
@@ -271,10 +273,6 @@ trait MongoCollectionBase[T <: DBObject] extends Iterable[T] with Logging { self
def findAndRemove[A <% DBObject](query: A) =
_typedValue(underlying.findAndRemove(query))
- override def head = headOption.get
- override def headOption = findOne
- override def tail = find.skip(1).toList
-
/**
* write concern aware write op block.
*
@@ -470,7 +468,7 @@ trait MongoCollectionBase[T <: DBObject] extends Iterable[T] with Logging { self
*/
def setObjectClass[A <: DBObject: Manifest](c: Class[A]) = {
underlying.setObjectClass(c)
- new MongoTypedCollection[A](underlying = self.underlying)
+ new MongoGenericTypedCollection[A](underlying = self.underlying)
}
/**
@@ -717,7 +715,7 @@ trait MongoCollectionBase[T <: DBObject] extends Iterable[T] with Logging { self
* @return if the two collections are the same object
*/
override def equals(obj: Any) = obj match {
- case other: MongoCollectionBase[_] => underlying.equals(other.underlying)
+ case other: MongoCollectionBase => underlying.equals(other.underlying)
case _ => false
}
@@ -875,7 +873,7 @@ trait MongoCollectionBase[T <: DBObject] extends Iterable[T] with Logging { self
* @param cursor (DBCursor)
* @return (MongoCursorBase)
*/
- def _newCursor(cursor: DBCursor): MongoCursorBase[T]
+ def _newCursor(cursor: DBCursor): CursorType
/**
* _newInstance
@@ -888,7 +886,7 @@ trait MongoCollectionBase[T <: DBObject] extends Iterable[T] with Logging { self
* @param cursor (DBCollection)
* @return (this.type)
*/
- def _newInstance(collection: DBCollection): MongoCollectionBase[T]
+ def _newInstance(collection: DBCollection): MongoCollectionBase
protected def _typedValue(dbObj: DBObject): Option[T] = Option(dbObj.asInstanceOf[T])
}
@@ -903,7 +901,10 @@ trait MongoCollectionBase[T <: DBObject] extends Iterable[T] with Logging { self
*
* @tparam DBObject
*/
-class MongoCollection(val underlying: DBCollection) extends MongoCollectionBase[DBObject] {
+class MongoCollection(val underlying: DBCollection) extends MongoCollectionBase with Iterable[DBObject] {
+
+ type T = DBObject
+ type CursorType = MongoCursor
/**
* _newCursor
@@ -930,10 +931,14 @@ class MongoCollection(val underlying: DBCollection) extends MongoCollectionBase[
* @param cursor (DBCollection)
* @return (this.type)
*/
- def _newInstance(collection: DBCollection) = new MongoCollection(collection)
+ def _newInstance(collection: DBCollection): MongoCollection = new MongoCollection(collection)
override protected def _typedValue(dbObj: DBObject): Option[DBObject] = Option(dbObj)
+ override def head = headOption.get
+ override def headOption = findOne
+ override def tail = find.skip(1).toStream
+
}
/**
@@ -947,7 +952,13 @@ class MongoCollection(val underlying: DBCollection) extends MongoCollectionBase[
* @param val underlying (DBCollection)
* @tparam T A Subclass of DBObject
*/
-class MongoTypedCollection[T <: DBObject: Manifest](val underlying: DBCollection) extends MongoCollectionBase[T] {
+trait MongoTypedCollection extends MongoCollectionBase {
+
+}
+
+class MongoGenericTypedCollection[A <: DBObject](val underlying: DBCollection) extends MongoTypedCollection {
+ type T = A
+ type CursorType = MongoGenericTypedCursor[A]
/**
* _newCursor
@@ -959,9 +970,9 @@ class MongoTypedCollection[T <: DBObject: Manifest](val underlying: DBCollection
* Should figure out the right type to return based on typing setup.
*
* @param cursor (DBCursor)
- * @return (MongoCursorBase)
+ * @return (MongoCollectionBase)
*/
- def _newCursor(cursor: DBCursor) = new MongoTypedCursor[T](cursor)
+ def _newCursor(cursor: DBCursor) = new MongoGenericTypedCursor[T](cursor)
/**
* _newInstance
@@ -974,7 +985,7 @@ class MongoTypedCollection[T <: DBObject: Manifest](val underlying: DBCollection
* @param cursor (DBCollection)
* @return (this.type)
*/
- def _newInstance(collection: DBCollection) = new MongoTypedCollection[T](collection)
+ def _newInstance(collection: DBCollection) = new MongoGenericTypedCollection[T](collection)
}
/** Helper object for some static methods
View
64 casbah-core/src/main/scala/MongoCursor.scala
@@ -42,7 +42,9 @@ import scalaj.collection.Imports._
*
* @tparam T (DBObject or subclass thereof)
*/
-trait MongoCursorBase[T <: DBObject] extends Iterator[T] with Logging {
+trait MongoCursorBase extends Logging {
+
+ type T <: DBObject
val underlying: DBCursor
@@ -106,25 +108,6 @@ trait MongoCursorBase[T <: DBObject] extends Iterator[T] with Logging {
def count = underlying.count
/**
- * size
- *
- * The DBCursor's count of elements in the query,
- * AFTER the application of skip/limit, passed through
- * from the Java object.
- *
- * <b>NOTE:</b> size() takes into account any skip/limit settings on a cursor;
- * it is the size of just the window.
- * If you want to get a count of the entire query ignoring skip/limit
- * you must use count()
- *
- * @see count()
- *
- * @return Int indicating the number of elements returned by the query after skip/limit
- * @throws MongoException
- */
- override def size = underlying.size
-
- /**
* Manipulate Query Options
*
* Adds an option - see Bytes.QUERYOPTION_* for list
@@ -485,7 +468,7 @@ trait MongoCursorBase[T <: DBObject] extends Iterator[T] with Logging {
* @param cursor (DBCursor)
* @return (this.type)
*/
- def _newInstance(cursor: DBCursor): MongoCursorBase[T]
+ def _newInstance(cursor: DBCursor): MongoCursorBase
/**
* copy
@@ -496,7 +479,7 @@ trait MongoCursorBase[T <: DBObject] extends Iterator[T] with Logging {
*
* @return The new cursor
*/
- def copy(): MongoCursorBase[T] = _newInstance(underlying.copy()) // parens for side-effects
+ def copy(): MongoCursorBase = _newInstance(underlying.copy()) // parens for side-effects
}
@@ -511,9 +494,29 @@ trait MongoCursorBase[T <: DBObject] extends Iterator[T] with Logging {
* @param val underlying (com.mongodb.DBCollection)
* @tparam DBObject
*/
-class MongoCursor(val underlying: DBCursor) extends MongoCursorBase[DBObject] {
+class MongoCursor(val underlying: DBCursor) extends MongoCursorBase with Iterator[DBObject] {
+
+ type T = DBObject
/**
+ * size
+ *
+ * The DBCursor's count of elements in the query,
+ * AFTER the application of skip/limit, passed through
+ * from the Java object.
+ *
+ * <b>NOTE:</b> size() takes into account any skip/limit settings on a cursor;
+ * it is the size of just the window.
+ * If you want to get a count of the entire query ignoring skip/limit
+ * you must use count()
+ *
+ * @see count()
+ *
+ * @return Int indicating the number of elements returned by the query after skip/limit
+ * @throws MongoException
+ */
+ override def size = underlying.size
+ /**
* _newInstance
*
* Utility method which concrete subclasses
@@ -547,14 +550,14 @@ object MongoCursor extends Logging {
* @param keys (K) Keys to return from the query
* @return (instance) A new MongoCursor
*/
- def apply[T <: DBObject: Manifest](collection: MongoCollectionBase[T], query: DBObject,
+ def apply[T <: DBObject: Manifest](collection: MongoCollectionBase, query: DBObject,
keys: DBObject) = {
val cursor = new DBCursor(collection.underlying, query, keys)
if (manifest[T] == manifest[DBObject])
new MongoCursor(cursor)
else
- new MongoTypedCursor[T](cursor)
+ new MongoGenericTypedCursor[T](cursor)
}
}
@@ -568,9 +571,10 @@ object MongoCursor extends Logging {
* @since 1.0
*
* @param val underlying (com.mongodb.DBCollection)
- * @tparam T A Subclass of DBObject
+ * @tparam A A Subclass of DBObject
*/
-class MongoTypedCursor[T <: DBObject: Manifest](val underlying: DBCursor) extends MongoCursorBase[T] {
+class MongoGenericTypedCursor[A <: DBObject](val underlying: DBCursor) extends MongoCursorBase {
+ type T = A
/**
* _newInstance
@@ -583,7 +587,7 @@ class MongoTypedCursor[T <: DBObject: Manifest](val underlying: DBCursor) extend
* @param cursor (DBCursor)
* @return (this.type)
*/
- def _newInstance(cursor: DBCursor) = new MongoTypedCursor[T](cursor)
+ def _newInstance(cursor: DBCursor) = new MongoGenericTypedCursor[T](cursor)
/**
* copy
@@ -594,10 +598,8 @@ class MongoTypedCursor[T <: DBObject: Manifest](val underlying: DBCursor) extend
*
* @return The new cursor
*/
- override def copy(): MongoTypedCursor[T] = _newInstance(underlying.copy()) // parens for side-effects
-
+ override def copy(): MongoGenericTypedCursor[T] = _newInstance(underlying.copy()) // parens for side-effects
}
-
/**
*
*
View
16 casbah-core/src/main/scala/MongoDB.scala
@@ -59,21 +59,7 @@ class MongoDB(val underlying: com.mongodb.DB) {
* @param collection a string for the collection name
* @return MongoCollection A wrapped instance of a Mongo DBCollection Class returning generic DBObjects
*/
- def apply(collection: String) = underlying.getCollection(collection).asScala
- /**
- * Parameterized apply method to proxy getCollection, to allow invocation of
- * <code>dbInstance("collectionName")</code>
- * instead of getCollection
- *
- * This returns a Type-specific Collection wrapper, and requires the ability to either implicitly determine a manifest,
- * or that you explicitly pass it where necessary to use it. It should find things on it's own in most cases
- * but the compiler will tell you if not.
- *
- * @param collection a string for the collection name
- * @param clazz Class[A] where A is the Subclass of DBOBject you wish to work with for this collection
- * @return MongoCollection A wrapped instance of a Mongo DBCollection Class returning DBObject subclasses of type A
- */
- def apply[A <: DBObject](collection: String, clazz: Class[A])(implicit m: scala.reflect.Manifest[A]) = underlying.getCollection(collection).asScalaTyped(m)
+ def apply(collection: String): MongoCollection = underlying.getCollection(collection).asScala
def addUser(username: String, passwd: String) = underlying.addUser(username, passwd.toArray)
View
2  casbah-core/src/test/scala/CoreWrappersSpec.scala
@@ -196,11 +196,9 @@ class CoreWrappersSpec extends Specification with PendingUntilFixed with Logging
"Chain operations must return the proper *subtype*" in {
val cur = coll.find(MongoDBObject("foo" -> "bar")) skip 5
cur must haveClass[MongoCursor]
- cur must haveSuperClass[MongoCursorBase[DBObject]]
val cur2 = coll.find(MongoDBObject("foo" -> "bar")) limit 25 skip 12
cur2 must haveClass[MongoCursor]
- cur2 must haveSuperClass[MongoCursorBase[DBObject]]
}
View
1  casbah-core/src/test/scala/MapReduceSpec.scala
@@ -125,7 +125,6 @@ class MapReduceSpec extends Specification with PendingUntilFixed with Logging {
result.isError must beFalse
result.raw.getAs[String]("result") must beNone
result.size must beGreaterThan(0)
- log.warn("Result.size: %s Counts.output: %s", result.size, result.raw.expand[Int]("counts.output"))
result.size must beEqualTo(result.raw.expand[Int]("counts.output").getOrElse(-1))
val item = result.next
Please sign in to comment.
Something went wrong with that request. Please try again.