/src/main/scala/com/theintelligentbook/ibmodel/mongo/ContentEntry.scala
Scala | 250 lines | 162 code | 50 blank | 38 comment | 7 complexity | 92238dab4b3de7ca635f2a23a3e0de55 MD5 | raw file
- package com.theintelligentbook.ibmodel.mongo
- import com.mongodb.casbah.query.Imports._
- import java.util.Date
- import com.novus.salat._
- import com.novus.salat.global._
- import com.novus.salat.dao.SalatDAO
- import com.wbillingsley.handy._
- import com.novus.salat.annotations._
- case class AboutTarget(
- val ce: Option[ObjectId] = None
- )
- case class ContentEntry (
- val _id: ObjectId = new ObjectId(),
- @Key("book") var _book:Option[ObjectId] = None,
- @Key("addedBy") var _addedBy:Option[ObjectId] = None,
- val kind:String = "unknown",
- var refVal:Option[String] = None,
- var adjectives: Set[String] = Set.empty[String],
- var nouns: Set[String] = Set.empty[String],
- var highlightTopic:Option[String] = None,
- var topics: Set[String] = Set.empty[String],
-
- /* TODO: ContentEntry.refAbout is currently not used or saved.
- val refAbout: Option[AboutTarget] = None, */
- var site:String = "local",
- var name:Option[String] = None,
- @Key("shortDesc") var shortDescription:Option[String] = None,
- var showFirst:Boolean = false,
- var protect:Boolean = false,
- var inTrash:Boolean = false,
- var lastUpdate:Option[Date] = None,
-
- /** These are updated separately in the database */
-
- @Key("ncomments") val commentCount:Int = 0,
- val score:Int = 0,
-
- @Key("nvotes") val voteCount:Int = 0,
- val votes:Seq[Vote] = Seq.empty
-
- // TODO: maybe add metadata
- // TODO: History / provenance (copied from)
- ) extends HasObjectId {
-
- def id = _id
-
- def book = Ref.fromOptionId(classOf[Book], _book)
-
- def addedBy = Ref.fromOptionId(classOf[Reader], _addedBy)
- def containedIn = PresentationDAO.presentationsContainingEntry(RefItself(this))
-
- def touch { lastUpdate = Some(new Date) }
- var isNew = false
-
- def referenceAs[B](c: Class[B]) = Ref.fromOptionId(c, refVal)
-
- /**
- * Comments on ContentEntries are stored in a separate collection.
- * This is essentially because we usually view the content entry
- * without its comments.
- */
- def comments = EntryCommentDAO.findByCE(RefItself(this))
-
- }
- object ContentEntryDAO extends AbstractDAO[ContentEntry]("contentEntry") {
- def newContentEntry(b:Ref[Book], r:Ref[Reader], kind:String) = {
- val cc = new ContentEntry(
- _book = b.getId.asInstanceOf[Option[ObjectId]],
- _addedBy = r.getId.asInstanceOf[Option[ObjectId]],
- kind = kind,
- lastUpdate = Some(new Date)
- )
- cc.isNew = true
- DAO.cache(RefById(classOf[ContentEntry], cc.id), RefItself(cc))
- cc
- }
- def save(ce:ContentEntry) {
- ce.isNew = false
- /*
- * We use an upsert to save, so as not to overwrite new votes with old values
- */
- val u = MongoDBObject("$set" -> MongoDBObject(
- "book" -> ce._book, "addedBy" -> ce._addedBy,
- "kind" -> ce.kind, "refVal" -> ce.refVal, "adjectives" -> ce.adjectives,
- "nouns" -> ce.nouns, "highlightTopic" -> ce.highlightTopic, "topics" -> ce.topics,
- "site" -> ce.site, "name" -> ce.name, "shortDesc" -> ce.shortDescription,
- "showFirst" -> ce.showFirst, "protect" -> ce.protect, "inTrash" -> ce.inTrash,
- "lastUpdate" -> ce.lastUpdate
- ))
- val q = MongoDBObject("_id" -> ce._id)
- DAO.cache(RefById(classOf[ContentEntry], ce.id), RefItself(ce))
- sdao.update(q, u, upsert=true)
- }
- /**
- * Updates the lastUpdate of a content entry to now.
- */
- def touch(ce:Ref[ContentEntry]) {
- ce.getId.foreach { id =>
- sdao.update(MongoDBObject("_id" -> id), $set(Seq("lastUpdate" -> new Date)))
- }
- }
- /**
- * Looks up all the content entries for a given topic noun
- */
- def entriesByTopic(bookRef: Ref[Book], topic:String):Seq[ContentEntry] = {
- bookRef.getId match {
- case Some(bid) => {
- val cursor = sdao.find(MongoDBObject("book" -> bid, "topics" -> topic, "inTrash" -> false)) // TODO check whether we need a $in
- cursor.toSeq
- }
- case _ => Seq.empty[ContentEntry]
- }
- }
- /**
- * Looks up all the content entries for a given book
- */
- def entriesByBook(bookRef: Ref[Book]):Iterator[ContentEntry] = {
- bookRef.getId match {
- case Some(bid) => {
- val cursor = sdao.find(MongoDBObject("book" -> bid, "inTrash" -> false))
- cursor
- }
- case _ => Iterator.empty
- }
- }
- /**
- * Looks up all the content entries that are in the trash
- * @param bookRef
- * @return
- */
- def trashedEntriesByBook(bookRef:Ref[Book]):Iterator[ContentEntry] = {
- bookRef.getId match {
- case Some(bid) => {
- val cursor = sdao.find(MongoDBObject("book" -> bid, "inTrash" -> true))
- cursor
- }
- case _ => Iterator.empty
- }
- }
- /**
- * Constructs and runs a query to select chosen properties of ContentEntries that match specified filters.
- * @return List of Maps
- */
- def queryContentEntries(
- bookRef:Ref[Book], filters: Map[String, Any],
- sort:Option[String]=Some("_id"), descending:Boolean=false,
- max:Option[Int]=None
- ):Iterator[ContentEntry] = {
- bookRef.getId match {
- case Some(bid) => {
- var cursor = sdao.find(Map("book" -> bid, "inTrash" -> false) ++ filters)
- sort.foreach { s=>
- val i = if (descending) -1 else 1
- cursor = cursor.sort(MongoDBObject(s -> i))
- }
- max.foreach { i => cursor.limit(i) }
- cursor
- }
- case _ => Iterator.empty
- }
- }
-
- /**
- * Constructs and runs a query to select chosen properties of ContentEntries that match specified filters.
- * @return List of Maps
- */
- def recentlyUpdated(
- bookRef:Ref[Book], descending:Boolean=true,
- max:Option[Int]=None
- ):Iterator[ContentEntry] = {
- bookRef.getId match {
- case Some(bid) => {
- var cursor = sdao.find(Map("book" -> bid, "inTrash" -> false) ++ ("lastUpdate" $exists true))
- val i = if (descending) -1 else 1
- cursor = cursor.sort(MongoDBObject("lastUpdate" -> i))
- max.foreach { i => cursor.limit(i) }
- cursor
- }
- case _ => Iterator.empty
- }
- }
-
- /**
- * Adds a comment to a content entry
- */
- def addComment(ce:Ref[ContentEntry], addedBy:Ref[Reader], session:Option[String], text:String) {
- for (entry <- ce; b <- entry.book.getId) yield {
- val c = EntryCommentDAO.newEntryComment(ce, entry.book, addedBy, session, text)
- EntryCommentDAO.save(c)
- val update = MongoDBObject("$inc" -> MongoDBObject("ncomments" -> 1))
- val query = MongoDBObject("_id" -> entry.id)
- sdao.update(query, update)
- c
- }
- }
-
- def upVote(ce:Ref[ContentEntry], who:Ref[Reader]) {
- for (ceId <- ce.getId; rId <- who.getId) {
- val v = new Vote(Some(rId), up=true)
- val dbV = grater[Vote].asDBObject(v)
- val update = MongoDBObject("$push" -> MongoDBObject("votes" -> dbV), "$inc" -> MongoDBObject("nvotes" -> 1, "score" -> 1))
- val query = MongoDBObject("_id" -> ceId, "votes.addedBy" -> MongoDBObject("$ne" -> rId))
- sdao.update(query, update)
- }
- }
- def downVote(ce:Ref[ContentEntry], who:Ref[Reader]) {
- for (ceId <- ce.getId; rId <- who.getId) {
- val v = new Vote(Some(rId), up=true)
- val dbV = grater[Vote].asDBObject(v)
- val update = MongoDBObject("$push" -> MongoDBObject("votes" -> dbV), "$inc" -> MongoDBObject("nvotes" -> 1, "score" -> -1))
- val query = MongoDBObject("_id" -> ceId, "votes.addedBy" -> MongoDBObject("$ne" -> rId))
- sdao.update(query, update)
- }
- }
- }