Back to index

plone3  3.1.7
VariableSchemaSupport.py
Go to the documentation of this file.
00001 import sha
00002 
00003 from Products.Archetypes.ClassGen import ClassGenerator
00004 
00005 from AccessControl import ClassSecurityInfo
00006 from Acquisition import ImplicitAcquisitionWrapper
00007 from Globals import InitializeClass
00008 
00009 from Products.CMFCore import permissions
00010 from ExtensionClass import Base
00011 
00012 class VarClassGen(ClassGenerator):
00013     """A version of ClassGen that is able to generate a class' methods based on 
00014     an explicitly given schema.
00015     """
00016 
00017     def __init__(self, schema):
00018         self.schema = schema
00019 
00020     def updateMethods(self, klass):
00021         """Update the methods of the klass to support a new schema.
00022         
00023         This will re-generate methods.
00024         """
00025         self.generateMethods(klass, self.schema.fields())
00026 
00027 #
00028 # Instance-specific schemas. Note that Archeypes.Schema.compsition, which
00029 # is used in BaseObject, allows schemas to be composed dynamically on a per-
00030 # class basis, and is much more efficient and flexible (except that it cannot
00031 # do different schemas per-*instance*)
00032 #
00033 
00034 schemadict={}
00035 
00036 class VariableSchemaSupport(Base):
00037     """
00038     Mixin class to support instance-based schemas
00039     
00040     NOTE: This implementation has been found to be quite slow, because the
00041     hash is expensive to calculate and does not appear to work very well as
00042     a cache key.
00043     
00044     Attention: must be before BaseFolder or BaseContent in
00045     the inheritance list, e.g:
00046 
00047     class Blorf(VariableSchemaSupport, BaseContent):
00048         def getSchema():
00049             return some schema definition...
00050     """
00051 
00052     security = ClassSecurityInfo()
00053 
00054     security.declareProtected(permissions.View, 'Schema')
00055     def Schema(self):
00056         schema = self.getAndPrepareSchema()
00057         return ImplicitAcquisitionWrapper(schema, self)
00058 
00059     security.declareProtected(permissions.ManagePortal, 'getAndPrepareSchema')
00060     def getAndPrepareSchema(self):
00061         s = self.getSchema()
00062 
00063         # create a hash value out of the schema
00064         hash=sha.new(str([f.__dict__ for f in s.values()]) +
00065                      str(self.__class__)).hexdigest()
00066 
00067         if schemadict.has_key(hash): #ok we had that schema already, so take it
00068             schema=schemadict[hash]
00069         else: #make a new one and store it using the hash key
00070             schemadict[hash]=s
00071             schema=schemadict[hash]
00072             g=VarClassGen(schema)
00073             g.updateMethods(self.__class__) #generate the methods
00074 
00075         return schema
00076 
00077     # supposed to be overloaded. here the object can return its own schema
00078     security.declareProtected(permissions.View, 'getSchema')
00079     def getSchema(self):
00080         return self.schema
00081 
00082     security.declareProtected(permissions.ManagePortal,'setSchema')
00083     def setSchema(self, schema):
00084         self.schema=schema
00085 
00086 InitializeClass(VariableSchemaSupport)