Resolving CMIS-481. Also began to add some logging infrastructure.
git-svn-id: https://svn.apache.org/repos/asf/chemistry/cmislib/trunk@1210717 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/cmislib/model.py b/src/cmislib/model.py
index 4044835..62d6ce7 100644
--- a/src/cmislib/model.py
+++ b/src/cmislib/model.py
@@ -36,6 +36,7 @@
import time
import iso8601
import StringIO
+import logging
# would kind of like to not have any parsing logic in this module,
# but for now I'm going to put the serial/deserialization in methods
@@ -83,6 +84,8 @@
UNFILED_COLL = 'unfiled'
ROOT_COLL = 'root'
+moduleLogger = logging.getLogger('cmislib.model')
+
class CmisClient(object):
@@ -105,6 +108,8 @@
self.username = username
self.password = password
self.extArgs = kwargs
+ self.logger = logging.getLogger('cmislib.model.CmisClient')
+ self.logger.info('Creating an instance of CmisClient')
def __str__(self):
"""To string"""
@@ -343,6 +348,8 @@
self._permMap = {}
self._permissions = None
self._propagation = None
+ self.logger = logging.getLogger('cmislib.model.Repository')
+ self.logger.info('Creating an instance of Repository')
def __str__(self):
"""To string"""
@@ -353,6 +360,7 @@
This method will re-fetch the repository's XML data from the CMIS
repository.
"""
+ self.logger.debug('Reload called on object')
self.xmlDoc = self._cmisClient.get(self._cmisClient.repositoryUrl.encode('utf-8'))
self._initData()
@@ -1183,8 +1191,8 @@
properties['cmis:objectTypeId'] = CmisId(properties['cmis:objectTypeId'])
# build the Atom entry
- xmlDoc = getEntryXmlDoc(properties, contentFile,
- contentType, contentEncoding)
+ xmlDoc = getEntryXmlDoc(self, None, properties, contentFile,
+ contentType, contentEncoding)
# post the Atom entry
result = self._cmisClient.post(postUrl.encode('utf-8'), xmlDoc.toxml(encoding='utf-8'), ATOM_XML_ENTRY_TYPE)
@@ -1413,6 +1421,8 @@
self._repository = repository
self._xmlDoc = xmlDoc
self._results = []
+ self.logger = logging.getLogger('cmislib.model.ResultSet')
+ self.logger.info('Creating an instance of ResultSet')
def __iter__(self):
''' Iterator for the result set '''
@@ -1470,6 +1480,7 @@
'''
+ self.logger.debug('Reload called on result set')
self._getPageResults(SELF_REL)
def getResults(self):
@@ -1653,6 +1664,8 @@
self._allowableActions = {}
self.xmlDoc = xmlDoc
self._kwargs = kwargs
+ self.logger = logging.getLogger('cmislib.model.CmisObject')
+ self.logger.info('Creating an instance of CmisObject')
def __str__(self):
"""To string"""
@@ -1670,6 +1683,7 @@
'*'.
"""
+ self.logger.debug('Reload called on CmisObject')
if kwargs:
if self._kwargs:
self._kwargs.update(kwargs)
@@ -1745,6 +1759,7 @@
if self._objectId == None:
if self.xmlDoc == None:
+ logger.debug('Both objectId and xmlDoc were None, reloading')
self.reload()
props = self.getProperties()
self._objectId = CmisId(props['cmis:objectId'])
@@ -1927,6 +1942,7 @@
"""
+ self.logger.debug('Inside updateProperties')
# get the self link
selfUrl = self._getSelfLink()
@@ -1935,10 +1951,20 @@
args = {}
if (self.properties.has_key('cmis:changeToken') and
self.properties['cmis:changeToken'] != None):
+ self.logger.debug('Change token present, adding it to args')
args = {"changeToken": self.properties['cmis:changeToken']}
+ # the getEntryXmlDoc function may need the object type
+ if (self.properties.has_key('cmis:objectTypeId') and
+ not properties.has_key('cmis:objectTypeId')):
+ objectTypeId = self.properties['cmis:objectTypeId']
+
+ self.logger.debug('This object type is:' + objectTypeId)
+
# build the entry based on the properties provided
- xmlEntryDoc = getEntryXmlDoc(properties)
+ xmlEntryDoc = getEntryXmlDoc(self._repository, objectTypeId, properties)
+
+ self.logger.debug('xmlEntryDoc:' + xmlEntryDoc.toxml())
# do a PUT of the entry
updatedXmlDoc = self._cmisClient.put(selfUrl.encode('utf-8'),
@@ -2032,7 +2058,7 @@
props['cmis:sourceId'] = self.getObjectId()
props['cmis:targetId'] = targetObj.getObjectId()
props['cmis:objectTypeId'] = relTypeId
- xmlDoc = getEntryXmlDoc(props)
+ xmlDoc = getEntryXmlDoc(self._repository, properties=props)
url = self._getLink(RELATIONSHIPS_REL)
assert url != None, 'Could not determine relationships URL'
@@ -2251,7 +2277,7 @@
# get this document's object ID
# build entry XML with it
properties = {'cmis:objectId': self.getObjectId()}
- entryXmlDoc = getEntryXmlDoc(properties)
+ entryXmlDoc = getEntryXmlDoc(self._repository, properties=properties)
# post it to to the checkedout collection URL
result = self._cmisClient.post(checkoutUrl.encode('utf-8'),
@@ -2537,6 +2563,7 @@
args = {}
if (self.properties.has_key('cmis:changeToken') and
self.properties['cmis:changeToken'] != None):
+ self.logger.debug('Change token present, adding it to args')
args = {"changeToken": self.properties['cmis:changeToken']}
# put the content file
@@ -2577,6 +2604,7 @@
args = {}
if (self.properties.has_key('cmis:changeToken') and
self.properties['cmis:changeToken'] != None):
+ self.logger.debug('Change token present, adding it to args')
args = {"changeToken": self.properties['cmis:changeToken']}
# delete the content stream
@@ -2683,7 +2711,7 @@
properties['cmis:objectTypeId'] = CmisId(properties['cmis:objectTypeId'])
# build the Atom entry
- entryXml = getEntryXmlDoc(properties)
+ entryXml = getEntryXmlDoc(self._repository, properties=properties)
# post the Atom entry
result = self._cmisClient.post(postUrl.encode('utf-8'),
@@ -3119,6 +3147,8 @@
self._kwargs = None
self._typeId = typeId
self.xmlDoc = xmlDoc
+ self.logger = logging.getLogger('cmislib.model.ObjectType')
+ self.logger.info('Creating an instance of ObjectType')
def __str__(self):
"""To string"""
@@ -3327,6 +3357,8 @@
def __init__(self, propNode):
"""Constructor"""
self.xmlDoc = propNode
+ self.logger = logging.getLogger('cmislib.model.Property')
+ self.logger.info('Creating an instance of Property')
def __str__(self):
"""To string"""
@@ -3440,6 +3472,9 @@
else:
self._xmlDoc = None
+ self.logger = logging.getLogger('cmislib.model.ACL')
+ self.logger.info('Creating an instance of ACL')
+
def addEntry(self, ace):
"""
@@ -3612,6 +3647,9 @@
self._permissions = permissions
self._direct = direct
+ self.logger = logging.getLogger('cmislib.model.ACE')
+ self.logger.info('Creating an instance of ACE')
+
@property
def principalId(self):
"""Getter for principalId"""
@@ -3663,6 +3701,8 @@
self._changeEntryId = None
self._changeType = None
self._changeTime = None
+ self.logger = logging.getLogger('cmislib.model.ChangeEntry')
+ self.logger.info('Creating an instance of ChangeEntry')
def getId(self):
"""
@@ -3866,6 +3906,8 @@
node's element name.
"""
+ moduleLogger.debug('Inside parsePropValue')
+
if nodeName == 'propertyId':
return CmisId(value)
elif nodeName == 'propertyString':
@@ -3948,6 +3990,8 @@
of its child types depending on the specified baseType.
"""
+ moduleLogger.debug('Inside getSpecializedObject')
+
if 'cmis:baseTypeId' in obj.getProperties():
baseType = obj.getProperties()['cmis:baseTypeId']
if baseType == 'cmis:folder':
@@ -3972,6 +4016,8 @@
Internal helper method that knows how to build an empty Atom entry.
"""
+ moduleLogger.debug('Inside getEmptyXmlDoc')
+
entryXmlDoc = minidom.Document()
entryElement = entryXmlDoc.createElementNS(ATOM_NS, "entry")
entryElement.setAttribute('xmlns', ATOM_NS)
@@ -3979,7 +4025,7 @@
return entryXmlDoc
-def getEntryXmlDoc(properties=None, contentFile=None,
+def getEntryXmlDoc(repo=None, objectTypeId=None, properties=None, contentFile=None,
contentType=None, contentEncoding=None):
"""
@@ -3987,6 +4033,8 @@
on the properties and, optionally, the contentFile provided.
"""
+ moduleLogger.debug('Inside getEntryXmlDoc')
+
entryXmlDoc = minidom.Document()
entryElement = entryXmlDoc.createElementNS(ATOM_NS, "entry")
entryElement.setAttribute('xmlns', ATOM_NS)
@@ -4044,6 +4092,7 @@
propsElement = entryXmlDoc.createElementNS(CMIS_NS, 'cmis:properties')
objectElement.appendChild(propsElement)
+ typeDef = None
for propName, propValue in properties.items():
"""
the name of the element here is significant: it includes the
@@ -4053,72 +4102,25 @@
I could do a lookup to the type definition, but that doesn't
seem worth the performance hit
"""
- propType = type(propValue)
- isList = False
- if (propType == list):
+ if (propValue == None or (type(propValue) == list and propValue[0] == None)):
+ # grab the prop type from the typeDef
+ if (typeDef == None):
+ moduleLogger.debug('Looking up type def for:' + objectTypeId)
+ typeDef = repo.getTypeDefinition(objectTypeId)
+ #TODO what to do if type not found
+ propType = typeDef.properties[propName].propertyType
+ elif type(propValue) == list:
propType = type(propValue[0])
- isList = True
-
- if (propType == CmisId):
- propElementName = 'cmis:propertyId'
- if isList:
- propValueStrList = []
- for val in propValue:
- propValueStrList.append(val)
- else:
- propValueStrList = [propValue]
- elif (propType == str):
- propElementName = 'cmis:propertyString'
- if isList:
- propValueStrList = []
- for val in propValue:
- propValueStrList.append(val)
- else:
- propValueStrList = [propValue]
- elif (propType == datetime.datetime):
- propElementName = 'cmis:propertyDateTime'
- if isList:
- propValueStrList = []
- for val in propValue:
- propValueStrList.append(val.isoformat())
- else:
- propValueStrList = [propValue.isoformat()]
- elif (propType == bool):
- propElementName = 'cmis:propertyBoolean'
- if isList:
- propValueStrList = []
- for val in propValue:
- propValueStrList.append(unicode(val).lower())
- else:
- propValueStrList = [unicode(propValue).lower()]
- elif (propType == int):
- propElementName = 'cmis:propertyInteger'
- if isList:
- propValueStrList = []
- for val in propValue:
- propValueStrList.append(unicode(val))
- else:
- propValueStrList = [unicode(propValue)]
- elif (propType == float):
- propElementName = 'cmis:propertyDecimal'
- if isList:
- propValueStrList = []
- for val in propValue:
- propValueStrList.append(unicode(val))
- else:
- propValueStrList = [unicode(propValue)]
else:
- propElementName = 'cmis:propertyString'
- if isList:
- propValueStrList = []
- for val in propValue:
- propValueStrList.append(unicode(val))
- else:
- propValueStrList = [unicode(propValue)]
+ propType = type(propValue)
+
+ propElementName, propValueStrList = getElementNameAndValues(propType, propName, propValue, type(propValue) == list)
propElement = entryXmlDoc.createElementNS(CMIS_NS, propElementName)
propElement.setAttribute('propertyDefinitionId', propName)
for val in propValueStrList:
+ if val == None:
+ continue
valElement = entryXmlDoc.createElementNS(CMIS_NS, 'cmis:value')
valText = entryXmlDoc.createTextNode(val)
valElement.appendChild(valText)
@@ -4126,3 +4128,96 @@
propsElement.appendChild(propElement)
return entryXmlDoc
+
+def getElementNameAndValues(propType, propName, propValue, isList=False):
+
+ moduleLogger.debug('Inside getElementNameAndValues')
+ moduleLogger.debug('propType:%s propName:%s isList:%s' % (propType, propName, isList))
+ if (propType == 'id' or propType == CmisId):
+ propElementName = 'cmis:propertyId'
+ if isList:
+ propValueStrList = []
+ for val in propValue:
+ propValueStrList.append(val)
+ else:
+ propValueStrList = [propValue]
+ elif (propType == 'string' or propType == str):
+ propElementName = 'cmis:propertyString'
+ if isList:
+ propValueStrList = []
+ for val in propValue:
+ propValueStrList.append(val)
+ else:
+ propValueStrList = [propValue]
+ elif (propType == 'datetime' or propType == datetime.datetime):
+ propElementName = 'cmis:propertyDateTime'
+ if isList:
+ propValueStrList = []
+ for val in propValue:
+ if val != None:
+ propValueStrList.append(val.isoformat())
+ else:
+ propValueStrList.append(val)
+ else:
+ if propValue != None:
+ propValueStrList = [propValue.isoformat()]
+ else:
+ propValueStrList = [propValue]
+ elif (propType == 'boolean' or propType == bool):
+ propElementName = 'cmis:propertyBoolean'
+ if isList:
+ propValueStrList = []
+ for val in propValue:
+ if val != None:
+ propValueStrList.append(unicode(val).lower())
+ else:
+ propValueStrList.append(val)
+ else:
+ if propValue != None:
+ propValueStrList = [unicode(propValue).lower()]
+ else:
+ propValueStrList = [propValue]
+ elif (propType == 'integer' or propType == int):
+ propElementName = 'cmis:propertyInteger'
+ if isList:
+ propValueStrList = []
+ for val in propValue:
+ if val != None:
+ propValueStrList.append(unicode(val))
+ else:
+ propValueStrList.append(val)
+ else:
+ if propValue != None:
+ propValueStrList = [unicode(propValue)]
+ else:
+ propValueStrList = [propValue]
+ elif (propType == 'decimal' or propType == float):
+ propElementName = 'cmis:propertyDecimal'
+ if isList:
+ propValueStrList = []
+ for val in propValue:
+ if val != None:
+ propValueStrList.append(unicode(val))
+ else:
+ propValueStrList.append(val)
+ else:
+ if propValue != None:
+ propValueStrList = [unicode(propValue)]
+ else:
+ propValueStrList = [propValue]
+ else:
+ propElementName = 'cmis:propertyString'
+ if isList:
+ propValueStrList = []
+ for val in propValue:
+ if val != None:
+ propValueStrList.append(unicode(val))
+ else:
+ propValueStrList.append(val)
+ else:
+ if propValue != None:
+ propValueStrList = [unicode(propValue)]
+ else:
+ propValueStrList = [propValue]
+
+ return propElementName, propValueStrList