+

Implementation of groups objects and use it to synchronize groups with an advanced method

Benjamin Renard [2014-01-28 01:07:19]
Implementation of groups objects and use it to synchronize groups with an advanced method
Filename
mycoserver/db/__init__.py
mycoserver/group.py
mycoserver/testdata.py
diff --git a/mycoserver/db/__init__.py b/mycoserver/db/__init__.py
index ac4f8c4..171fd68 100644
--- a/mycoserver/db/__init__.py
+++ b/mycoserver/db/__init__.py
@@ -5,6 +5,7 @@ import json
 import logging
 log = logging.getLogger(__name__)
 import MySQLdb
+from mycoserver import group

 class DB(object):

@@ -72,26 +73,17 @@ class DB(object):

 	def sync_group(self,email,groups):
 		db_groups=self.get_group(email)
-		json_group=json.dumps(groups)
 		if db_groups!=False:
-			log.debug('Database groups : %s' % db_groups)
-			log.debug('Provided groups : %s' % groups)
-			if 'groups' not in db_groups or db_groups['groups']=={}:
-				log.debug('Database group is empty')
-				if 'groups' not in groups or groups['groups']=={}:
-					log.debug('Database and provided group are empty. Return empty')
-					return {'groups': {'groups': {}}}
-				else:
-					log.debug('Insert provided groups in database and return it')
-					if self.do_sql("INSERT INTO groups (email,groups) VALUES ('%s','%s')" % (email,json_group)):
-						return {'groups': groups}
-			elif 'groups' not in groups or groups['groups']=={}:
-				log.debug('Provide group is empty. Return database groups')
-				return {'groups': db_groups}
+			db_grouplist=group.GroupList()
+			db_grouplist.load(db_groups)
+			grouplist=group.GroupList()
+			grouplist.load(groups)
+			synced_grouplist=db_grouplist.sync(grouplist)
+			if self.set_group(email,synced_grouplist.export()):
+				log.debug('Groups successfuly synchronized, return result')
+				return {'groups': synced_grouplist.export()}
 			else:
-				log.debug('Update database with provided group and return it')
-				if self.do_sql("UPDATE groups SET groups='%s' WHERE email='%s'" % (json_group,email)):
-					return {'groups': groups}
+				return {'syncerror': 'Erreur en modifiant les informations de la base de donnees'}
 		return {'syncerror': 'Erreur inconnu'}

 	def get_group(self,email):
@@ -103,3 +95,14 @@ class DB(object):
 				return {'groups': {}}
 		else:
 			return False
