PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/scala/com/theintelligentbook/ibmodel/mongo/ContentEntry.scala

https://bitbucket.org/wbillingsley/ibmongo-2012-old-version-duct-tape-not-maintained
Scala | 250 lines | 162 code | 50 blank | 38 comment | 7 complexity | 92238dab4b3de7ca635f2a23a3e0de55 MD5 | raw file
  1. package com.theintelligentbook.ibmodel.mongo
  2. import com.mongodb.casbah.query.Imports._
  3. import java.util.Date
  4. import com.novus.salat._
  5. import com.novus.salat.global._
  6. import com.novus.salat.dao.SalatDAO
  7. import com.wbillingsley.handy._
  8. import com.novus.salat.annotations._
  9. case class AboutTarget(
  10. val ce: Option[ObjectId] = None
  11. )
  12. case class ContentEntry (
  13. val _id: ObjectId = new ObjectId(),
  14. @Key("book") var _book:Option[ObjectId] = None,
  15. @Key("addedBy") var _addedBy:Option[ObjectId] = None,
  16. val kind:String = "unknown",
  17. var refVal:Option[String] = None,
  18. var adjectives: Set[String] = Set.empty[String],
  19. var nouns: Set[String] = Set.empty[String],
  20. var highlightTopic:Option[String] = None,
  21. var topics: Set[String] = Set.empty[String],
  22. /* TODO: ContentEntry.refAbout is currently not used or saved.
  23. val refAbout: Option[AboutTarget] = None, */
  24. var site:String = "local",
  25. var name:Option[String] = None,
  26. @Key("shortDesc") var shortDescription:Option[String] = None,
  27. var showFirst:Boolean = false,
  28. var protect:Boolean = false,
  29. var inTrash:Boolean = false,
  30. var lastUpdate:Option[Date] = None,
  31. /** These are updated separately in the database */
  32. @Key("ncomments") val commentCount:Int = 0,
  33. val score:Int = 0,
  34. @Key("nvotes") val voteCount:Int = 0,
  35. val votes:Seq[Vote] = Seq.empty
  36. // TODO: maybe add metadata
  37. // TODO: History / provenance (copied from)
  38. ) extends HasObjectId {
  39. def id = _id
  40. def book = Ref.fromOptionId(classOf[Book], _book)
  41. def addedBy = Ref.fromOptionId(classOf[Reader], _addedBy)
  42. def containedIn = PresentationDAO.presentationsContainingEntry(RefItself(this))
  43. def touch { lastUpdate = Some(new Date) }
  44. var isNew = false
  45. def referenceAs[B](c: Class[B]) = Ref.fromOptionId(c, refVal)
  46. /**
  47. * Comments on ContentEntries are stored in a separate collection.
  48. * This is essentially because we usually view the content entry
  49. * without its comments.
  50. */
  51. def comments = EntryCommentDAO.findByCE(RefItself(this))
  52. }
  53. object ContentEntryDAO extends AbstractDAO[ContentEntry]("contentEntry") {
  54. def newContentEntry(b:Ref[Book], r:Ref[Reader], kind:String) = {
  55. val cc = new ContentEntry(
  56. _book = b.getId.asInstanceOf[Option[ObjectId]],
  57. _addedBy = r.getId.asInstanceOf[Option[ObjectId]],
  58. kind = kind,
  59. lastUpdate = Some(new Date)
  60. )
  61. cc.isNew = true
  62. DAO.cache(RefById(classOf[ContentEntry], cc.id), RefItself(cc))
  63. cc
  64. }
  65. def save(ce:ContentEntry) {
  66. ce.isNew = false
  67. /*
  68. * We use an upsert to save, so as not to overwrite new votes with old values
  69. */
  70. val u = MongoDBObject("$set" -> MongoDBObject(
  71. "book" -> ce._book, "addedBy" -> ce._addedBy,
  72. "kind" -> ce.kind, "refVal" -> ce.refVal, "adjectives" -> ce.adjectives,
  73. "nouns" -> ce.nouns, "highlightTopic" -> ce.highlightTopic, "topics" -> ce.topics,
  74. "site" -> ce.site, "name" -> ce.name, "shortDesc" -> ce.shortDescription,
  75. "showFirst" -> ce.showFirst, "protect" -> ce.protect, "inTrash" -> ce.inTrash,
  76. "lastUpdate" -> ce.lastUpdate
  77. ))
  78. val q = MongoDBObject("_id" -> ce._id)
  79. DAO.cache(RefById(classOf[ContentEntry], ce.id), RefItself(ce))
  80. sdao.update(q, u, upsert=true)
  81. }
  82. /**
  83. * Updates the lastUpdate of a content entry to now.
  84. */
  85. def touch(ce:Ref[ContentEntry]) {
  86. ce.getId.foreach { id =>
  87. sdao.update(MongoDBObject("_id" -> id), $set(Seq("lastUpdate" -> new Date)))
  88. }
  89. }
  90. /**
  91. * Looks up all the content entries for a given topic noun
  92. */
  93. def entriesByTopic(bookRef: Ref[Book], topic:String):Seq[ContentEntry] = {
  94. bookRef.getId match {
  95. case Some(bid) => {
  96. val cursor = sdao.find(MongoDBObject("book" -> bid, "topics" -> topic, "inTrash" -> false)) // TODO check whether we need a $in
  97. cursor.toSeq
  98. }
  99. case _ => Seq.empty[ContentEntry]
  100. }
  101. }
  102. /**
  103. * Looks up all the content entries for a given book
  104. */
  105. def entriesByBook(bookRef: Ref[Book]):Iterator[ContentEntry] = {
  106. bookRef.getId match {
  107. case Some(bid) => {
  108. val cursor = sdao.find(MongoDBObject("book" -> bid, "inTrash" -> false))
  109. cursor
  110. }
  111. case _ => Iterator.empty
  112. }
  113. }
  114. /**
  115. * Looks up all the content entries that are in the trash
  116. * @param bookRef
  117. * @return
  118. */
  119. def trashedEntriesByBook(bookRef:Ref[Book]):Iterator[ContentEntry] = {
  120. bookRef.getId match {
  121. case Some(bid) => {
  122. val cursor = sdao.find(MongoDBObject("book" -> bid, "inTrash" -> true))
  123. cursor
  124. }
  125. case _ => Iterator.empty
  126. }
  127. }
  128. /**
  129. * Constructs and runs a query to select chosen properties of ContentEntries that match specified filters.
  130. * @return List of Maps
  131. */
  132. def queryContentEntries(
  133. bookRef:Ref[Book], filters: Map[String, Any],
  134. sort:Option[String]=Some("_id"), descending:Boolean=false,
  135. max:Option[Int]=None
  136. ):Iterator[ContentEntry] = {
  137. bookRef.getId match {
  138. case Some(bid) => {
  139. var cursor = sdao.find(Map("book" -> bid, "inTrash" -> false) ++ filters)
  140. sort.foreach { s=>
  141. val i = if (descending) -1 else 1
  142. cursor = cursor.sort(MongoDBObject(s -> i))
  143. }
  144. max.foreach { i => cursor.limit(i) }
  145. cursor
  146. }
  147. case _ => Iterator.empty
  148. }
  149. }
  150. /**
  151. * Constructs and runs a query to select chosen properties of ContentEntries that match specified filters.
  152. * @return List of Maps
  153. */
  154. def recentlyUpdated(
  155. bookRef:Ref[Book], descending:Boolean=true,
  156. max:Option[Int]=None
  157. ):Iterator[ContentEntry] = {
  158. bookRef.getId match {
  159. case Some(bid) => {
  160. var cursor = sdao.find(Map("book" -> bid, "inTrash" -> false) ++ ("lastUpdate" $exists true))
  161. val i = if (descending) -1 else 1
  162. cursor = cursor.sort(MongoDBObject("lastUpdate" -> i))
  163. max.foreach { i => cursor.limit(i) }
  164. cursor
  165. }
  166. case _ => Iterator.empty
  167. }
  168. }
  169. /**
  170. * Adds a comment to a content entry
  171. */
  172. def addComment(ce:Ref[ContentEntry], addedBy:Ref[Reader], session:Option[String], text:String) {
  173. for (entry <- ce; b <- entry.book.getId) yield {
  174. val c = EntryCommentDAO.newEntryComment(ce, entry.book, addedBy, session, text)
  175. EntryCommentDAO.save(c)
  176. val update = MongoDBObject("$inc" -> MongoDBObject("ncomments" -> 1))
  177. val query = MongoDBObject("_id" -> entry.id)
  178. sdao.update(query, update)
  179. c
  180. }
  181. }
  182. def upVote(ce:Ref[ContentEntry], who:Ref[Reader]) {
  183. for (ceId <- ce.getId; rId <- who.getId) {
  184. val v = new Vote(Some(rId), up=true)
  185. val dbV = grater[Vote].asDBObject(v)
  186. val update = MongoDBObject("$push" -> MongoDBObject("votes" -> dbV), "$inc" -> MongoDBObject("nvotes" -> 1, "score" -> 1))
  187. val query = MongoDBObject("_id" -> ceId, "votes.addedBy" -> MongoDBObject("$ne" -> rId))
  188. sdao.update(query, update)
  189. }
  190. }
  191. def downVote(ce:Ref[ContentEntry], who:Ref[Reader]) {
  192. for (ceId <- ce.getId; rId <- who.getId) {
  193. val v = new Vote(Some(rId), up=true)
  194. val dbV = grater[Vote].asDBObject(v)
  195. val update = MongoDBObject("$push" -> MongoDBObject("votes" -> dbV), "$inc" -> MongoDBObject("nvotes" -> 1, "score" -> -1))
  196. val query = MongoDBObject("_id" -> ceId, "votes.addedBy" -> MongoDBObject("$ne" -> rId))
  197. sdao.update(query, update)
  198. }
  199. }
  200. }