PageRenderTime 142ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/net.modelbased.sensapp.library.datastore/src/main/scala/net/modelbased/sensapp/library/datastore/DataStoreOperations.scala

https://github.com/SINTEF-9012/sensapp
Scala | 181 lines | 51 code | 13 blank | 117 comment | 2 complexity | 90ae597b1e8c46caef962059bb683aeb MD5 | raw file
  1. /**
  2. * ====
  3. * This file is part of SensApp [ http://sensapp.modelbased.net ]
  4. *
  5. * Copyright (C) 2011- SINTEF ICT
  6. * Contact: SINTEF ICT <nicolas.ferry@sintef.no>
  7. *
  8. * Module: net.modelbased.sensapp
  9. *
  10. * SensApp is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Lesser General Public License as
  12. * published by the Free Software Foundation, either version 3 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * SensApp is distributed in the hope that it will be useful, but
  16. * WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General
  21. * Public License along with SensApp. If not, see
  22. * <http://www.gnu.org/licenses/>.
  23. * ====
  24. *
  25. * This file is part of SensApp [ http://sensapp.modelbased.net ]
  26. *
  27. * Copyright (C) 2012- SINTEF ICT
  28. * Contact: SINTEF ICT <nicolas.ferry@sintef.no>
  29. *
  30. * Module: net.modelbased.sensapp.library.datastore
  31. *
  32. * SensApp is free software: you can redistribute it and/or modify
  33. * it under the terms of the GNU Lesser General Public License as
  34. * published by the Free Software Foundation, either version 3 of
  35. * the License, or (at your option) any later version.
  36. *
  37. * SensApp is distributed in the hope that it will be useful, but
  38. * WITHOUT ANY WARRANTY; without even the implied warranty of
  39. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  40. * GNU Lesser General Public License for more details.
  41. *
  42. * You should have received a copy of the GNU Lesser General
  43. * Public License along with SensApp. If not, see
  44. * <http://www.gnu.org/licenses/>.
  45. */
  46. package net.modelbased.sensapp.library.datastore
  47. import com.mongodb.casbah.Imports._
  48. import com.mongodb.casbah.commons.MongoDBObjectBuilder
  49. import com.mongodb.util.JSON
  50. /**
  51. * This trait defines manipulations used to manipulate DataStore Elements
  52. *
  53. * @author Sebastien Mosser
  54. *
  55. * @param T the type of the elements stored in the DataStore
  56. */
  57. trait DataStoreOperations[T] extends DataSpecific[T] {
  58. /**
  59. * the exists method check if an object exists in the datastore based on a criterion
  60. *
  61. * Assumption: the given criterion identify only ONE object, or none.
  62. *
  63. * @param id the criterion used to identify the object
  64. * @return False if no match found, True if 'id' matched an object.
  65. */
  66. def exists(id: Criterion): Boolean = {
  67. pull(id) match {
  68. case Some(_) => true
  69. case None => false
  70. }
  71. }
  72. /**
  73. * The pull method retrieve an object from the DataStore based on a criterion.
  74. *
  75. * Assumption: the given criterion identify only ONE object, or none.
  76. *
  77. * @param id the criterion used to identify the object
  78. * @return None if no match found, Some(obj) if 'obj' matched.
  79. */
  80. def pull(id: Criterion): Option[T] = {
  81. val dbResult = _collection.findOne(MongoDBObject(id._1 -> id._2))
  82. dbResult match {
  83. case Some(dbObj) => Some(toDomainObject(dbObj))
  84. case None => None
  85. }
  86. }
  87. /**
  88. * The push method store an object in the DataStore.
  89. *
  90. * It will erase another object that return the same identifier criteria
  91. * (see the identify method in the DataSpecific trait).
  92. *
  93. * @param obj the object to be stored
  94. *
  95. */
  96. def push(obj: T) {
  97. pull(identify(obj)) match {
  98. case Some(db) => drop(db)
  99. case _ =>
  100. }
  101. _collection += toDatabaseObject(obj)
  102. }
  103. /**
  104. * The retrieve method is used to perform a criteria-based query
  105. *
  106. * @param criteria a list of expected criterion (AND semantics)
  107. * @return a list of objects that EXACTLY matched these criteria
  108. */
  109. def retrieve(criteria: List[(String, Any)]): List[T] = {
  110. val prototype = MongoDBObject.newBuilder
  111. criteria foreach { c => prototype += (c._1 -> c._2) }
  112. _collection.find(prototype.result).toList map { toDomainObject(_) }
  113. }
  114. /**
  115. * the drop method remove an object from the registry.
  116. *
  117. * The removal is serialization-based. It will remove from the registry
  118. * an element that is serialized exactly as its given parameter.
  119. *
  120. * @param obj the T instance to be dropped out
  121. */
  122. def drop(obj: T) { _collection -= toDatabaseObject(obj) }
  123. /**
  124. * The dropAll method clear the content of the registry.
  125. *
  126. * Use with caution.
  127. */
  128. def dropAll() { _collection.drop() }
  129. /**
  130. * Compute the size of the registry, that is, the number of object currently
  131. * stored.
  132. *
  133. * @return the size of the registry
  134. */
  135. def size = _collection.size
  136. /**
  137. * The underlying MongoDB collection
  138. */
  139. @MongoDBSpecific
  140. protected lazy val _collection = {
  141. val conn = MongoConnection()
  142. val db = conn(databaseName)
  143. val col = db(collectionName)
  144. col.ensureIndex(key)
  145. col
  146. }
  147. /**
  148. * Transform a domain object (T) into an instance of DBObject (mongoDB specific)
  149. *
  150. * @param obj the object to be transformed
  151. * @return the associated DBObject
  152. */
  153. @MongoDBSpecific
  154. private def toDatabaseObject(obj: T): DBObject = {
  155. val raw = JSON.parse(serialize(obj))
  156. if (null == raw)
  157. throw new RuntimeException("Unable to parse JSON data") // FIXME (DataStoreException)
  158. raw.asInstanceOf[BasicDBObject].asDBObject
  159. }
  160. /**
  161. * Transform a DBObject (MongoDB) into an instance of the domain object (T)
  162. *
  163. * @param dbobj the DBObject to be transformed
  164. * @return the associated domain object (T)
  165. */
  166. @MongoDBSpecific
  167. private def toDomainObject(dbObj: DBObject): T = { deserialize(dbObj.toString) }
  168. }