Doc, webdav: new API for the DAV:resourcetype property.

This property is used in DAV folders, CalDAV, GroupDAV and CardDAV, with
different extensions at each one. So, it needs an extensible API for the
value it may return.

Typical response in a calendar dir:
	<D:resourcetype>
	    <D:collection>
	    <ns0:vevent-collection xmlns:ns0="http://groupdav.org"/>
	    <ns1:calendar xmlns:ns1="urn:ietf:params:xml:ns:caldav" />
	</D:resourcetype>

The last two elements have to be added by subclassing the node in the
caldav module.

Conflicts:

	document_webdav/dav_fs.py

bzr revid: p_christ@hol.gr-20100801083722-nh4ty58fy0hobrgk
This commit is contained in:
P. Christeas 2010-08-01 11:37:22 +03:00
parent 313ffd1550
commit 2289282c8b
3 changed files with 107 additions and 22 deletions

View File

@ -314,6 +314,14 @@ class node_class(object):
logger.debug('Property %s not supported' % prop, exc_info=True)
return None
def get_dav_resourcetype(self, cr):
""" Get the DAV resource type.
Is here because some nodes may exhibit special behaviour, like
CalDAV/GroupDAV collections
"""
raise NotImplementedError
def move_to(self, cr, ndir_node, new_name=False, fil_obj=None, ndir_obj=None, in_write=False):
""" Move this node to a new parent directory.
@param ndir_node the collection that this node should be moved under
@ -456,6 +464,9 @@ class node_database(node_class):
def _get_ttag(self,cr):
return 'db-%s' % cr.dbname
def get_dav_resourcetype(self, cr):
return ('collection', 'DAV:')
def mkdosname(company_name, default='noname'):
""" convert a string to a dos-like name"""
if not company_name:
@ -778,6 +789,9 @@ class node_res_dir(node_class):
def _get_ttag(self,cr):
return 'rdir-%d' % self.dir_id
def get_dav_resourcetype(self, cr):
return ('collection', 'DAV:')
class node_res_obj(node_class):
""" A special sibling to node_dir, which does only contain dynamically
created folders foreach resource in the foreign model.
@ -1034,6 +1048,9 @@ class node_res_obj(node_class):
def _get_ttag(self,cr):
return 'rodir-%d-%d' % (self.dir_id, self.res_id)
def get_dav_resourcetype(self, cr):
return ('collection', 'DAV:')
class node_file(node_class):
our_type = 'file'
def __init__(self, path, parent, context, fil):
@ -1168,6 +1185,9 @@ class node_file(node_class):
def _get_ttag(self,cr):
return 'file-%d' % self.file_id
def get_dav_resourcetype(self, cr):
return ''
def move_to(self, cr, ndir_node, new_name=False, fil_obj=None, ndir_obj=None, in_write=False):
if ndir_node.context != self.context:
raise NotImplementedError("Cannot move files between contexts")
@ -1313,6 +1333,8 @@ class node_content(node_class):
def _get_ttag(self,cr):
return 'cnt-%d%s' % (self.cnt_id,(self.act_id and ('-' + str(self.act_id))) or '')
def get_dav_resourcetype(self, cr):
return ''
class nodefd_content(StringIO, node_descriptor):
""" A descriptor to content nodes

View File

@ -370,19 +370,22 @@ class openerp_dav_handler(dav_interface):
if cr: cr.close()
@memoize(CACHE_SIZE)
def _get_dav_resourcetype(self,uri):
def _get_dav_resourcetype(self, uri):
""" return type of object """
self.parent.log_message('get RT: %s' % uri)
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
try:
if not dbname:
return COLLECTION
node = self.uri2object(cr,uid,pool, uri2)
node = self.uri2object(cr, uid, pool, uri2)
if not node:
raise DAV_NotFound2(uri2)
if node.type in ('collection','database'):
return COLLECTION
return OBJECT
try:
return node.get_dav_resourcetype(cr)
except NotImplementedError:
if node.type in ('collection','database'):
return ('collection', 'DAV:')
return ''
finally:
if cr: cr.close()
@ -739,6 +742,17 @@ class openerp_dav_handler(dav_interface):
@memoize(CACHE_SIZE)
def is_collection(self, uri):
""" test if the given uri is a collection """
return self._get_dav_resourcetype(uri)==COLLECTION
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
try:
if not dbname:
return True
node = self.uri2object(cr,uid,pool, uri2)
if not node:
raise DAV_NotFound2(uri2)
if node.type in ('collection','database'):
return True
return False
finally:
if cr: cr.close()
#eof

View File

@ -48,6 +48,70 @@ def mk_prop_response(self, uri, good_props, bad_props, doc):
re.setAttribute("xmlns:ns"+str(nsnum),nsname)
nsnum=nsnum+1
def _prop_child(xnode, ns, prop, value):
"""Append a property xml node to xnode, with <prop>value</prop>
And a little smarter than that, it will consider namespace and
also allow nested properties etc.
:param ns the namespace of the <prop/> node
:param prop the name of the property
:param value the value. Can be:
string: text node
tuple ('elem', 'ns') for empty sub-node <ns:elem />
tuple ('elem', 'ns', sub-elems) for sub-node with elements
list, of above tuples
"""
if ns == 'DAV:':
ns_prefix = 'D:'
else:
ns_prefix="ns"+str(namespaces.index(ns))+":"
pe=doc.createElement(ns_prefix+str(prop))
if hasattr(value, '__class__') and value.__class__.__name__ == 'Element':
pe.appendChild(value)
else:
if ns == 'DAV:' and prop=="resourcetype" and isinstance(value, int):
# hack, to go..
if value == 1:
ve=doc.createElement("D:collection")
pe.appendChild(ve)
else:
_prop_elem_child(pe, ns, value, ns_prefix)
xnode.appendChild(pe)
def _prop_elem_child(pnode, pns, v, pns_prefix):
if isinstance(v, list):
for vit in v:
_prop_elem_child(pnode, pns, vit, pns_prefix)
elif isinstance(v,tuple):
need_ns = False
if v[1] == pns:
ns_prefix = pns_prefix
elif v[1] == 'DAV:':
ns_prefix = 'D:'
elif v[1] in namespaces:
ns_prefix="ns"+str(namespaces.index(v[1]))+":"
else:
# namespaces.append(v[1])
# nsnum += 1
ns_prefix="ns"+str(nsnum)+":"
need_ns = True
ve=doc.createElement(ns_prefix+v[0])
if need_ns:
ve.setAttribute("xmlns:ns"+str(nsnum), v[1])
if len(v) > 2 and isinstance(v[2], list):
# support nested elements like:
# ( 'elem', 'ns:', [('sub-elem1', 'ns1'), ...]
_prop_elem_child(ve, v[1], v[2], ns_prefix)
pnode.appendChild(ve)
else:
ve=doc.createTextNode(tools.ustr(v))
pnode.appendChild(ve)
# write href information
uparts=urlparse.urlparse(uri)
fileloc=uparts[2]
@ -74,22 +138,7 @@ def mk_prop_response(self, uri, good_props, bad_props, doc):
for p,v in good_props[ns].items():
if not v:
continue
pe=doc.createElement(ns_prefix+str(p))
if hasattr(v, '__class__') and v.__class__.__name__ == 'Element':
pe.appendChild(v)
else:
if ns == 'DAV:' and p=="resourcetype":
if v == 1:
ve=doc.createElement("D:collection")
pe.appendChild(ve)
elif isinstance(v,tuple) and v[1] == ns:
ve=doc.createElement(ns_prefix+v[0])
pe.appendChild(ve)
else:
ve=doc.createTextNode(tools.ustr(v))
pe.appendChild(ve)
gp.appendChild(pe)
_prop_child(gp, ns, p, v)
ps.appendChild(gp)
s=doc.createElement("D:status")