PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/web-core/app/models/MetadataCache.scala

https://github.com/delving/culture-hub
Scala | 124 lines | 85 code | 27 blank | 12 comment | 4 complexity | 01905cced03f14e3fdcc9a4ab8c88253 MD5 | raw file
  1. package models
  2. import _root_.util.OrganizationConfigurationHandler
  3. import com.mongodb.casbah.Imports._
  4. import core.{ ItemType, SystemField }
  5. import org.bson.types.ObjectId
  6. import HubMongoContext._
  7. import com.novus.salat.dao.SalatDAO
  8. import java.util.Date
  9. import scala.collection.JavaConverters._
  10. /**
  11. * A generic MetadataItem. The source data is meant to be kept as raw XML documents, for one or multiple versioned schemas.
  12. *
  13. * @author Manuel Bernhardt <bernhardt.manuel@gmail.com>
  14. */
  15. case class MetadataItem(modified: Date = new Date(),
  16. collection: String,
  17. itemType: String,
  18. itemId: String,
  19. xml: Map[String, String], // schemaPrefix -> raw XML string
  20. schemaVersions: Map[String, String], // schemaPrefix -> schemaVersion
  21. index: Int,
  22. invalidTargetSchemas: Seq[String] = Seq.empty,
  23. systemFields: Map[String, List[String]] = Map.empty) {
  24. def getSystemFieldValues(field: SystemField): Seq[String] = {
  25. systemFields.get(field.tag).getOrElse(new BasicDBList).asInstanceOf[BasicDBList].asScala.map(_.toString).toSeq
  26. }
  27. }
  28. object MetadataCache {
  29. def getMongoCollectionName(orgId: String) = "%s_MetadataCache".format(orgId)
  30. def get(orgId: String, col: String, itemType: ItemType): core.MetadataCache = get(orgId, col, itemType.itemType)
  31. def get(orgId: String, col: String, itemType: String): core.MetadataCache = {
  32. val configuration = OrganizationConfigurationHandler.getByOrgId(orgId)
  33. val mongoConnection = mongoConnections.getResource(configuration)
  34. // manu, 20.02.2012 - I'm fully aware that this may eventually lead to lost cached records
  35. // but a better fix involving batch inserts will eventually come later
  36. // manu, 16.03.2014 - commenting out the WriteConcern FsyncSafe as it leads to extremely slow writes (of the order of 100 ms / record)
  37. // mongoConnection.setWriteConcern(WriteConcern.FsyncSafe)
  38. val mongoCollection: MongoCollection = mongoConnection(getMongoCollectionName(configuration.orgId))
  39. // manu, 16.03.2014 - commenting out the WriteConcern FsyncSafe as it leads to extremely slow writes (of the order of 100 ms / record)
  40. // mongoCollection.setWriteConcern(WriteConcern.JournalSafe)
  41. mongoCollection.ensureIndex(MongoDBObject("collection" -> 1, "itemType" -> 1, "itemId" -> 1))
  42. mongoCollection.ensureIndex(MongoDBObject("collection" -> 1, "itemType" -> 1))
  43. mongoCollection.ensureIndex(MongoDBObject("collection" -> 1, "itemType" -> 1, "index" -> 1))
  44. new MongoMetadataCache(orgId, col, itemType, mongoCollection)
  45. }
  46. def getItemTypes(orgId: String, col: String): Seq[ItemType] = {
  47. val configuration = OrganizationConfigurationHandler.getByOrgId(orgId)
  48. val mongoConnection = mongoConnections.getResource(configuration)
  49. val mongoCollection: MongoCollection = mongoConnection(getMongoCollectionName(configuration.orgId))
  50. val types: Seq[Any] = mongoCollection.distinct("itemType", MongoDBObject("collection" -> col))
  51. types.map(t => ItemType(t.toString))
  52. }
  53. }
  54. class MongoMetadataCache(orgId: String, col: String, itemType: String, mongoCollection: MongoCollection) extends SalatDAO[MetadataItem, ObjectId](mongoCollection) with core.MetadataCache {
  55. def underlying: MongoMetadataCache = this
  56. def saveOrUpdate(item: MetadataItem) {
  57. val mappings = item.xml.foldLeft(MongoDBObject()) { (r, c) => r + (c._1 -> c._2) }
  58. val schemaVersions = item.schemaVersions.foldLeft(MongoDBObject()) { (r, c) => r + (c._1 -> c._2) }
  59. update(
  60. q = MongoDBObject("collection" -> item.collection, "itemType" -> item.itemType, "itemId" -> item.itemId),
  61. o = $set(
  62. "modified" -> new Date(),
  63. "collection" -> item.collection,
  64. "itemType" -> item.itemType,
  65. "itemId" -> item.itemId,
  66. "index" -> item.index,
  67. "systemFields" -> item.systemFields.asDBObject,
  68. "xml" -> mappings,
  69. "schemaVersions" -> schemaVersions
  70. ),
  71. upsert = true
  72. )
  73. }
  74. def iterate(index: Int = 0, limit: Option[Int], from: Option[Date] = None, until: Option[Date] = None, metadataPrefix: Option[String] = None): Iterator[MetadataItem] = {
  75. // the use of index here is totally wrong when using metadataPrefix
  76. val query = MongoDBObject("collection" -> col, "itemType" -> itemType) ++ ("index" $gt index)
  77. val fromQuery = from.map { f => ("modified" $gte f) }
  78. val untilQuery = until.map { u => ("modified" $lte u) }
  79. val metadataPrefixQuery = metadataPrefix.map { prefix => (s"xml.$prefix" $exists true) }
  80. val q = Seq(fromQuery, untilQuery, metadataPrefixQuery).foldLeft(query) { (c, r) =>
  81. if (r.isDefined) c ++ r.get else c
  82. }
  83. val cursor = find(q).sort(MongoDBObject("index" -> 1))
  84. if (limit.isDefined) {
  85. cursor.limit(limit.get)
  86. } else {
  87. cursor
  88. }
  89. }
  90. def list(index: Int = 0, limit: Option[Int], from: Option[Date] = None, until: Option[Date] = None): List[MetadataItem] = iterate(index, limit, from, until).toList
  91. def listByMetadataPrefix(index: Int = 0, limit: Option[Int], from: Option[Date] = None, until: Option[Date] = None, metadataPrefix: Option[String] = None): List[MetadataItem] = iterate(index, limit, from, until, metadataPrefix).toList
  92. def count(): Long = count(MongoDBObject("collection" -> col, "itemType" -> itemType))
  93. def findOne(itemId: String): Option[MetadataItem] = findOne(MongoDBObject("collection" -> col, "itemType" -> itemType, "itemId" -> itemId))
  94. def findMany(itemIds: Seq[String]): Seq[MetadataItem] = find(MongoDBObject("collection" -> col, "itemType" -> itemType) ++ ("itemId" $in itemIds)).toSeq
  95. def remove(itemId: String) { remove(MongoDBObject("collection" -> col, "itemId" -> itemId)) }
  96. def removeAll() { remove(MongoDBObject("collection" -> col, "itemType" -> itemType)) }
  97. }