[Erp5-report] r15715 - in /erp5/trunk/products/ERP5SyncML: ./ Conduit/ Interface/ dtml/ tests/
nobody at svn.erp5.org
nobody at svn.erp5.org
Thu Aug 16 19:10:06 CEST 2007
Author: fabien
Date: Thu Aug 16 19:10:06 2007
New Revision: 15715
URL: http://svn.erp5.org?rev=15715&view=rev
Log:
remove gid_generator, now gid are generate in the Conduit
Added:
erp5/trunk/products/ERP5SyncML/Conduit/ERP5ConduitTitleGid.py
erp5/trunk/products/ERP5SyncML/Conduit/SharedVCardConduit.py (with props)
erp5/trunk/products/ERP5SyncML/ERP5SyncMLMobileServer.py (with props)
Modified:
erp5/trunk/products/ERP5SyncML/Conduit/ERP5Conduit.py
erp5/trunk/products/ERP5SyncML/Conduit/VCardConduit.py
erp5/trunk/products/ERP5SyncML/Interface/IConduit.py
erp5/trunk/products/ERP5SyncML/Publication.py
erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py
erp5/trunk/products/ERP5SyncML/Subscription.py
erp5/trunk/products/ERP5SyncML/SyncCode.py
erp5/trunk/products/ERP5SyncML/SynchronizationTool.py
erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py
erp5/trunk/products/ERP5SyncML/dtml/managePublications.dtml
erp5/trunk/products/ERP5SyncML/dtml/manageSubscriptions.dtml
erp5/trunk/products/ERP5SyncML/dtml/manage_addPublication.dtml
erp5/trunk/products/ERP5SyncML/dtml/manage_addSubscription.dtml
erp5/trunk/products/ERP5SyncML/tests/testERP5SyncML.py
erp5/trunk/products/ERP5SyncML/tests/testERP5SyncMLVCard.py
Modified: erp5/trunk/products/ERP5SyncML/Conduit/ERP5Conduit.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/Conduit/ERP5Conduit.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/Conduit/ERP5Conduit.py (original)
+++ erp5/trunk/products/ERP5SyncML/Conduit/ERP5Conduit.py Thu Aug 16 19:10:06 2007
@@ -1166,3 +1166,16 @@
xml_string = buf.getvalue()
buf.close()
return xml_string
+
+ def getGidFromObject(self, object):
+ """
+ return the Gid composed with the object informations
+ """
+ return object.getId()
+
+ def getGidFromXML(self, xml, gid_from_xml_list):
+ """
+ return the Gid composed with xml informations
+ """
+ return None
+
Added: erp5/trunk/products/ERP5SyncML/Conduit/ERP5ConduitTitleGid.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/Conduit/ERP5ConduitTitleGid.py?rev=15715&view=auto
==============================================================================
--- erp5/trunk/products/ERP5SyncML/Conduit/ERP5ConduitTitleGid.py (added)
+++ erp5/trunk/products/ERP5SyncML/Conduit/ERP5ConduitTitleGid.py Thu Aug 16 19:10:06 2007
@@ -1,0 +1,57 @@
+##############################################################################
+#
+# Copyright (c) 2007 Nexedi SARL and Contributors. All Rights Reserved.
+# Fabien Morin <fabien.morin at gmail.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
+from AccessControl import ClassSecurityInfo
+from Products.ERP5Type import Permissions
+from Products.ERP5SyncML.SyncCode import SyncCode
+
+from zLOG import LOG
+
+class ERP5ConduitTitleGid(ERP5Conduit):
+ """
+ ERP5ConduitTitleGid provides two methods who permit to have the GID
+ The Gid is composed by the title : "FirtName LastName"
+ this class is made for unit test
+ """
+
+ # Declarative security
+ security = ClassSecurityInfo()
+
+ def getGidFromObject(self, object):
+ """
+ return the Gid composed of FirstName and LastName generate with the object
+ """
+ return object.getTitle()
+
+# def getGidFromXML(self, xml):
+# """
+# return the Gid composed of FirstName and LastName generate with a peace of
+# xml
+# """
+# #to be defined
Added: erp5/trunk/products/ERP5SyncML/Conduit/SharedVCardConduit.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/Conduit/SharedVCardConduit.py?rev=15715&view=auto
==============================================================================
--- erp5/trunk/products/ERP5SyncML/Conduit/SharedVCardConduit.py (added)
+++ erp5/trunk/products/ERP5SyncML/Conduit/SharedVCardConduit.py Thu Aug 16 19:10:06 2007
@@ -1,0 +1,99 @@
+##############################################################################
+#
+# Copyright (c) 2007 Nexedi SARL and Contributors. All Rights Reserved.
+# Fabien Morin <fabien.morin at gmail.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+from Products.ERP5SyncML.Conduit.VCardConduit import VCardConduit
+from AccessControl import ClassSecurityInfo
+from Products.ERP5Type import Permissions
+from Products.ERP5SyncML.SyncCode import SyncCode
+from zLOG import LOG, INFO, DEBUG, TRACE
+
+class SharedVCardConduit(VCardConduit, SyncCode):
+ """
+ A conduit is in charge to read data from a particular structure,
+ and then to save this data in another structure.
+
+ SharedVCardConduit is a peace of code who provide GID.
+ This GID are the same for all subscriber, so a same object could be updated
+ by all the subscriber.
+ """
+
+
+ # Declarative security
+ security = ClassSecurityInfo()
+
+ def getGidFromObject(self, object):
+ """
+ return the Gid composed of FirstName_LastName generate with the object
+ """
+ gid_list = []
+ if object.getFirstName() not in ('', None):
+ gid_list.append(object.getFirstName())
+ gid_list.append('_')
+ if object.getLastName() not in ('', None):
+ gid_list.append(object.getLastName())
+ sql_kw = {}
+ sql_kw['portal_type'] = 'Person'
+ sql_kw['title'] = object.getTitle()
+ sql_kw['id'] = '<'+object.getId()
+ results = object.portal_catalog.countResults(**sql_kw)[0][0]
+ LOG('getGidFromObject', DEBUG, 'getId:%s, getTitle:%s' % (object.getId(), object.getTitle()))
+ LOG('getGidFromObject, number of results :', DEBUG, results)
+ if int(results) > 0:
+ gid_list.append('__')
+ gid_list.append(str(int(results)+1))
+ gid = ''.join(gid_list)
+ LOG('getGidFromObject gid :', DEBUG, gid)
+ return gid
+
+ def getGidFromXML(self, vcard, gid_from_xml_list):
+ """
+ return the Gid composed of FirstName and LastName generate with a vcard
+ """
+ vcard_dict = self.vcard2Dict(vcard)
+ gid_from_vcard_list = []
+ if vcard_dict.has_key('first_name') and \
+ vcard_dict['first_name'] not in ('', None):
+ gid_from_vcard_list.append(vcard_dict['first_name'])
+ gid_from_vcard_list.append('_')
+ if vcard_dict.has_key('last_name') and \
+ vcard_dict['last_name'] not in ('', None):
+ gid_from_vcard_list.append(vcard_dict['last_name'])
+ gid_from_vcard = ''.join(gid_from_vcard_list)
+ LOG('getGidFromXML, gid_from_vcard :', DEBUG, gid_from_vcard)
+ number = len([item for item in gid_from_xml_list if item.startswith(gid_from_vcard)])
+ LOG('getGidFromXML, gid_from_xml_list :', DEBUG, gid_from_xml_list)
+ LOG('getGidFromXML, number :', DEBUG, number)
+ if number > 0:
+ gid_from_vcard_list.append('__')
+ gid_from_vcard_list.append(str(number+1))
+ #it's mean for 3 persons a a a, the gid will be
+ #a_, a___2 a___3
+ gid_from_vcard = ''.join(gid_from_vcard_list)
+ LOG('getGidFromXML, returned gid_from_vcard :', DEBUG, gid_from_vcard)
+ return gid_from_vcard
+
Propchange: erp5/trunk/products/ERP5SyncML/Conduit/SharedVCardConduit.py
------------------------------------------------------------------------------
svn:executable = *
Modified: erp5/trunk/products/ERP5SyncML/Conduit/VCardConduit.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/Conduit/VCardConduit.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/Conduit/VCardConduit.py (original)
+++ erp5/trunk/products/ERP5SyncML/Conduit/VCardConduit.py Thu Aug 16 19:10:06 2007
@@ -64,6 +64,8 @@
"""
LOG('VCardConduit',0,'addNode, object=%s, object_id=%s, sub_object:%s, \
xml:\n%s' % (str(object), str(object_id), str(sub_object), xml))
+ if not isinstance(xml, str):
+ xml = self.nodeToString(xml)
portal_type = 'Person' #the VCard can just use Person
if sub_object is None:
@@ -134,21 +136,6 @@
"""
prefered_type = self.MEDIA_TYPE['TEXT_XVCARD']
return prefered_type
-
- def getGidFromXML(self, vcard):
- """
- return the Gid composed of FirstName and LastName
- """
- vcard_dict = self.vcard2Dict(vcard)
- gid_from_vcard = []
- if vcard_dict.has_key('first_name'):
- gid_from_vcard.append(vcard_dict['first_name'])
- gid_from_vcard.append(' ')
- if vcard_dict.has_key('last_name'):
- gid_from_vcard.append(vcard_dict['last_name'])
- gid_from_vcard = ''.join(gid_from_vcard)
- LOG('gid_from_vcard', 0, gid_from_vcard)
- return gid_from_vcard
def changePropertyEncoding(self, property_parameters_list,
property_value_list):
Added: erp5/trunk/products/ERP5SyncML/ERP5SyncMLMobileServer.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/ERP5SyncMLMobileServer.py?rev=15715&view=auto
==============================================================================
--- erp5/trunk/products/ERP5SyncML/ERP5SyncMLMobileServer.py (added)
+++ erp5/trunk/products/ERP5SyncML/ERP5SyncMLMobileServer.py Thu Aug 16 19:10:06 2007
@@ -1,0 +1,237 @@
+#!/usr/bin/python
+# coding=UTF-8
+import httplib
+import urllib,urllib2, os
+from Ft.Xml import Parse
+import cStringIO
+import string
+import socket
+import time
+from optparse import OptionParser
+try:
+ from Ft.Xml.Domlette import Print, PrettyPrint
+except ImportError:
+ LOG('ERP5Conduit',0,"Can't import Print and PrettyPrint")
+ class Print:
+ def __init__(self, *args, **kw):
+ raise ImportError, "Sorry, it was not possible to import Ft library"
+
+ class PrettyPrint:
+ def __init__(self, *args, **kw):
+ raise ImportError, "Sorry, it was not possible to import Ft library"
+
+
+class OptionParser(OptionParser):
+
+ def check_required (self, opt):
+ option = self.get_option(opt)
+
+ # Assumes the option's 'default' is set to None!
+ if getattr(self.values, option.dest) is None:
+ self.error("%s option not supplied" % option)
+
+
+parser = OptionParser()
+parser.add_option("--host", help="address of this small server (typically, it's the ip of this computer)")
+parser.add_option("--publication", help="address of the publication (e.g. http://localhost:9080/erp5Serv)")
+parser.add_option("-p", "--port", type="int", help="port used by this server (default is 1234)", default=1234)
+
+(options, args) = parser.parse_args()
+
+parser.check_required("--publication")
+parser.check_required("--host")
+
+
+
+#CONFIGURATION SECTION
+
+#address of this small server :
+#Host = '192.168.242.247'
+Host=options.host
+
+#address of the publication :
+#publication_url = 'http://localhost:9080/erp5Serv'
+publication_url = options.publication
+
+#address use to transmit the message received from the external client :
+to_url = publication_url+"/portal_synchronizations/readResponse"
+
+#port of this server :
+#Port = 1234
+Port=options.port
+
+#address of the this server :
+syncml_server_url = 'http://'+Host+':'+str(Port)
+
+#socket :
+sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
+
+#END CONFIGURATION SECTION
+
+CRLF = "\015\012"
+#in unix, it's the same as \r\n, and on windows, it's the same as \n (\r on mac)
+#this octal constant just increase a little this application portability
+
+
+
+
+def nodeToString(node):
+ """
+ return an xml string corresponding to the node
+ """
+ buf = cStringIO.StringIO()
+ Print(node, stream=buf, encoding='utf-8')
+ xml_string = buf.getvalue()
+ buf.close()
+ return xml_string
+
+def xml2wbxml(xml):
+ """
+ convert xml string to wbxml using a temporary file
+ """
+ import os
+ f = open('/tmp/xml2wbxml', 'w')
+ f.write(xml)
+ f.close()
+ os.system('/usr/bin/xml2wbxml -o /tmp/xml2wbxml /tmp/xml2wbxml')
+ f = open('/tmp/xml2wbxml', 'r')
+ wbxml = f.read()
+ f.close()
+ return wbxml
+
+def wbxml2xml(wbxml):
+ """
+ convert wbxml string to xml using a temporary file
+ """
+ import os
+ f = open('/tmp/wbxml2xml', 'w')
+ f.write(wbxml)
+ f.close()
+ os.system('/usr/bin/wbxml2xml -o /tmp/wbxml2xml /tmp/wbxml2xml')
+ f = open('/tmp/wbxml2xml', 'r')
+ xml = f.read()
+ f.close()
+ return xml
+
+def hexdump(raw=''):
+ """
+ print raw in readable format without broke the terminal output !
+ """
+ buf = ""
+ line = ""
+ start = 0
+ done = False
+ while not done:
+ end = start + 16
+ max = len(raw)
+ if end > max:
+ end = max
+ done = True
+ chunk = raw[start:end]
+ for i in xrange(len(chunk)):
+ if i > 0:
+ spacing = " "
+ else:
+ spacing = ""
+ buf += "%s%02x" % (spacing, ord(chunk[i]))
+ if done:
+ for i in xrange(16 - (end % 16)):
+ buf += " "
+ buf += " "
+ for c in chunk:
+ val = ord(c)
+ if val >= 33 and val <= 126:
+ buf += c
+ else:
+ buf += "."
+ buf += "\n"
+ start += 16
+ return buf
+
+def getClientUrl(text):
+ """
+ find the client url in the text and return it
+ """
+ document = Parse(text)
+ client_url = document.xpath('string(//SyncHdr/Source/LocURI)').encode('utf-8')
+ return client_url
+
+def sendResponse(text, to_url, client_url):
+ """
+ send the message receive from the external client to erp5 server
+ """
+ result = None
+ opener = urllib2.build_opener()
+ urllib2.install_opener(opener)
+ to_encode = {}
+
+ print '\nsendResponse...'
+
+ text=wbxml2xml(text)
+ text = text.replace(syncml_server_url, publication_url)
+ text = text.replace(client_url, syncml_server_url)
+
+ print "text = ",text
+ to_encode['text'] = text
+ to_encode['sync_id'] = 'Person'
+ headers = {'Content-type': 'application/vnd.syncml+xml'}
+
+ encoded = urllib.urlencode(to_encode)
+ data=encoded
+ request = urllib2.Request(url=to_url, data=data)
+
+ try:
+ result = urllib2.urlopen(request).read()
+ except socket.error, msg:
+ print 'error, url:%s ,data : %s'%(url, data)
+ except urllib2.URLError, msg:
+ print "sendResponse, can't open url : %s" % to_url
+
+ return result
+
+
+def main():
+ sock.bind((Host,Port))
+ # we just listen to one and unique connection
+ sock.listen(1)
+
+ text = ''
+ # the script stop here until a client connect to him
+ print 'wait for a client connection...'
+ client, address = sock.accept()
+ print "the host ",address," is connected."
+ while 1:
+ print('\n\nwait for message ...')
+ msg = client.recv(1024) # we receive 1024 caracter max
+ if not msg: # if we receive nothing
+ break
+ elif not msg.startswith('POST'):
+ text = text + msg
+ if text.endswith('\x01\x01'):
+ client_url = getClientUrl(wbxml2xml(text))
+ response = sendResponse(text=text, to_url=to_url, client_url=client_url)
+ if response not in ('', None):
+ response = response.replace(syncml_server_url, client_url)
+ response = response.replace(publication_url, syncml_server_url)
+ print "\nresponse = \n",response
+ response = xml2wbxml(response)
+ print "response send to the phone :\n", hexdump(response)
+ date_to_print = time.strftime("%a, %d %b %Y %H:%M:%S GMT")
+ head = CRLF.join((
+ "HTTP/1.1 200 OK",
+ "Date: %s GMT" % date_to_print,
+ "Server: myPythonServer",
+ "Content-Length: %s" % len(response),
+ "Content-Type: application/vnd.syncml+wbxml",
+ ))
+ message = "%s%s%s%s" % (head, CRLF, CRLF, response)
+ #here it's necessary to have 2 CRLF, for more details
+ #see http://www.w3.org/Protocols/rfc2616/rfc2616.html
+ client.send(message)
+ text=''
+ else:
+ print "this message is a POST header."
+ sock.close()
+
+if __name__ == "__main__":
+ main()
Propchange: erp5/trunk/products/ERP5SyncML/ERP5SyncMLMobileServer.py
------------------------------------------------------------------------------
svn:executable = *
Modified: erp5/trunk/products/ERP5SyncML/Interface/IConduit.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/Interface/IConduit.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/Interface/IConduit.py (original)
+++ erp5/trunk/products/ERP5SyncML/Interface/IConduit.py Thu Aug 16 19:10:06 2007
@@ -110,7 +110,7 @@
return the Gid composed with the object informations
"""
- def getGidFromXML(self, xml):
+ def getGidFromXML(self, xml, gid_from_xml_list):
"""
return the Gid composed with xml informations
"""
Modified: erp5/trunk/products/ERP5SyncML/Publication.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/Publication.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/Publication.py (original)
+++ erp5/trunk/products/ERP5SyncML/Publication.py Thu Aug 16 19:10:06 2007
@@ -144,7 +144,7 @@
# Constructor
def __init__(self, id, title, publication_url, destination_path,
source_uri, query, xml_mapping, conduit, gpg_key, id_generator,
- gid_generator, media_type, authentication_format,
+ media_type, authentication_format,
authentication_type, activity_enabled, synchronize_with_erp5_sites,
sync_content_type):
"""
@@ -159,7 +159,6 @@
self.xml_mapping = xml_mapping
self.domain_type = self.PUB
self.gpg_key = gpg_key
- self.setGidGenerator(gid_generator)
self.setMediaType(media_type)
self.setSynchronizationIdGenerator(id_generator)
self.setConduit(conduit)
Modified: erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py (original)
+++ erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py Thu Aug 16 19:10:06 2007
@@ -234,7 +234,10 @@
result = self.PubSyncInit(publication,xml_client,subscriber=subscriber,
sync_type=self.SLOW_SYNC)
elif self.checkAlert(xml_client) and \
- alert_code in (self.TWO_WAY, self.SLOW_SYNC, self.ONE_WAY_FROM_SERVER):
+ alert_code in (self.TWO_WAY, self.SLOW_SYNC, \
+ self.ONE_WAY_FROM_SERVER):
+ subscriber.setXMLMapping(publication.getXMLMapping())
+ subscriber.setConduit(publication.getConduit())
result = self.PubSyncInit(publication=publication,
xml_client=xml_client, subscriber=subscriber, sync_type=alert_code)
else:
Modified: erp5/trunk/products/ERP5SyncML/Subscription.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/Subscription.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/Subscription.py (original)
+++ erp5/trunk/products/ERP5SyncML/Subscription.py Thu Aug 16 19:10:06 2007
@@ -649,7 +649,7 @@
# Constructor
def __init__(self, id, title, publication_url, subscription_url,
destination_path, source_uri, target_uri, query, xml_mapping,
- conduit, gpg_key, id_generator, gid_generator, media_type, login,
+ conduit, gpg_key, id_generator, media_type, login,
password, activity_enabled, alert_code, synchronize_with_erp5_sites,
sync_content_type):
"""
@@ -677,7 +677,6 @@
self.password=password
self.domain_type = self.SUB
self.gpg_key = gpg_key
- self.setGidGenerator(gid_generator)
self.setSynchronizationIdGenerator(id_generator)
self.setConduit(conduit)
Folder.__init__(self, id)
@@ -944,22 +943,6 @@
xml = func()
return xml
- def setGidGenerator(self, method):
- """
- This set the method name wich allows to find a gid
- from any object
- """
- if method in (None, '', 'None'):
- method = 'getId'
- self.gid_generator = method
-
- def getGidGenerator(self):
- """
- This get the method name wich allows to find a gid
- from any object
- """
- return self.gid_generator
-
def getMediaType(self):
"""
This method return the type of media used in this session,
@@ -1046,17 +1029,25 @@
"""
o_base = aq_base(object)
o_gid = None
- gid_gen = self.getGidGenerator()
+ conduit_name = self.getConduit()
+ conduit = self.getConduitByName(conduit_name)
+ gid_gen = getattr(conduit, 'getGidFromObject', None)
+ LOG('getGidFromObject, Conduit :', DEBUG, conduit_name)
+ LOG('getGidFromObject, gid_gen:', DEBUG, gid_gen)
if callable(gid_gen):
o_gid = gid_gen(object)
- elif getattr(o_base, gid_gen, None) is not None:
- generator = getattr(object, gid_gen)
- o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant
- elif gid_gen is not None:
- # It might be a script python
- generator = getattr(object,gid_gen)
- o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant
+ else:
+ raise ValueError, "The conduit "+conduit_name+"seems to no have a \
+ getGidFromObject method and it must"
+# elif getattr(o_base, gid_gen, None) is not None:
+# generator = getattr(object, gid_gen)
+# o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant
+# elif gid_gen is not None:
+# # It might be a script python
+# generator = getattr(object,gid_gen)
+# o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant
o_gid = b16encode(o_gid)
+ LOG('getGidFromObject returning', DEBUG, o_gid)
return o_gid
def getObjectFromGid(self, gid):
@@ -1490,3 +1481,23 @@
retrun the user logged in
"""
return getattr(self, 'user', None)
+
+ def getConduitByName(self, conduit_name):
+ """
+ Get Conduit Object by given name.
+ The Conduit can be located in Any Products according to naming Convention
+ Products.<Product Name>.Conduit.<Conduit Module> ,if conduit_name equal module's name.
+ By default Conduit must be defined in Products.ERP5SyncML.Conduit.<Conduit Module>
+ """
+ from Products.ERP5SyncML import Conduit
+ if conduit_name.startswith('Products'):
+ path = conduit_name
+ conduit_name = conduit_name.split('.')[-1]
+ conduit_module = __import__(path, globals(), locals(), [''])
+ conduit = getattr(conduit_module, conduit_name)()
+ else:
+ conduit_module = __import__('.'.join([Conduit.__name__, conduit_name]),
+ globals(), locals(), [''])
+ conduit = getattr(conduit_module, conduit_name)()
+ return conduit
+
Modified: erp5/trunk/products/ERP5SyncML/SyncCode.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/SyncCode.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/SyncCode.py (original)
+++ erp5/trunk/products/ERP5SyncML/SyncCode.py Thu Aug 16 19:10:06 2007
@@ -72,7 +72,7 @@
PUB_CONFLICT_CLIENT_WIN = 8
MAX_LINES = 5000
- MAX_OBJECTS = 100
+ MAX_OBJECTS = 300
action_tag = 'workflow_action'
#NOT_EDITABLE_PROPERTY = ('id','object','uid','xupdate:element',action_tag,
Modified: erp5/trunk/products/ERP5SyncML/SynchronizationTool.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/SynchronizationTool.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/SynchronizationTool.py (original)
+++ erp5/trunk/products/ERP5SyncML/SynchronizationTool.py Thu Aug 16 19:10:06 2007
@@ -178,7 +178,7 @@
def manage_addPublication(self, title, publication_url,
destination_path, source_uri, query, xml_mapping,
conduit, gpg_key,
- synchronization_id_generator=None, gid_generator=None,
+ synchronization_id_generator=None,
media_type=None, authentication_format='b64',
authentication_type='syncml:auth-basic',
RESPONSE=None, activity_enabled = False,
@@ -195,7 +195,7 @@
pub = Publication(new_id, title, publication_url,
destination_path, source_uri, query, xml_mapping,
conduit, gpg_key, synchronization_id_generator,
- gid_generator, media_type,
+ media_type,
authentication_format,
authentication_type,
activity_enabled, synchronize_with_erp5_sites,
@@ -212,7 +212,7 @@
def manage_addSubscription(self, title, publication_url, subscription_url,
destination_path, source_uri, target_uri, query,
xml_mapping, conduit, gpg_key,
- synchronization_id_generator=None, gid_generator=None,
+ synchronization_id_generator=None,
media_type=None, login=None, password=None,
RESPONSE=None, activity_enabled=False,
alert_code=SyncCode.TWO_WAY,
@@ -230,7 +230,7 @@
sub = Subscription(new_id, title, publication_url, subscription_url,
destination_path, source_uri, target_uri, query,
xml_mapping, conduit, gpg_key,
- synchronization_id_generator, gid_generator, media_type,
+ synchronization_id_generator, media_type,
login, password, activity_enabled, alert_code,
synchronize_with_erp5_sites, sync_content_type)
folder._setObject( new_id, sub )
@@ -245,7 +245,7 @@
def manage_editPublication(self, title, publication_url,
destination_path, source_uri, query, xml_mapping,
conduit, gpg_key, synchronization_id_generator,
- gid_generator, media_type=None,
+ media_type=None,
authentication_format='b64',
authentication_type='syncml:auth-basic',
RESPONSE=None, activity_enabled=False,
@@ -265,7 +265,6 @@
pub.setXMLMapping(xml_mapping)
pub.setGPGKey(gpg_key)
pub.setSynchronizationIdGenerator(synchronization_id_generator)
- pub.setGidGenerator(gid_generator)
pub.setMediaType(media_type)
pub.setAuthenticationFormat(authentication_format)
pub.setAuthenticationType(authentication_type)
@@ -279,7 +278,7 @@
'manage_editSubscription')
def manage_editSubscription(self, title, publication_url, subscription_url,
destination_path, source_uri, target_uri, query, xml_mapping, conduit,
- gpg_key, synchronization_id_generator, gid_generator, media_type=None,
+ gpg_key, synchronization_id_generator, media_type=None,
login='', password='', RESPONSE=None, activity_enabled=False,
alert_code=SyncCode.TWO_WAY, synchronize_with_erp5_sites=False,
sync_content_type='application/vnd.syncml+xml'):
@@ -299,7 +298,6 @@
sub.setGPGKey(gpg_key)
sub.setSubscriptionUrl(subscription_url)
sub.setSynchronizationIdGenerator(synchronization_id_generator)
- sub.setGidGenerator(gid_generator)
sub.setMediaType(media_type)
sub.setLogin(login)
sub.setPassword(password)
Modified: erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py (original)
+++ erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py Thu Aug 16 19:10:06 2007
@@ -778,10 +778,28 @@
object_list = domain.getObjectList()
object_path_list = map(lambda x: x.getPhysicalPath(),object_list)
subscriber.setRemainingObjectPathList(object_path_list)
-
- local_gid_list = map(lambda x: domain.getGidFromObject(x),object_list)
+
+ if subscriber.getMediaType() == self.MEDIA_TYPE['TEXT_VCARD']:
+ #here the method getGidFromObject don't return the good gid because
+ #the conduit use the catalog to determine it and object are not yet
+ #cataloged so if there is many times the same gid, we must count it
+ gid_not_encoded_list = []
+ for object in object_list:
+ LOG('getSyncMLData :', DEBUG, 'object:%s, object_list:%s, objectTitle:%s, local_gid_list:%s' % (object, object_list, object.getTitle(), local_gid_list))
+ gid = b16decode(domain.getGidFromObject(object))
+ if gid in gid_not_encoded_list:
+ number = len([item for item in gid_not_encoded_list if item.startswith(gid)])
+ if number > 0:
+ gid = gid+'__'+str(number+1)
+ gid_not_encoded_list.append(gid)
+ local_gid_list.append(b16encode(gid))
+ LOG('getSyncMLData :', DEBUG,'gid_not_encoded_list:%s, local_gid_list:%s, gid:%s' % (gid_not_encoded_list, local_gid_list, gid))
+ else:
+ local_gid_list = map(lambda x: domain.getGidFromObject(x),object_list)
+
# Objects to remove
LOG('remove object to remove ...', DEBUG, '')
+ object_gid_deleted = []
for object_gid in subscriber.getGidList():
if object_gid not in local_gid_list:
# This is an object to remove
@@ -792,6 +810,7 @@
if xml_object is not None: # This prevent to delete an object that
# we were not able to create
rid = signature.getRid()
+ object_gid_deleted.append(object_gid)
syncml_data += self.deleteXMLObject(
xml_object=signature.getXML() or '',
object_gid=object_gid,
@@ -1022,6 +1041,7 @@
"""
xml_confirmation = ''
has_next_action = 0
+ gid_from_xml_list = []
destination = self.unrestrictedTraverse(domain.getDestinationPath())
LOG('applyActionList args', DEBUG, 'domain : %s\n subscriber : %s\n cmd_id : %s' % (domain.getPath(), subscriber.getPath(), cmd_id))
LOG('applyActionList', DEBUG, self.getSyncActionList(remote_xml))
@@ -1034,8 +1054,13 @@
partial_data = self.getPartialData(action)
rid = self.getActionId(action)
if action.nodeName != 'Delete':
- if hasattr(conduit, 'getGidFromXML'):
- gid = b16encode(conduit.getGidFromXML(self.getDataText(action)))
+ if hasattr(conduit, 'getGidFromXML') and \
+ conduit.getGidFromXML(self.getDataText(action),
+ gid_from_xml_list) not in ('', None):
+ gid = conduit.getGidFromXML(self.getDataText(action),
+ gid_from_xml_list)
+ gid_from_xml_list.append(gid)
+ gid = b16encode(gid)
else:
gid=rid
else:
Modified: erp5/trunk/products/ERP5SyncML/dtml/managePublications.dtml
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/dtml/managePublications.dtml?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/dtml/managePublications.dtml (original)
+++ erp5/trunk/products/ERP5SyncML/dtml/managePublications.dtml Thu Aug 16 19:10:06 2007
@@ -161,16 +161,6 @@
<tr>
<td align="left" valign="top">
<div class="form-label">
- Gid Generator
- </label></div>
- </td>
- <td align="left" valign="top">
- <input type="text" name="gid_generator" value="<dtml-var getGidGenerator>" size="40" />
- </td>
- </tr>
- <tr>
- <td align="left" valign="top">
- <div class="form-label">
Media Type
</label></div>
</td>
Modified: erp5/trunk/products/ERP5SyncML/dtml/manageSubscriptions.dtml
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/dtml/manageSubscriptions.dtml?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/dtml/manageSubscriptions.dtml (original)
+++ erp5/trunk/products/ERP5SyncML/dtml/manageSubscriptions.dtml Thu Aug 16 19:10:06 2007
@@ -198,16 +198,6 @@
<tr>
<td align="left" valign="top">
<div class="form-label">
- Gid Generator
- </label></div>
- </td>
- <td align="left" valign="top">
- <input type="text" name="gid_generator" value="<dtml-var getGidGenerator>" size="40" />
- </td>
- </tr>
- <tr>
- <td align="left" valign="top">
- <div class="form-label">
Media Type
</label></div>
</td>
Modified: erp5/trunk/products/ERP5SyncML/dtml/manage_addPublication.dtml
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/dtml/manage_addPublication.dtml?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/dtml/manage_addPublication.dtml (original)
+++ erp5/trunk/products/ERP5SyncML/dtml/manage_addPublication.dtml Thu Aug 16 19:10:06 2007
@@ -156,16 +156,6 @@
<tr>
<td align="left" valign="top">
<div class="form-label">
- Gid Generator
- </label></div>
- </td>
- <td align="left" valign="top">
- <input type="text" name="gid_generator" size="40" />
- </td>
- </tr>
- <tr>
- <td align="left" valign="top">
- <div class="form-label">
Media Type
</label></div>
</td>
Modified: erp5/trunk/products/ERP5SyncML/dtml/manage_addSubscription.dtml
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/dtml/manage_addSubscription.dtml?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/dtml/manage_addSubscription.dtml (original)
+++ erp5/trunk/products/ERP5SyncML/dtml/manage_addSubscription.dtml Thu Aug 16 19:10:06 2007
@@ -193,16 +193,6 @@
<tr>
<td align="left" valign="top">
<div class="form-label">
- Gid Generator
- </label></div>
- </td>
- <td align="left" valign="top">
- <input type="text" name="gid_generator" size="40" />
- </td>
- </tr>
- <tr>
- <td align="left" valign="top">
- <div class="form-label">
Media Type
</label></div>
</td>
Modified: erp5/trunk/products/ERP5SyncML/tests/testERP5SyncML.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/tests/testERP5SyncML.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/tests/testERP5SyncML.py (original)
+++ erp5/trunk/products/ERP5SyncML/tests/testERP5SyncML.py Thu Aug 16 19:10:06 2007
@@ -346,7 +346,6 @@
xml_mapping=self.xml_mapping,
conduit='ERP5Conduit',
gpg_key='',
- gid_generator='getId',
activity_enabled=False,
authentication_format='b64',
authentication_type='syncml:auth-basic')
@@ -370,7 +369,6 @@
xml_mapping=self.xml_mapping,
conduit='ERP5Conduit',
gpg_key='',
- gid_generator='getId',
activity_enabled=False,
login='fab',
password='myPassword')
@@ -394,7 +392,6 @@
xml_mapping=self.xml_mapping,
conduit='ERP5Conduit',
gpg_key='',
- gid_generator='getId',
activity_enabled=False,
login='fab',
password='myPassword')
@@ -408,15 +405,13 @@
def setupPublicationAndSubscriptionAndGid(self, quiet=0, run=run_all_test):
self.setupPublicationAndSubscription(quiet=1,run=1)
- def getGid(object):
- return object.getTitle()
portal_sync = self.getSynchronizationTool()
sub1 = portal_sync.getSubscription(self.sub_id1)
sub2 = portal_sync.getSubscription(self.sub_id2)
pub = portal_sync.getPublication(self.pub_id)
- pub.setGidGenerator(getGid)
- sub1.setGidGenerator(getGid)
- sub2.setGidGenerator(getGid)
+ sub1.setConduit('ERP5ConduitTitleGid')
+ sub2.setConduit('ERP5ConduitTitleGid')
+ pub.setConduit('ERP5ConduitTitleGid')
pub.setSynchronizationIdGenerator('_generateNextId')
sub1.setSynchronizationIdGenerator('_generateNextId')
sub2.setSynchronizationIdGenerator('_generateNextId')
@@ -1342,7 +1337,6 @@
xml_mapping=self.xml_mapping,
conduit='ERP5Conduit',
gpg_key='',
- gid_generator='getId',
activity_enabled=False,
alert_code = SyncCode.ONE_WAY_FROM_SERVER,
login = 'fab',
Modified: erp5/trunk/products/ERP5SyncML/tests/testERP5SyncMLVCard.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/tests/testERP5SyncMLVCard.py?rev=15715&r1=15714&r2=15715&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/tests/testERP5SyncMLVCard.py (original)
+++ erp5/trunk/products/ERP5SyncML/tests/testERP5SyncMLVCard.py Thu Aug 16 19:10:06 2007
@@ -66,13 +66,22 @@
if not run: return
if not quiet:
ZopeTestCase._print('\nTest Add a VCard Publication ')
- LOG('Testing... ',0,'test_36_AddVCardPublication')
+ LOG('Testing... ',0,'test_01_AddVCardPublication')
portal_id = self.getPortalName()
portal_sync = self.getSynchronizationTool()
- portal_sync.manage_addPublication(self.pub_id, self.publication_url,
- '/%s/person_server' % portal_id, 'Person', 'objectValues',
- 'Person_exportAsVCard', 'VCardConduit', '', 'generateNewId',
- 'getId', SyncCode.MEDIA_TYPE['TEXT_VCARD'])
+ portal_sync.manage_addPublication(title=self.pub_id,
+ publication_url=self.publication_url,
+ destination_path='/%s/person_server' % portal_id,
+ source_uri='Person',
+ query='objectValues',
+ xml_mapping='Person_exportAsVCard',
+ conduit='SharedVCardConduit',
+ gpg_key='',
+ synchronization_id_generator='generateNewId',
+ media_type='text/vcard',
+ activity_enabled=False,
+ authentication_format='b64',
+ authentication_type='syncml:auth-basic')
pub = portal_sync.getPublication(self.pub_id)
self.failUnless(pub is not None)
@@ -83,11 +92,21 @@
LOG('Testing... ',0,'test_02_AddVCardSubscription1')
portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool()
- portal_sync.manage_addSubscription(self.sub_id1, self.publication_url,
- self.subscription_url1, '/%s/person_client1' % portal_id,
- 'Person', 'Person', 'objectValues', 'Person_exportAsVCard',
- 'VCardConduit', '', 'generateNewId', 'getId',
- SyncCode.MEDIA_TYPE['TEXT_VCARD'])
+ portal_sync.manage_addSubscription(title=self.sub_id1,
+ publication_url=self.publication_url,
+ subscription_url=self.subscription_url1,
+ destination_path='/%s/person_client1' % portal_id,
+ source_uri='Person',
+ target_uri='Person',
+ query='objectValues',
+ xml_mapping='Person_exportAsVCard',
+ conduit='SharedVCardConduit',
+ gpg_key='',
+ synchronization_id_generator='generateNewId',
+ media_type='text/vcard',
+ activity_enabled=False,
+ login='fab',
+ password='myPassword')
sub = portal_sync.getSubscription(self.sub_id1)
self.failUnless(sub is not None)
@@ -98,11 +117,21 @@
LOG('Testing... ',0,'test_03_AddVCardSubscription2')
portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool()
- portal_sync.manage_addSubscription(self.sub_id2, self.publication_url,
- self.subscription_url2, '/%s/person_client2' % portal_id,
- 'Person', 'Person', 'objectValues', 'Person_exportAsVCard',
- 'VCardConduit', '', 'generateNewId', 'getId',
- SyncCode.MEDIA_TYPE['TEXT_VCARD'])
+ portal_sync.manage_addSubscription(title=self.sub_id2,
+ publication_url=self.publication_url,
+ subscription_url=self.subscription_url2,
+ destination_path='/%s/person_client2' % portal_id,
+ source_uri='Person',
+ target_uri='Person',
+ query='objectValues',
+ xml_mapping='Person_exportAsVCard',
+ conduit='SharedVCardConduit',
+ gpg_key='',
+ synchronization_id_generator='generateNewId',
+ media_type='text/vcard',
+ activity_enabled=False,
+ login='fab',
+ password='myPassword')
sub = portal_sync.getSubscription(self.sub_id2)
self.failUnless(sub is not None)
@@ -143,7 +172,7 @@
if not run: return
if not quiet:
- ZopeTestCase._print('\nTest Basic VCard Synchronization')
+ ZopeTestCase._print('\nTest Basic VCard Synchronization ')
LOG('Testing... ',0,'test_05_basicVCardSynchronization')
self.test_04_FirstVCardSynchronization(quiet=True, run=True)
@@ -179,7 +208,7 @@
"""
if not run: return
if not quiet:
- ZopeTestCase._print('\nTest No Duplicate Data When Adding')
+ ZopeTestCase._print('\nTest No Duplicate Data When Adding ')
LOG('Testing... ',0,'test_05_verifyNoDuplicateDataWhenAdding')
self.test_04_FirstVCardSynchronization(quiet=True, run=True)
portal_sync = self.getSynchronizationTool()
More information about the Erp5-report
mailing list