Back to index

plone3  3.1.7
sheet.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # PlonePAS - Adapt PluggableAuthService for use in Plone
00004 # Copyright (C) 2005 Enfold Systems, Kapil Thangavelu, et al
00005 #
00006 # This software is subject to the provisions of the Zope Public License,
00007 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this
00008 # distribution.
00009 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00010 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00011 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00012 # FOR A PARTICULAR PURPOSE.
00013 #
00014 ##############################################################################
00015 """
00016 Add Mutable Property Sheets and Schema Mutable Property Sheets to PAS
00017 
00018 also a property schema type registry which is extensible.
00019 
00020 """
00021 
00022 from types import StringTypes, IntType
00023 from types import LongType, FloatType, InstanceType
00024 
00025 from DateTime.DateTime import DateTime
00026 
00027 from zope.component import getUtility
00028 from Products.CMFCore.interfaces import ISiteRoot
00029 
00030 from Products.PluggableAuthService.utils import classImplements
00031 from Products.PluggableAuthService.UserPropertySheet import _SequenceTypes
00032 from Products.PluggableAuthService.UserPropertySheet import UserPropertySheet
00033 from Products.PlonePAS.interfaces.propertysheets import IMutablePropertySheet
00034 
00035 class PropertyValueError(ValueError): pass
00036 
00037 class PropertySchemaTypeMap(object):
00038 
00039     def __init__(self):
00040         self.tmap = {}
00041         self.tmap_order = []
00042 
00043     def addType(self, type_name, identifier, order=None):
00044         self.tmap[type_name] = identifier
00045         if order is not None and isinstance(order, int):
00046             self.tmap_order.insert(order, type_name)
00047         else:
00048             self.tmap_order.append(type_name)
00049 
00050     def getTypeFor(self, value):
00051         ptypes = [(ptype, self.tmap[ptype]) for ptype in self.tmap_order]
00052         for ptype, inspector in ptypes:
00053             if inspector(value):
00054                 return ptype
00055         raise TypeError, 'Invalid property type: %s' % type(value)
00056 
00057     def validate(self, property_type, value):
00058         inspector = self.tmap[property_type]
00059         return inspector(value)
00060 
00061 PropertySchema = PropertySchemaTypeMap()
00062 PropertySchema.addType('string', lambda x: x is None or type(x) in StringTypes)
00063 PropertySchema.addType('text', lambda x: x is None or type(x) in StringTypes)
00064 PropertySchema.addType('boolean', lambda x: 1)  # anything can be boolean
00065 PropertySchema.addType('int', lambda x:  x is None or type(x) is IntType)
00066 PropertySchema.addType('long', lambda x:  x is None or type(x) is LongType)
00067 PropertySchema.addType('float', lambda x:  x is None or type(x) is FloatType)
00068 PropertySchema.addType('lines', lambda x:  x is None or type(x) in _SequenceTypes)
00069 PropertySchema.addType('selection', lambda x:  x is None or type(x) in StringTypes)
00070 PropertySchema.addType('multiple selection', lambda x:  x is None or type(x) in _SequenceTypes)
00071 PropertySchema.addType('date', lambda x: 1 or x is None or type(x) is InstanceType and isinstance(x, DateTime))
00072 validateValue = PropertySchema.validate
00073 
00074 class MutablePropertySheet(UserPropertySheet):
00075 
00076 ##    def __init__(self, id, **kw):
00077 ##        UserPropertySheet.__init__(self, id, **kw)
00078 
00079     def validateProperty(self, id, value):
00080         if not self._properties.has_key(id):
00081             raise PropertyValueError, 'No such property found on this schema'
00082 
00083         proptype = self.getPropertyType(id)
00084         if not validateValue(proptype, value):
00085             raise PropertyValueError, ("Invalid value (%s) for "
00086                                        "property '%s' of type %s" %
00087                                        (value, id, proptype))
00088 
00089     def setProperty(self, user, id, value):
00090         self.validateProperty(id, value)
00091 
00092         self._properties[id] = value
00093         self._properties = self._properties
00094 
00095         # cascade to plugin
00096         provider = self._getPropertyProviderForUser(user)
00097         provider.setPropertiesForUser(user, self)
00098 
00099     def setProperties(self, user, mapping):
00100         prop_keys = self._properties.keys()
00101         prop_update = mapping.copy()
00102 
00103         for key, value in tuple(prop_update.items()):
00104             if key not in prop_keys:
00105                 prop_update.pop(key)
00106                 continue
00107             self.validateProperty(key, value)
00108 
00109         self._properties.update(prop_update)
00110 
00111         # cascade to plugin
00112         provider = self._getPropertyProviderForUser(user)
00113         provider.setPropertiesForUser(user, self)
00114 
00115     def _getPropertyProviderForUser(self, user):
00116         # XXX This assumes that the acl_users that we want is in the portal
00117         # root. This may not always be the case.
00118         portal = getUtility(ISiteRoot)
00119         return portal.acl_users._getOb(self._id)
00120 
00121 classImplements(MutablePropertySheet,
00122                 IMutablePropertySheet)
00123 
00124 class SchemaMutablePropertySheet(MutablePropertySheet): pass
00125 
00126 classImplements(SchemaMutablePropertySheet,
00127                 IMutablePropertySheet)