From 9e8491008592273b8619949184c5f8a196028302 Mon Sep 17 00:00:00 2001
From: Nicolas Dumazet <nicolas.dumazet@nexedi.com>
Date: Thu, 10 Feb 2011 07:16:08 +0000
Subject: [PATCH] clean way to generate category accessors.

(Not yet used)


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@43251 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5Type/Core/CategoryProperty.py     | 157 +++++++++++++++++-
 .../ERP5Type/Core/DynamicCategoryProperty.py  |  19 ++-
 product/ERP5Type/Core/PropertySheet.py        |   6 +
 3 files changed, 175 insertions(+), 7 deletions(-)

diff --git a/product/ERP5Type/Core/CategoryProperty.py b/product/ERP5Type/Core/CategoryProperty.py
index cfc59543f0..66c5de64a7 100644
--- a/product/ERP5Type/Core/CategoryProperty.py
+++ b/product/ERP5Type/Core/CategoryProperty.py
@@ -29,7 +29,12 @@
 from AccessControl import ClassSecurityInfo
 from Products.ERP5Type import Permissions, PropertySheet
 from Products.ERP5Type.XMLObject import XMLObject
+
 from Products.ERP5Type.Accessor.Base import Getter as BaseGetter
+from Products.ERP5Type.Accessor import Category, Value, Alias
+from Products.ERP5Type.Utils import UpperCase
+
+from Products.ERP5Type.Core.StandardProperty import StandardProperty
 
 class CategoryProperty(XMLObject):
   """
@@ -66,9 +71,159 @@ class CategoryProperty(XMLObject):
     return context.newContent(portal_type=cls.portal_type,
                               reference=category_name)
 
+  getter_definition_dict = {
+      # normal accessors
+      'get%sList': Category.ListGetter,
+      'get%sSet': Category.SetGetter,
+      'get%sItemList': Category.ItemListGetter,
+      'getDefault%s': Category.DefaultGetter,
+      'get%s': Category.DefaultGetter,
+      # value accessors
+      'get%sValueList': Value.ListGetter,
+      'get%sValueSet': Value.SetGetter,
+      'get%sTitleList': Value.TitleListGetter,
+      'get%sTitleSet': Value.TitleSetGetter,
+      'get%sTranslatedTitleList': Value.TranslatedTitleListGetter,
+      'get%sTranslatedTitleSet': Value.TranslatedTitleSetGetter,
+      'get%sReferenceList': Value.ReferenceListGetter,
+      'get%sReferenceSet': Value.ReferenceSetGetter,
+      'get%sIdList': Value.IdListGetter,
+      'get%sIdSet': Value.IdSetGetter,
+      'get%sLogicalPathList': Value.LogicalPathListGetter,
+      'get%sLogicalPathSet': Value.LogicalPathSetGetter,
+      'get%sUidList': Value.UidListGetter,
+      'get%sUidSet': Value.UidSetGetter,
+      'get%sPropertyList': Value.PropertyListGetter,
+      'get%sPropertySet': Value.PropertySetGetter,
+      'getDefault%sValue': Value.DefaultGetter,
+      'get%sValue': Value.DefaultGetter,
+      'getDefault%sTitle': Value.DefaultTitleGetter,
+      'get%sTitle': Value.DefaultTitleGetter,
+      'getDefault%sTranslatedTitle': Value.DefaultTranslatedTitleGetter,
+      'get%sTranslatedTitle': Value.DefaultTranslatedTitleGetter,
+      'getDefault%sReference': Value.DefaultReferenceGetter,
+      'get%sReference': Value.DefaultReferenceGetter,
+      'getDefault%sUid': Value.DefaultUidGetter,
+      'get%sUid': Value.DefaultUidGetter,
+      'getDefault%sId': Value.DefaultIdGetter,
+      'get%sId': Value.DefaultIdGetter,
+      'getDefault%sTitleOrId': Value.DefaultTitleOrIdGetter,
+      'get%sTitleOrId': Value.DefaultTitleOrIdGetter,
+      'getDefault%sProperty': Value.DefaultPropertyGetter,
+      'get%sProperty': Value.DefaultPropertyGetter,
+      'getDefault%sLogicalPath': Value.DefaultLogicalPathGetter,
+      'get%sLogicalPath': Value.DefaultLogicalPathGetter,
+      'get%sTranslatedLogicalPath': Value.DefaultTranslatedLogicalPathGetter,
+  }
+  setter_definition_dict = {
+      # public 'reindexers'
+      'set%sValue': Alias.Reindex,
+      'set%sValueList': Alias.Reindex,
+      'set%sValueSet': Alias.Reindex,
+      'setDefault%sValue': Alias.Reindex,
+      'set%sUid': Alias.Reindex,
+      'set%sUidList': Alias.Reindex,
+      'set%sUidSet': Alias.Reindex,
+      'setDefault%sUid': Alias.Reindex,
+      # setters
+      '_set%sValue': Value.Setter,
+      '_categorySet%sValue': Value.Setter,
+      '_set%sValueList': Value.ListSetter,
+      '_categorySet%sValueList': Value.ListSetter,
+      '_set%sValueSet': Value.SetSetter,
+      '_categorySet%sValueSet': Value.SetSetter,
+      '_setDefault%sValue': Value.DefaultSetter,
+      '_categorySetDefault%sValue': Value.DefaultSetter,
+      # uid setters
+      '_set%sUid': Value.UidSetter,
+      '_categorySet%sUid': Value.UidSetter,
+      '_set%sUidList': Value.UidListSetter,
+      '_categorySet%sUidList': Value.UidListSetter,
+      '_set%sUidSet': Value.UidSetSetter,
+      '_categorySet%sUidSet': Value.UidSetSetter,
+      '_setDefault%sUid': Value.UidDefaultSetter,
+      '_categorySetDefault%sUid': Value.UidDefaultSetter,
+  }
+
+  @classmethod
+  def applyPropertyOnAccessorHolder(cls,
+                                    accessor_holder,
+                                    category_id,
+                                    category_tool):
+    # Create free text accessors.
+    # XXX These are only for backward compatibility.
+    storage_id = None
+    if category_id == 'group':
+      storage_id = 'group'
+    elif category_id == 'site':
+      storage_id = 'location'
+
+    StandardProperty.applyPropertyOnAccessorHolder(
+                      accessor_holder=accessor_holder,
+                      reference='%s_free_text' % category_id,
+                      elementary_type='text',
+                      is_multivalues=False,
+                      property_default='',
+                      storage_id=storage_id,
+                      read_permission=Permissions.AccessContentsInformation,
+                      write_permission=Permissions.ModifyPortalContent)
+
+    # Get read and write permission
+    if category_tool is not None:
+      cat_object = category_tool.get(category_id, None)
+    else:
+      cat_object = None
+    if cat_object is not None:
+      read_permission = Permissions.__dict__.get(
+                              cat_object.getReadPermission(),
+                              Permissions.AccessContentsInformation)
+      write_permission = Permissions.__dict__.get(
+                              cat_object.getWritePermission(),
+                              Permissions.ModifyPortalContent)
+    else:
+      read_permission = Permissions.AccessContentsInformation
+      write_permission = Permissions.ModifyPortalContent
+
+    # Actually create accessors
+    uppercase_reference = UpperCase(id)
+
+    # three special cases
+    accessor = Category.Tester('has' + uppercase_reference, id)
+    accessor_holder.registerAccessor(accessor, read_permission)
+
+    accessor_name = uppercase_reference[0].lower() + uppercase_reference[1:]
+    accessor = Value.ListGetter(accessor_name + 'Values', id)
+    accessor_holder.registerAccessor(accessor_holder, read_permission)
+    accessor = Value.IdListGetter(accessor_name + 'Ids', id)
+    accessor_holder.registerAccessor(accessor_holder, read_permission)
+
+    # then getters
+    for id_format, accessor_class in cls.getter_definition_dict.iteritems():
+      accessor_name = id_format % uppercase_reference
+
+      public_accessor = accessor_class(accessor_name, id)
+      accessor_holder.registerAccessor(public_accessor, read_permission)
+
+      # create the private getter on the fly instead of having a definition dict
+      # that's twice the size for the same info
+      accessor_name = '_category' + accessor_name[0].upper() + accessor_name[1:]
+      private_accessor = accessor_class(accessor_name, id)
+      accessor_holder.registerAccessor(private_accessor, read_permission)
+
+    # and setters
+    for id_format, accessor_class in cls.setter_definition_dict.iteritems():
+      accessor_name = id_format % uppercase_reference
+
+      accessor = accessor_class(accessor_name, id)
+      accessor_holder.registerAccessor(accessor, write_permission)
+
   security.declareProtected(Permissions.AccessContentsInformation,
                             'applyOnAccessorHolder')
-  def applyOnAccessorHolder(self, accessor_holder, expression_context):
+  def applyOnAccessorHolder(self, accessor_holder, expression_context, portal):
     reference = self.getReference()
     if reference is not None:
       accessor_holder._categories.append(reference)
+      category_tool = getattr(portal, 'portal_categories', None)
+      self.applyPropertyOnAccessorHolder(accessor_holder,
+                                         reference,
+                                         category_tool)
diff --git a/product/ERP5Type/Core/DynamicCategoryProperty.py b/product/ERP5Type/Core/DynamicCategoryProperty.py
index ecc00d3d8c..215024670f 100644
--- a/product/ERP5Type/Core/DynamicCategoryProperty.py
+++ b/product/ERP5Type/Core/DynamicCategoryProperty.py
@@ -30,9 +30,9 @@ from AccessControl import ClassSecurityInfo
 from Products.CMFCore.Expression import Expression
 
 from Products.ERP5Type import Permissions, PropertySheet
-from Products.ERP5Type.XMLObject import XMLObject
+from Products.ERP5Type.Core.CategoryProperty import CategoryProperty
 
-class DynamicCategoryProperty(XMLObject):
+class DynamicCategoryProperty(CategoryProperty):
   """
   Define a Dynamic Category Property Document for a ZODB Property
   Sheets (a dynamic category is defined by a TALES expression rather
@@ -73,10 +73,17 @@ class DynamicCategoryProperty(XMLObject):
 
   security.declareProtected(Permissions.AccessContentsInformation,
                             'applyOnAccessorHolder')
-  def applyOnAccessorHolder(self, accessor_holder, expression_context):
+  def applyOnAccessorHolder(self, accessor_holder, expression_context, portal):
     expression_string = self.getCategoryExpression()
     if expression_string is not None:
       expression = Expression(expression_string)
-      for category_id in expression(expression_context):
-        if category_id is not None:
-          accessor_holder._categories.append(category_id)
+      value = expression(expression_context)
+
+      category_tool = getattr(portal, 'portal_categories', None)
+      if not isinstance(value, (tuple, list)):
+        value = [value]
+      for category_id in value:
+        self.applyPropertyOnAccessorHolder(accessor_holder,
+                                           category_id,
+                                           category_tool)
+        accessor_holder._categories.append(category_id)
diff --git a/product/ERP5Type/Core/PropertySheet.py b/product/ERP5Type/Core/PropertySheet.py
index 26e20ed399..da572e826d 100644
--- a/product/ERP5Type/Core/PropertySheet.py
+++ b/product/ERP5Type/Core/PropertySheet.py
@@ -213,3 +213,9 @@ class PropertySheet(Folder):
                                                        constraint)
 
     return property_sheet
+
+  security.declareProtected(Permissions.AccessContentsInformation,
+                            'applyOnAccessorHolder')
+  def applyOnAccessorHolder(self, accessor_holder, expression_context, portal):
+    for property in self.contentValues():
+      property.applyOnAccessorHolder(accessor_holder, expression_context, portal)
-- 
2.30.9