Code: Select all
'''
User Fields
-----------
'''
# Standard
import logging
import collections
LOG = logging.getLogger(__name__)
TEXTFIELD_MASTERS = 'getTextFieldMasters'
FIELDMASTER_USER = 'com.sun.star.text.fieldmaster.User'
FIELDMASTER_TEMPLATE = 'com.sun.star.text.fieldmaster.User.%s'
class UserFields(collections.MutableMapping):
"""
Treat user field values sets as a key, value mapping which allows them to
be exposed with the same api as a traditional python dictionary
"""
def __init__(self, model):
"""h
Verify the provided model is a document model object and set the base
model attribute for this class.
:type model: object
:param model: Document model from uno api
:raises: TypeError
"""
if not hasattr(model, TEXTFIELD_MASTERS):
raise TypeError('Invalid document model object.')
self._model = model
def __dict__(self):
"""Return a representation of user fields as a true dictionary"""
return self._get_all()
def keys(self):
"""Return a list of keys"""
return self._get_all().keys()
def values(self):
"""Return a list of all values"""
return self._get_all().values()
@property
def model(self):
"""
Return the model object that this instance wraps
:type model: object
:param model: OpenOffice/LibreOffice model object
"""
return self._model
def _create_metadata(self, name, value, overwrite=True):
"""
Create new metadata in document. If the metadata field already exists
in the document, a warning will be logged and the value of the existing
field will be updated unless overwrite is set to False.
:type name: str
:param name: metadata field name
:type value: str
:param value: metadata field value
:type overwrite: bool
:param overwrite: Flag to overwrite existing value if field exists
"""
field_obj = self.model.getTextFieldMasters()
if not field_obj.hasByName(FIELDMASTER_TEMPLATE % name):
new_field = self.model.createInstance(FIELDMASTER_USER)
new_field.Name = name
new_field.Content = value
LOG.info('Created new user field "%s: %s"' % (name, value))
else:
if overwrite:
LOG.warning('A field with the name %s already exists' % name)
self._update_metadata(name, value)
else:
raise Exception('Metadata key %s already exists.' % name)
def _update_metadata(self, name, value, autocreate=True):
"""
Update metadata in document.
:type name: str
:param name: metadata field name
:type value: str
:param value: metadata field value
:type autocreate: bool
:param autocreate: Automatically create non-existant fields flag
:raises: KeyError
"""
field_obj = self.model.getTextFieldMasters()
if not field_obj.hasByName(FIELDMASTER_TEMPLATE % name):
if autocreate:
LOG.debug("Creating new field %s: %s" % (name, value))
self._create_metadata(name, value)
else:
raise KeyError('Metadata key %s does not exist.' % name)
else:
field = field_obj.getByName(FIELDMASTER_TEMPLATE % name)
field.Content = value
LOG.info("Updated metadata field %s to %s" % (name, value))
def _delete_metadata(self, name):
"""
Remove metadata in document
:type name: str
:param name: field name of metadata to remove from document
"""
field_obj = self.model.getTextFieldMasters()
if field_obj.hasByName(FIELDMASTER_TEMPLATE % name):
field = field_obj.getByName(FIELDMASTER_TEMPLATE % name)
field.dispose()
def _get_metadata(self, name, **kwargs):
"""
Retrieve metadata in document
:type name: str
:param name: field name of metadata to retrive value for
"""
default_value = kwargs.get('default_value', '')
raise_error = kwargs.get('raise_error', False)
field_obj = self.model.getTextFieldMasters()
fieldname = FIELDMASTER_TEMPLATE % name
if field_obj.hasByName(fieldname):
field = field_obj.getByName(fieldname)
return field.Content
else:
if raise_error:
raise KeyError('Metadata key %s does not exist.' % name)
else:
LOG.debug('Fieldname "%s" does not exist.' % name)
return default_value
def field_exists(self, name):
"""
Check whether that a metadata field exists in a document
:type name: str
:param name: field name of metadata to check existance of
:returns: True if field exists, otherwise False
:rtype: bool
"""
field_obj = self.model.getTextFieldMasters()
return field_obj.hasByName(FIELDMASTER_TEMPLATE % name)
def _get_all(self):
"""
Retrieve all metadata from a document
:returns: dictionary of user fields and values
:rtype: dict
"""
meta_dict = {}
field_obj = self.model.getTextFieldMasters()
field_names = field_obj.getElementNames()
for field_name in field_names:
if FIELDMASTER_USER in field_name:
field = field_obj.getByName(field_name)
meta_dict[field.Name] = field.Content
return meta_dict
def __getitem__(self, key):
try:
return self._get_metadata(key, raise_error=True)
except KeyError:
raise KeyError(key)
def __setitem__(self, key, value):
self._update_metadata(key, value, autocreate=True)
def __delitem__(self, key):
self._delete_metadata(key)
def __iter__(self):
return iter(self.__dict__())
def __len__(self):
return len(self.keys())
def __repr__(self):
return self._get_all()
def __str__(self):
return "<UserFields instance: %s>" % ", ".join(self.keys())