PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Poliwiki/grails-app/services/org/poliwiki/VersioningService.groovy

http://poliwiki.googlecode.com/
Groovy | 341 lines | 294 code | 36 blank | 11 comment | 84 complexity | 2d0abcd03412ed6e16c257e651f85fbf MD5 | raw file
Possible License(s): AGPL-3.0
  1. package org.poliwiki
  2. import com.mongodb.DBObject
  3. import com.mongodb.DB
  4. import com.mongodb.DBCollection
  5. import com.mongodb.BasicDBObject
  6. import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty
  7. import org.codehaus.groovy.grails.web.converters.ConverterUtil
  8. import org.hibernate.SessionFactory
  9. import org.poliwiki.dao.ServiceUtils
  10. import org.poliwiki.office.Jurisdiction
  11. /**
  12. *
  13. * Authors: Nathaniel Miller and Alex Schneeman
  14. *
  15. */
  16. class VersioningService {
  17. SessionFactory sessionFactory
  18. def mongoService
  19. static transactional = true
  20. public static final String POV_VERSIONS = "povVersions";
  21. public static final String ISSUE_VERSIONS = "issueVersions";
  22. public static final String PERSON_VERSIONS = "personVersions";
  23. public static final String GROUP_VERSIONS = "groupVersions";
  24. public static final String JURIS_VERSIONS = "jurisVersions"
  25. public static final String LATEST_VERSIONS = "latestVersions";
  26. boolean listening
  27. public void syncVersion(Object entity) {
  28. boolean shouldVersion = false
  29. synchronized (this) {
  30. if (VersioningUtils.shouldVersion(entity)) {
  31. entity.saveRevision = false
  32. shouldVersion = true
  33. }
  34. }
  35. if (shouldVersion) {
  36. boolean successful =insert(entity)
  37. }
  38. }
  39. public DB getDb(){
  40. return mongoService.getDb()
  41. }
  42. public DBObject findLatest(String collection, Object clazz, Object id) throws IllegalArgumentException {
  43. DBObject searchById = new BasicDBObject("class", clazz);
  44. searchById.put("id", id);
  45. DBCollection coll = getDb().getCollection(LATEST_VERSIONS);
  46. DBObject res = coll.findOne(searchById);
  47. if (res==null) {
  48. throw new IllegalArgumentException("No record found in "+collection+ " with class " + clazz + " and id " + id.toString());
  49. }
  50. return findById(collection, id, res.get("revision"));
  51. }
  52. public DBObject safeFindLatest(String collection, Object clazz, Object id) {
  53. try {
  54. return findLatest(collection, clazz, id);
  55. } catch (IllegalArgumentException e) {
  56. return null;
  57. }
  58. }
  59. public DBObject findById(String collection, Object id, Object revision) throws IllegalArgumentException{
  60. DBObject searchById= new BasicDBObject("id", id);
  61. searchById.put("revision.revision", revision);
  62. DBCollection coll = getDb().getCollection(collection);
  63. DBObject res = coll.findOne(searchById);
  64. if(res==null){
  65. throw new IllegalArgumentException("No record found in "+collection+ " at database " + mongoService.getDbName() +" with id "+id.toString()+" and revision " + revision.toString());
  66. }
  67. return res;
  68. }
  69. public DBObject safeFindById(String collection, Object id, Object version){
  70. try{
  71. return findById(collection, id, version);
  72. } catch(IllegalArgumentException e){
  73. System.out.println(e.getMessage());
  74. return null;
  75. }
  76. }
  77. public DBObject findLatestVersion(Object id, String clazz){
  78. DBObject searchById = new BasicDBObject("id", id);
  79. searchById.put("class", clazz);
  80. DBCollection coll = getDb().getCollection(LATEST_VERSIONS);
  81. DBObject dbo = coll.findOne(searchById)
  82. return dbo;
  83. }
  84. public Diff getDiff(long id, long revisionOne, long revisionTwo, Class klass){
  85. String coll = findCollection(klass)
  86. DBObject objOne = safeFindById(coll, id, revisionOne)
  87. DBObject objTwo = safeFindById(coll, id, revisionTwo)
  88. return new Diff(objOne, objTwo)
  89. }
  90. public Object get(long id, long version, Class clazz) throws IllegalArgumentException {
  91. String coll = findCollection(clazz)
  92. DBObject obj = safeFindById(coll, id, version)
  93. return dbObjectToObject(obj)
  94. }
  95. public Object getLatest(Object o) throws IllegalArgumentException {
  96. getLatest(o.id, o.getClass())
  97. }
  98. public Object getLatest(long id, Class clazz) throws IllegalArgumentException{
  99. String coll = findCollection(ServiceUtils.getRealClass(clazz.newInstance()))
  100. Object o = findLatestVersion(id, ServiceUtils.getRealClass(clazz.newInstance()).getName())
  101. if (o != null) {
  102. DBObject obj = safeFindById(coll, id, o.get("revision"))
  103. return dbObjectToObject(obj)
  104. } else {
  105. return null
  106. }
  107. }
  108. public DBObject getLatestDBO(long id, Class clazz) throws IllegalArgumentException{
  109. String coll = findCollection(ServiceUtils.getRealClass(clazz.newInstance()))
  110. Object o = findLatestVersion(id, ServiceUtils.getRealClass(clazz.newInstance()).getName())
  111. if (o != null) {
  112. DBObject obj = safeFindById(coll, id, o.get("revision"))
  113. return obj
  114. } else {
  115. return null
  116. }
  117. }
  118. public DBObject objectToDBObject(Object o, Map<String, Integer> config) {
  119. DBObject dbo = new BasicDBObject("class", ServiceUtils.getRealClass(o).getName())
  120. if (ConverterUtil.getDomainClass(o.getClass().getName()) != null) {
  121. dbo.put("id", o.id)
  122. }
  123. for (GrailsDomainClassProperty p: ConverterUtil.getDomainClass(o.getClass().name).persistentProperties) {
  124. if (config.containsKey(p.getName())) {
  125. continue // skip fields in the config
  126. }
  127. Object prop = o."$p.name"
  128. if (Collection.isInstance(prop)) {
  129. List<Object> list = new ArrayList<Object>()
  130. for (Object b: prop) {
  131. if (VersioningUtils.fullClassObject(b, null)) {
  132. DBObject obj = objectToDBObject(b)
  133. list.add(obj)
  134. } else if (ConverterUtil.getDomainClass(b.getClass().getName()) != null) {
  135. DBObject bl = new BasicDBObject("id", b.id)
  136. bl.put("class", ServiceUtils.getRealClass(b).getName())
  137. list.add(bl)
  138. } else {
  139. list.add(b)
  140. }
  141. }
  142. dbo.put(p.name, list)
  143. } else if (ConverterUtil.getDomainClass(prop.getClass().getName()) != null) {
  144. if (VersioningUtils.fullClassObject(prop, null)) {
  145. dbo.put(p.name, objectToDBObject(prop))
  146. } else {
  147. DBObject bl = new BasicDBObject("id", prop.id)
  148. bl.put("class", ServiceUtils.getRealClass(prop).getName())
  149. dbo.put(p.name, bl)
  150. }
  151. } else {
  152. dbo.put(p.name, prop)
  153. }
  154. }
  155. return dbo
  156. }
  157. public DBObject objectToDBObject(Object o){
  158. return objectToDBObject(o, VersioningUtils.getDefaultConfig())
  159. }
  160. public Object revert(long id, long version, Class clazz) throws IllegalArgumentException {
  161. String coll = findCollection(clazz);
  162. DBObject obj = safeFindById(coll, id, version)
  163. return revertToDBObject(obj)
  164. }
  165. public Object revertToDBObject(DBObject dbo) {
  166. String[] a = ((String)dbo.get("class")).split("\\.")
  167. def c = ServiceUtils.getClassForName(a[a.length-1]).get(dbo.get("id"))
  168. for (GrailsDomainClassProperty p : ConverterUtil.getDomainClass(c.getClass().getName()).persistentProperties) {
  169. def o = dbo.get(p.name)
  170. if (o.getClass() == BasicDBObject) {
  171. c."$p.name" = ConverterUtil.getDomainClass((String)o.get("class")).newInstance().getClass().get(o.get("id"))
  172. } else if (Collection.isInstance(o)){
  173. if(p.getType().isInterface()) {
  174. Collection n = new TreeSet()
  175. if (p.getType() == Set) {
  176. n = new HashSet()
  177. } else if (p.getType() == List) {
  178. n = new ArrayList()
  179. } else if (p.getType() == Queue) {
  180. n = new LinkedList()
  181. }
  182. for (Object b : o) {
  183. if(BasicDBObject.isInstance(b)){
  184. n.add(dbObjectToObject((DBObject)b))
  185. } else{
  186. n.add(b)
  187. }
  188. }
  189. c."$p.name" = n
  190. } else {
  191. Collection n = (Collection)p.getType().newInstance()
  192. for (Object b : o) {
  193. n.add(b)
  194. }
  195. c."$p.name" = n
  196. }
  197. } else {
  198. c."$p.name" = o
  199. }
  200. }
  201. c.id = dbo.get("id")
  202. return c
  203. }
  204. public Object dbObjectToObject(DBObject dbo) {
  205. def c = ConverterUtil.getDomainClass((String)dbo.get("class")).newInstance()
  206. if (!VersioningUtils.fullClassObject(c, null)) {
  207. return c.getClass().get(dbo.get('id'))
  208. }
  209. for (GrailsDomainClassProperty p : ConverterUtil.getDomainClass(c.getClass().getName()).persistentProperties) {
  210. def o = dbo.get(p.name)
  211. /*if (o == null) {
  212. c."$p.name" = null
  213. } else if (p.getType() == Map) {
  214. c."$p.name" = new HashMap<String, String>((Map)o) // drop all the BasicDBObject cruft
  215. } else */
  216. if (o.getClass() == BasicDBObject) {
  217. // c."$p.name" = ConverterUtil.getDomainClass((String)o.get("class")).newInstance().getClass().newInstance()
  218. c."$p.name" = dbObjectToObject(o)
  219. } else if (Collection.isInstance(o)){
  220. if(p.getType().isInterface()) {
  221. Collection n = new TreeSet()
  222. if (p.getType() == Set) {
  223. n = new HashSet()
  224. } else if (p.getType() == List) {
  225. n = new ArrayList()
  226. } else if (p.getType() == Queue) {
  227. n = new LinkedList()
  228. }
  229. for (Object b : o) {
  230. if(BasicDBObject.isInstance(b)){
  231. n.add(dbObjectToObject((DBObject)b))
  232. } else{
  233. n.add(b)
  234. }
  235. }
  236. c."$p.name" = n
  237. } else {
  238. Collection n = (Collection)p.getType().newInstance()
  239. for (Object b : o) {
  240. n.add(b)
  241. }
  242. c."$p.name" = n
  243. }
  244. } else {
  245. c."$p.name" = o
  246. }
  247. }
  248. c.id = dbo.get("id")
  249. return c
  250. }
  251. public boolean insert(Object obj) {
  252. DBCollection coll
  253. coll = getDb().getCollection(findCollection(ServiceUtils.getRealClass(obj)))
  254. coll.insert(objectToDBObject(obj))
  255. DBObject version = findLatestVersion(obj.id, ServiceUtils.getRealClass(obj).getName())
  256. if (version != null) {
  257. List<Object> revisions = (List<Object>)version.get("revisions")
  258. if (revisions == null) {
  259. revisions = new ArrayList<Object>()
  260. }
  261. revisions.add(obj.revision.revision)
  262. version.put("revision", obj.revision.revision)
  263. version.put("revisions",revisions)
  264. getDb().getCollection(LATEST_VERSIONS).save(version)
  265. } else {
  266. DBObject dbo = new BasicDBObject("class", ServiceUtils.getRealClass(obj).getName())
  267. dbo.put("id", obj.id)
  268. dbo.put("revision", obj.revision.revision)
  269. List<Object> revisions = (List<Object>)dbo.get("revisions")
  270. if (revisions == null) {
  271. revisions = new ArrayList<Object>()
  272. }
  273. revisions.add(obj.revision.revision)
  274. dbo.put("revisions", revisions)
  275. getDb().getCollection(LATEST_VERSIONS).insert(dbo)
  276. }
  277. return true
  278. }
  279. public List<RevisionInformation> getAllRevisions(Object o){
  280. String coll = findCollection(ServiceUtils.getRealClass(o))
  281. DBObject latest= findLatestVersion(o.id,o.getClass().getName())
  282. List<Object> revisionNumbers= (List<Object>)latest.get("revisions")
  283. List<RevisionInformation> res = new ArrayList<RevisionInformation>()
  284. for(Long revision : revisionNumbers){
  285. DBObject dbo= safeFindById(coll, o.id, revision)
  286. res.add((RevisionInformation)dbObjectToObject((DBObject)dbo.get("revision")))
  287. }
  288. return res
  289. }
  290. public String findCollection(Class obj) {
  291. if (obj.equals(Group)) {
  292. return GROUP_VERSIONS
  293. } else if (obj.equals(Issue)) {
  294. return ISSUE_VERSIONS
  295. } else if (obj.equals(Person)) {
  296. return PERSON_VERSIONS
  297. } else if (obj.equals(Pov)) {
  298. return POV_VERSIONS
  299. } else if (obj.equals(Jurisdiction)){
  300. return JURIS_VERSIONS
  301. } else {
  302. throw new IllegalArgumentException("unknown object for versioning: " + obj)
  303. }
  304. }
  305. }