+
+	def set_group(self,email,groups):
+		ret=self.select("SELECT groups FROM groups WHERE email='%s'" % email)
+		if ret!=False:
+			json_groups=json.dumps(groups)
+			if len(ret)==1:
+				return self.do_sql("UPDATE groups SET groups='%s' WHERE email='%s'" % (json_groups,email))
+			else:
+				return self.do_sql("INSERT INTO groups (email,groups) VALUES ('%s','%s')" % (email,json_groups))
+		else:
+			return False
diff --git a/mycoserver/group.py b/mycoserver/group.py
new file mode 100644
index 0000000..bb43fc6
--- /dev/null
+++ b/mycoserver/group.py
@@ -0,0 +1,210 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import logging
+import urllib
+log = logging.getLogger(__name__)
+
+class GroupList(object):
+
+  def __init__(self):
+    self.groups={}
+    self.lastChange=False
+
+  def load(self,data):
+    if 'lastChange' in data:
+      self.lastChange=data['lastChange']
+    if 'groups' in data:
+      for g in data['groups']:
+        self.groups[g]=Group()
+        self.groups[g].load(data['groups'][g])
+
+  def export(self):
+    groups={}
+    for uuid in self.groups:
+      groups[uuid]=self.groups[uuid].export()
+
+    return {
+      'lastChange': self.lastChange,
+      'groups': groups
+    }
+
+  def toJSON(self,pretty=False):
+    if pretty:
+      return json.dumps(self.export(),indent=4, separators=(',', ': '))
+    else:
+      return json.dumps(self.export())
+
+  def sync(self,groups):
+    ret=GroupList()
+    if groups.lastChange<self.lastChange:
+      ret.lastChange=self.lastChange
+    else:
+      ret.lastChange=groups.lastChange
+    for uuid in groups.groups:
+      if uuid in self.groups:
+        ret.groups[uuid]=self.groups[uuid].sync(groups.groups[uuid])
+      else:
+        ret.groups[uuid]=groups.groups[uuid]
+    return ret
+
+
+class Group(object):
+
+  def __init__(self):
+    self.uuid=None
+    self.name=None
+    self.contributors={}
+    self.contributions={}
+    self.deletedContributions={}
+
+  def load(self,data):
+    try:
+      self.uuid=data['uuid']
+      self.name=data['name']
+      for email in data['contributors']:
+        self.contributors[email]=Contributor()
+        self.contributors[email].load(data['contributors'][email])
+      for uuid in data['contributions']:
+        self.contributions[uuid]=Contribution()
+        self.contributions[uuid].load(data['contributions'][uuid])
+      if 'deletedContributions' in data:
+        for uuid in data['deletedContributions']:
+          self.deletedContributions[uuid]=Contribution()
+          self.deletedContributions[uuid].load(data['deletedContributions'][uuid])
+      return True
+    except Exception,e:
+      logging.error('Error loading JSON data : %s',e)
+      return False
+
+  def export(self):
+    contributors={}
+    for email in self.contributors:
+      contributors[email]=self.contributors[email].export()
+
+    contributions={}
+    for uuid in self.contributions:
+      contributions[uuid]=self.contributions[uuid].export()
+
+    deletedContributions={}
+    for uuid in self.deletedContributions:
+      deletedContributions[uuid]=self.deletedContributions[uuid].export()
+
+    return {
+      'uuid': self.uuid,
+      'name': self.name,
+      'contributors': contributors,
+      'contributions': contributions,
+      'deletedContributions': deletedContributions
+    }
+
+  def sync(self, group):
+    ret=Group()
+    ret.uuid=self.uuid
+
+    # FIXME : Add lastChange on group to permit name choice between to object
+    ret.name=group.name
+
+    ## Contributors
+    ret.contributors=self.contributors
+    for email in group.contributors:
+      if email not in ret.contributors:
+        ret.contributors[email]=group.contributors[email]
+
+    ## Deleted Contributions
+    for uuid in self.deletedContributions:
+      if uuid in group.deletedContributions:
+        ret.deletedContributions[uuid]=self.deletedContributions[uuid].sync(group.deletedContributions[uuid])
+      else:
+        ret.deletedContributions[uuid]=self.deletedContributions[uuid]
+    for uuid in group.deletedContributions:
+      if uuid not in ret.deletedContributions:
+        ret.deletedContributions[uuid]=group.deletedContributions[uuid]
+
+    ## Contributions
+    for uuid in self.contributions:
+      if uuid in group.contributions:
+        ret.contributions[uuid]=self.contributions[uuid].sync(group.contributions[uuid])
+      elif uuid not in ret.deletedContributions:
+        ret.contributions[uuid]=self.contributions[uuid]
+      elif self.contributions[uuid].lastChange>ret.deletedContributions[uuid].lastChange:
+        ret.contributions[uuid]=self.contributions[uuid]
+    for uuid in group.contributions:
+      if uuid not in ret.contributions:
+        if uuid not in ret.deletedContributions:
+          ret.contributions[uuid]=group.contributions[uuid]
+        elif group.contributions[uuid].lastChange>ret.deletedContributions[uuid].lastChange:
+          ret.contributions[uuid]=group.contributions[uuid]
+
+    return ret
+
+
+class Contribution(object):
+
+  def __init__(self):
+    self.uuid=None
+    self.contributor=None
+    self.title=None
+    self.cost=None
+    self.date=None
+    self.lastChange=None
+
+  def load(self,data):
+    self.uuid=data['uuid']
+    self.contributor=data['contributor']
+    self.title=data['title']
+    self.cost=data['cost']
+    self.date=data['date']
+    self.lastChange=data['lastChange']
+
+  def export(self):
+    return {
+      'uuid': self.uuid,
+      'contributor': self.contributor,
+      'cost': self.cost,
+      'title': self.title,
+      'date': self.date,
+      'lastChange': self.lastChange
+    }
+
+  def sync(self, c):
+    if c.lastChange>self.lastChange:
+      return c
+    else:
+      return self
+
+class Contributor(object):
+
+  def __init__(self):
+    self.name=None
+    self.email=None
+
+  def load(self,data):
+    self.name=data['name']
+    self.email=data['email']
+
+  def export(self):
+    return {
+      'name': self.name,
+      'email': self.email
+    }
+
+
+if __name__ == '__main__':
+  import testdata
+  import json
+
+  data=json.loads(testdata.group_as_json)
+  data2=json.loads(testdata.group_as_json2)
+
+  gl=GroupList()
+  gl.load(data2)
+
+  print gl.toJSON(True)
+
+  print 'Try sync groups'
+  gl2=GroupList()
+  gl2.load(data)
+  gl_sync=gl.sync(gl2)
+  print 'Sync group : %s' % gl_sync
+  print gl_sync.toJSON(True)
diff --git a/mycoserver/testdata.py b/mycoserver/testdata.py
new file mode 100644
index 0000000..bd9c45b
--- /dev/null
+++ b/mycoserver/testdata.py
@@ -0,0 +1,5 @@
+#!/usr/bin/python
+
+group_as_json="""{"groups":{"7547b547-a3df-40f6-a728-e990ef35c67d":{"uuid":"7547b547-a3df-40f6-a728-e990ef35c67d","name":"test","contributors":{"ben@ben.com":{"name":"Benjamin","email":"ben@ben.com"},"ludo@myco.com":{"name":"Ludovic","email":"ludo@myco.com"}},"contributions":{"4467c88a-f99d-416f-9055-6241441579ed":{"contributor":"ben@ben.com","uuid":"4467c88a-f99d-416f-9055-6241441579ed","cost":14,"title":"test2","date":1390867172110,"lastChange":1390867172117},"78171e1b-8bcf-4614-ac9b-363fd23e3745":{"contributor":"ben@ben.com","uuid":"78171e1b-8bcf-4614-ac9b-363fd23e3745","cost":13,"title":"test","date":1390086000000,"lastChange":1390137335475}},"deletedContributions":{"a370e8a9-ec54-44e8-b6df-22d60d8e6214":{"contributor":"ben@ben.com","cost":12,"date":1390863713090,"lastChange":1390863716422,"title":"test2","uuid":"a370e8a9-ec54-44e8-b6df-22d60d8e6214"}}}}}"""
+
+group_as_json2="""{"groups":{"7547b547-a3df-40f6-a728-e990ef35c67d":{"uuid":"7547b547-a3df-40f6-a728-e990ef35c67d","name":"test","contributors":{"ben@ben.com":{"name":"Benjamin","email":"ben@ben.com"},"ludo@myco.com":{"name":"Ludovic","email":"ludo@myco.com"}},"contributions":{"78171e1b-8bcf-4614-ac9b-363fd23e3745":{"contributor":"ben@ben.com","uuid":"78171e1b-8bcf-4614-ac9b-363fd23e3745","cost":13,"title":"test","date":1390086000000,"lastChange":1390137335475}},"deletedContributions":{}}}}"""
ViewGit