From b169d779abf1539a3c004da4d85c4fa9cf376839 Mon Sep 17 00:00:00 2001
From: Jean-Paul Smets <jp@nexedi.com>
Date: Sat, 5 Jan 2008 22:43:14 +0000
Subject: [PATCH] Moved code to separate files.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@18606 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5Type/DocumentationHelper.py       | 998 ------------------
 .../AccessorMethodDocumentationHelper.py      | 119 +++
 .../BusinessTemplateDocumentationHelper.py    | 101 ++
 .../CallableDocumentationHelper.py            |  36 +
 .../ClassDocumentationHelper.py               |  36 +
 .../ClassMethodDocumentationHelper.py         |  67 ++
 .../DCWorkflowDocumentationHelper.py          | 136 +++
 .../DocumentationHelper.py                    | 143 +++
 .../DocumentationSection.py                   |  56 +
 .../InstancePropertyDocumentationHelper.py    |  36 +
 .../ERP5Type/DocumentationHelper/Legacy.py    | 302 ++++++
 .../PortalDocumentationHelper.py              |  36 +
 .../PortalTypeDocumentationHelper.py          |  91 ++
 .../PortalTypeInstanceDocumentationHelper.py  | 228 ++++
 .../PropertyDocumentationHelper.py            |  37 +
 .../WorkflowMethodDocumentationHelper.py      | 101 ++
 .../ERP5Type/DocumentationHelper/__init__.py  |  45 +
 17 files changed, 1570 insertions(+), 998 deletions(-)
 delete mode 100644 product/ERP5Type/DocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/AccessorMethodDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/BusinessTemplateDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/CallableDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/ClassDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/ClassMethodDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/DCWorkflowDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/DocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/DocumentationSection.py
 create mode 100644 product/ERP5Type/DocumentationHelper/InstancePropertyDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/Legacy.py
 create mode 100644 product/ERP5Type/DocumentationHelper/PortalDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/PortalTypeDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/PortalTypeInstanceDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/PropertyDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/WorkflowMethodDocumentationHelper.py
 create mode 100644 product/ERP5Type/DocumentationHelper/__init__.py

diff --git a/product/ERP5Type/DocumentationHelper.py b/product/ERP5Type/DocumentationHelper.py
deleted file mode 100644
index 99d0e3bb87..0000000000
--- a/product/ERP5Type/DocumentationHelper.py
+++ /dev/null
@@ -1,998 +0,0 @@
-from Acquisition import Implicit
-from AccessControl import ClassSecurityInfo
-from Globals import InitializeClass
-
-from Products.CMFCore.utils import getToolByName
-
-from Products.ERP5Type.Accessor.Accessor import Accessor
-from Products.ERP5Type.Base import WorkflowMethod
-from Products.ERP5Type import Permissions
-
-class DocumentationSection(Implicit):
-
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  def __init__(self, id, title, class_name, uri_list):
-    self.id = id
-    self.title = title
-    self.class_name = class_name
-    self.uri_list = uri_list
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getClassName')
-  def getClassName(self):
-    return self.class_name
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getURIList')
-  def getURIList(self):
-    return self.uri_list
-
-  # more API needed XXX
-
-InitializeClass(DocumentationSection)
-
-class DocumentationHelper(Implicit):
-  """
-    Example URIs
-
-    person_module/23
-    person_module/23#title
-    person_module/23#getTitle
-    portal_worklows/validation_workflow
-    portal_worklows/validation_workflow/states/draft
-    portal_worklows/validation_workflow/states/draft#title
-    Products.ERP5Type.Document.Person.notify
-    Products.ERP5Type.Document.Person.isRAD
-    portal_types/Person
-    portal_types/Person/actions#view
-  """
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  # Methods to override
-  def __init__(self, uri):
-    self.uri = uri
-
-  def getDocumentedObject(self):
-    if '/' in self.uri and '#' not in self.uri:
-      # URI refers to a portal object
-      # and is a relative URL
-      documented_object = self.getPortalObject().portal_categories.resolveCategory(self.uri)  
-    elif '/' in self.uri and '#' in self.uri:
-      url, method = self.uri.split('#') 
-      # if / in method, method's not an acessor but a workflow method
-      documented_object = self.getPortalObject().unrestrictedTraverse(url)
-      if '/' not in method:
-        documented_object = self.getPortalObject().unrestrictedTraverse(url)
-        documented_object = getattr(documented_object, method, None)
-      else:
-        wf_url = 'portal_workflow/%s' % method
-        documented_object = self.getPortalObject().unrestrictedTraverse(wf_url)
-    else:
-      # URI refers to a python class / method
-      import imp
-      module_list = self.uri.split('.')
-      base_module = module_list[0]
-      if base_module == 'Products':
-        # For now, we do not even try to import
-        # or locate objects which are not in Products
-        import Products
-        documented_object = Products
-        for key in module_list[1:]:
-          LOG('loop in module_list', 0, repr(documented_object))
-          documented_object = getattr(documented_object, key)
-      else:
-        raise NotImplemented
-        #fp, pathname, description = imp.find_module(base_module)
-        #documented_object = imp.load_module(fp, pathname, description)
-
-    return documented_object
-
-  def getTitle(self):
-    """
-    Returns the title of the documentation helper
-    (ex. class name)
-    """
-    raise NotImplemented
-
-  def getType(self):
-    """
-    Returns the type of the documentation helper
-    (ex. Class, float, string, Portal Type, etc.)
-    """
-    raise NotImplemented
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getSectionList')
-  def getSectionList(self):
-    """
-    Returns a list of documentation sections
-    """
-    raise NotImplemented
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getURI')
-  def getURI(self):
-    """
-    Returns a URI to later access this documentation
-    from portal_classes
-    """
-    return self.uri
-
-  # Generic methods which all subclasses should inherit
-  security.declareProtected(Permissions.AccessContentsInformation, 'getClassName')
-  def getClassName(self):
-    """
-    Returns our own class name
-    """
-    return self.__class__.__name__
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'view')
-  def view(self):
-    """
-    Renders the documentation with a standard form
-    ex. PortalTypeInstanceDocumentationHelper_view
-    """
-    return getattr(self, '%s_view' % self.getClassName())()
-
-  security.declareProtected(Permissions.AccessContentsInformation, '__call__')
-  def __call__(self):
-    return self.view()
-
-InitializeClass(DocumentationHelper)
-
-class PortalTypeInstanceDocumentationHelper(DocumentationHelper):
-  """
-    Provides access to all documentation information
-    of a portal type instance.
-  """
-
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  def __init__(self, uri):
-    self.uri = uri
-
-  def getInstance(self):
-    return self.getPortalObject().restrictedTraverse(self.uri)
-
-  # API Implementation
-  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
-  def getTitle(self):
-    """
-    Returns the title of the documentation helper
-    """
-    return self.getInstance().getTitleOrId()
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
-  def getType(self):
-    """
-    Returns the type of the documentation helper
-    """
-    return "Portal Type Instance"
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getSectionList' )
-  def getSectionList(self):
-    """
-    Returns a list of documentation sections
-    """
-    return [
-      #DocumentationSection(
-        #id='instance_property',
-        #title='Instance Properties',
-        #class_name='InstancePropertyDocumentationHelper',
-        #uri_list=self.getClassPropertyURIList(),
-      #),
-      DocumentationSection(
-        id='workflow_method',
-        title='Workflow Method',
-        class_name='WorkflowMethodDocumentationHelper',
-        uri_list=self.getWorkflowMethodURIList(inherited=0),
-      ),
-      DocumentationSection(
-        id='accessor',
-        title='Accessor',
-        class_name='AccessorMethodDocumentationHelper',
-        uri_list=self.getAccessorMethodURIList(inherited=0),
-      ),
-      DocumentationSection(
-        id='class_method',
-        title='Class Methods',
-        class_name='ClassMethodDocumentationHelper',
-        uri_list=self.getClassMethodURIList(inherited=0),
-      ).__of__(self.getInstance()),
-    ]
-
-  # Specific methods
-  security.declareProtected( Permissions.AccessContentsInformation, 'getPortalType' )
-  def getPortalType(self):
-    """
-    """
-    return self.getInstance().getPortalType()
-
-  def _getPropertyHolder(self):
-    from Products.ERP5Type.Base import Base
-    return Base.aq_portal_type[(self.getPortalType(), self.getInstance().__class__)]
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getAccessorMethodItemList' )
-  def getAccessorMethodItemList(self):
-    """
-    """
-    return self._getPropertyHolder().getAccessorMethodItemList()
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getAccessorMethodIdList' )
-  def getAccessorMethodIdList(self):
-    """
-    """
-    return self._getPropertyHolder().getAccessorMethodIdList()
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getAccessorMethodURIList' )
-  def getAccessorMethodURIList(self, inherited=1, local=1):
-    """
-    Returns a list of URIs to accessor methods
-    """
-    method_id_list = self.getAccessorMethodIdList(inherited=inherited, local=local)
-    klass = self.getInstance().__class__
-    class_name = klass.__name__
-    module = klass.__module__
-    uri_prefix = '%s.%s.' % (module, class_name)
-    return map(lambda x: '%s%s' % (uri_prefix, x), method_id_list)
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getWorkflowMethodItemList' )
-  def getWorkflowMethodItemList(self):
-    """
-    """
-    return self._getPropertyHolder().getWorkflowMethodItemList()
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getWorkflowObject' )
-  def getWorkflowObject(self):
-    """
-    """
-    return self._getPropertyHolder()
-  
-  security.declareProtected(Permissions.AccessContentsInformation, 'getWorkflowMethodIdList' )
-  def getWorkflowMethodIdList(self):
-    """
-    """
-    return self._getPropertyHolder().getWorkflowMethodIdList()    
-
-  def getWorkflowMethodURIList(self, inherited=1, local=1):
-    """
-    Returns a list of URIs to workflow  methods
-    """
-    method_id_list = self.getWorkflowMethodIdList(inherited=inherited, local=local)
-    klass = self.getInstance().__class__
-    class_name = klass.__name__
-    module = klass.__module__
-    uri_prefix = '%s.%s.' % (module, class_name)
-    return map(lambda x: '%s%s' % (uri_prefix, x), method_id_list)
-
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getActionMethodItemList' )
-  def getActionMethodItemList(self):
-    """
-    """
-    return self._getPropertyHolder().getActionMethodItemList()
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getActionMethodIdList' )
-  def getActionMethodIdList(self):
-    """
-    """
-    return self._getPropertyHolder().getActionMethodIdList()
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getClassMethodItemList' )
-  def getClassMethodItemList(self, inherited=1, local=1):
-    """
-    Return a list of tuple (id, method) for every class method
-    """
-    klass = self.getInstance().__class__
-    return self._getPropertyHolder().getClassMethodItemList(klass, inherited=inherited, local=local)
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getClassMethodIdList' )
-  def getClassMethodIdList(self, inherited=1, local=1):
-    """
-    Return a list of tuple (id, method) for every class method
-    """
-    klass = self.getInstance().__class__
-    return self._getPropertyHolder().getClassMethodIdList(klass, inherited=inherited, local=local)
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getClassMethodURIList' )
-  def getClassMethodURIList(self, inherited=1, local=1):
-    """
-    Returns a list of URIs to class methods
-    """
-    method_id_list = self.getClassMethodIdList(inherited=inherited, local=local)
-    klass = self.getInstance().__class__
-    class_name = klass.__name__
-    module = klass.__module__
-    uri_prefix = '%s.%s.' % (module, class_name)
-    return map(lambda x: '%s%s' % (uri_prefix, x), method_id_list)
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getClassPropertyItemList' )
-  def getClassPropertyItemList(self, inherited=1, local=1):
-    """
-    Return a list of tuple (id, method) for every class method
-    """
-    klass = self.getInstance().__class__
-    return self._getPropertyHolder().getClassPropertyItemList(klass, inherited=inherited, local=local)
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getClassPropertyIdList' )
-  def getClassPropertyIdList(self, inherited=1, local=1):
-    """
-    Return a list of tuple (id, method) for every class method
-    """
-    klass = self.getInstance().__class__
-    return self._getPropertyHolder().getClassPropertyIdList(klass, inherited=inherited, local=local)
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getGeneratedPropertyIdList' )
-  def getGeneratedPropertyIdList(self):
-    """
-    """
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getGeneratedBaseCategoryIdList' )
-  def getGeneratedBaseCategoryIdList(self):
-    """
-    """
-
-InitializeClass(PortalTypeInstanceDocumentationHelper)
-
-class PortalDocumentationHelper(DocumentationHelper):
-  """
-  """
-
-class ClassDocumentationHelper(DocumentationHelper):
-  """
-  """
-
-class AccessorDocumentationHelper(DocumentationHelper):
-  """
-  """
-
-class ClassMethodDocumentationHelper(DocumentationHelper):
-  """
-    Provides documentation about a class method
-  """
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getDescription')
-  def getDescription(self):
-    return self.getDocumentedObject().__doc__
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
-  def getType(self):
-    """
-    Returns the type of the documentation helper
-    """
-    return "Class Method"
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
-  def getTitle(self):
-    """
-    Returns the type of the documentation helper
-    """
-    return self.getDocumentedObject().__name__
-
-InitializeClass(ClassMethodDocumentationHelper)
-
-class AccessorMethodDocumentationHelper(DocumentationHelper):
-  """
-    Provides documentation about an accessor
-  """
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  def __init__(self, uri):
-    self.uri = uri
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getDescription')
-  def getDescription(self):
-    return self.getDocumentedObject().__doc__
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
-  def getType(self):
-    """
-    Returns the type of the documentation helper
-    """
-    return self.getDocumentedObject().func_code.__module__
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
-  def getTitle(self):
-    """
-    Returns the title of the documentation helper
-    """
-    return self.getDocumentedObject().__name__
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getArgCount' )
-  def getArgCount(self):
-    """
-    Returns the number of args of the accessor
-    """
-    return self.getDocumentedObject().func_code.co_argcount
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getVarNames' )
-  def getVarNames(self):
-    """
-    Returns the list of args of the accessor
-    """
-    return self.getDocumentedObject().func_code.co_varnames
-
-
-InitializeClass(AccessorMethodDocumentationHelper)
-
-class CallableDocumentationHelper(DocumentationHelper):
-  """
-  """
-
-class InstancePropertyDocumentationHelper(DocumentationHelper):
-  """
-  """
-
-class PropertyDocumentationHelper(DocumentationHelper):
-  """
-  """
-
-class WorkflowMethodDocumentationHelper(DocumentationHelper):
-  """
-    Provides documentation about a workflow method
-  """
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  def __init__(self, uri):
-    self.uri = uri
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getDescription')
-  def getDescription(self):
-    return self.getDocumentedObject().__dict__['description']
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getType' )
-  def getType(self):
-    """
-    Returns the type of the documentation helper
-    """
-    return self.getDocumentedObject().__module__
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getTitle' )
-  def getTitle(self):
-    """
-    Returns the title of the documentation helper
-    """
-    return self.getDocumentedObject().__dict__['title']
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getDestinationState' )
-  def getDestinationState(self):
-    """
-    Returns the destination_state of the transition workflow method
-    """
-    return self.getDocumentedObject().__dict__['new_state_id']
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getTriggerType' )
-  def getTriggerType(self):
-    """
-    Returns the trigger type of the workflow method
-    """
-    TT = ['Automatic','Initiated by user action','Initiated by WorkflowMethod']
-    TT_id = self.getDocumentedObject().__dict__['trigger_type']
-    return TT[TT_id]
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getLocalRoles' )
-  def getLocalRoles(self):
-    """
-    Returns the local roles of the workflow method
-    """
-    return self.getDocumentedObject().__ac_local_roles__
-
-  security.declareProtected(Permissions.AccessContentsInformation, 'getAvailableStateIds' )
-  def getAvailableStateIds(self):
-    """
-    Returns available states in the workflow
-    """
-    return self.getDocumentedObject().getAvailableStateIds()
-
-InitializeClass(WorkflowMethodDocumentationHelper)
-
-class DCWorkflowDocumentationHelper(DocumentationHelper):
-  """
-    Provides access to all documentation information
-    of a workflow.
-  """
-
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  # API Implementation
-  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
-  def getTitle(self):
-    """
-    Returns the title of the documentation helper
-    """
-    return self.getDocumentedObject().getTitleOrId()
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
-  def getType(self):
-    """
-    Returns the type of the documentation helper
-    """
-    return "DC Workflow"
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getSectionList' )
-  def getSectionList(self):
-    """
-    Returns a list of documentation sections
-    """
-    return map(lambda x: x.__of__(self), [
-      DocumentationSection(
-        id='state',
-        title='Workflow States',
-        class_name='DCWorkflowStateDocumentationHelper',
-        uri_list=self.getStateURIList(),
-      ),
-      DocumentationSection(
-        id='transition',
-        title='Workflow Transitions',
-        class_name='DCWorkflowTransitionDocumentationHelper',
-        uri_list=self.getStateURIList(),
-      ),
-      DocumentationSection(
-        id='variable',
-        title='Workflow Variables',
-        class_name='DCWorkflowVariableDocumentationHelper',
-        uri_list=self.getVariableURIList(),
-      ),
-      DocumentationSection(
-        id='variable',
-        title='Workflow Permissions',
-        class_name='PermissionDocumentationHelper',
-        uri_list=self.getPermissionURIList(),
-      ),
-    ])
-
-  # Specific methods
-  security.declareProtected( Permissions.AccessContentsInformation, 'getDescription' )
-  def getDescription(self):
-    """
-    Returns the title of the documentation helper
-    """
-    raise NotImplemented
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getVariableURIList' )
-  def getVariableURIList(self):
-    """
-    """
-    raise NotImplemented
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getStateURIList' )
-  def getStateURIList(self):
-    """
-    """
-    raise NotImplemented
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getVariableURIList' )
-  def getVariableURIList(self):
-    """
-    """
-    raise NotImplemented
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getPermissionURIList' )
-  def getPermissionURIList(self):
-    """
-    """
-    raise NotImplemented
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getGraphImageURL' )
-  def getGraphImageURL(self):
-    """
-      Returns a URL to a graphic representation of the workflow
-    """
-    raise NotImplemented
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getGraphImageData' )
-  def getGraphImageData(self):
-    """
-      Returns the graphic representation of the workflow as a PNG file
-    """
-    raise NotImplemented
-
-InitializeClass(DCWorkflowDocumentationHelper)
-
-class BusinessTemplateDocumentationHelper(DocumentationHelper):
-  """
-    Provides access to all documentation information
-    of a business template.
-  """
-
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  # API Implementation
-  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
-  def getTitle(self):
-    """
-    Returns the title of the documentation helper
-    """
-    return self.getDocumentedObject().getTitleOrId()
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
-  def getType(self):
-    """
-    Returns the type of the documentation helper
-    """
-    return "Business Template"
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getSectionList' )
-  def getSectionList(self):
-    """
-    Returns a list of documentation sections
-    """
-    return map(lambda x: x.__of__(self), [
-      DocumentationSection(
-        id='portal_type',
-        title='Portal Types',
-        class_name='PortalTypeDocumentationHelper',
-        uri_list=self.getPortalTypeURIList(),
-      ),
-      DocumentationSection(
-        id='workflow',
-        title='Workflows',
-        class_name='DCWorkflowDocumentationHelper',
-        uri_list=self.getDCWorkflowURIList(),
-      ),
-      DocumentationSection(
-        id='interaction',
-        title='Interaction Workflows',
-        class_name='InteractionWorkflowStateDocumentationHelper',
-        uri_list=self.getInteractionWorkflowURIList(),
-      ),
-      DocumentationSection(
-        id='skin_folder',
-        title='Skin Folders',
-        class_name='SkinFolderDocumentationHelper',
-        uri_list=self.getSkinFolderURIList(),
-      ),
-    ])
-
-  # Specific methods
-  security.declareProtected( Permissions.AccessContentsInformation, 'getDescription' )
-  def getDescription(self):
-    """
-    Returns the title of the documentation helper
-    """
-    raise NotImplemented
-
-
-InitializeClass(BusinessTemplateDocumentationHelper)
-
-
-class PortalTypeDocumentationHelper(DocumentationHelper):
-  """
-    Provides access to all documentation information
-    of a portal type. Accessors and methods are documented
-    by generating a temporary instance which provides
-    an access to the property holder and allows
-    reusing PortalTypeInstanceDocumentationHelper
-  """
-
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  # API Implementation
-  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
-  def getTitle(self):
-    """
-    Returns the title of the documentation helper
-    """
-    return self.getDocumentedObject().getTitleOrId()
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
-  def getType(self):
-    """
-    Returns the type of the documentation helper
-    """
-    return "Portal Type"
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getSectionList' )
-  def getSectionList(self):
-    """
-    Returns a list of documentation sections
-    """
-    return map(lambda x: x.__of__(self), [
-      DocumentationSection(
-        id='action',
-        title='Actions',
-        class_name='ActionDocumentationHelper',
-        uri_list=self.getActionURIList(),
-      ),
-      DocumentationSection(
-        id='local_role',
-        title='Local Role Definitions',
-        class_name='LocalRoleDefinitionDocumentationHelper',
-        uri_list=self.getDCWorkflowURIList(),
-      ),
-      # XXX - add here all sections of a portal type instance
-    ])
-
-  # Specific methods
-  security.declareProtected( Permissions.AccessContentsInformation, 'getDescription' )
-  def getDescription(self):
-    """
-    Returns the title of the documentation helper
-    """
-    raise NotImplemented
-
-
-InitializeClass(PortalTypeDocumentationHelper)
-
-
-
-
-
-#############################################################################
-#############################################################################
-
-if 0:
-  if 0:
-    static_method_list = []    # Class methods
-    static_property_list = []  # Class attributes
-    dynamic_method_list = []   # Workflow methods
-    dynamic_property_list = [] # Document properties
-    dynamic_category_list = [] # Categories
-    dynamic_accessor_list = [] # Accessors
-
-
-  security.declareProtected( Permissions.ManagePortal, 'asDocumentationHelper' )
-  def asDocumentationHelper(self, item_id=None):
-    """
-      Fills and return a DocHelper object from context.
-      Overload this in any object the has to fill the DocHelper in its own way.
-
-      item_id : If specified, the documented item will be
-                getattr(self, item_title) if it exists, otherwise None will
-                be returned.
-
-      TODO:
-       - Check that filtering is correct : display only and every things
-         defined on the class itself.
-       - Add a list of all accessible things in the documented item context
-         (heritated methods & attributes) in a light way that still allows to
-         link directly to the corresponding documentation.
-       - Rewrite accessor generation system so that it can generate accessor
-         names when given a property/category.
-
-       KEEPMEs:
-         There are pieces of code in this function that can have interesting
-         results, but who are also very verbose. They are disabled (commented
-         out) by default, but they should be kept.
-         Explanation of the interest :
-         The accessors are gathered from 2 sources : the ones defined on the
-         PortalType, and systematically generated names, and tested for
-         presence on the documented item.
-         There are 4 cases then :
-         -Accessor whose name was generated exists both on the PortalType and
-          on the documented item. That's normal.
-         -Accessor whose name was generated exists neither on the PortalType
-          nor on the documented item. That's normal, but could mean that the
-          accessor name generator isn't optimal.
-         -Accessor whose name was generated is found on the object but not on
-          the PortalType. This is a problem.
-         -Accessors gathered from PortalType aren't all found by guessing
-          systematically the names. That means that the accessor name
-          generation is not perfect and requires improvement.
-
-         nb: the accessors are gathered from 2 sources, the first is somehow
-         accidental when searching for workflow methods defined on the
-         PortalType, and are browsed a second time to be able to group them
-         by property or category.
-    """
-    if item_id is None:
-      documented_item = self
-      item_id = documented_item.getTitle()
-    elif getattr(self, item_id, None) is not None:
-      documented_item = getattr(self, item_id)
-    else:
-      return None
-
-    # The documented object is an instance (or not) of this class.
-    item_class = getattr(documented_item, '__bases__', None) is None \
-                 and documented_item.__class__ \
-                 or documented_item
-
-    static_method_list = []    # Class methods
-    static_property_list = []  # Class attributes
-    dynamic_method_list = []   # Workflow methods
-    dynamic_property_list = [] # Document properties
-    dynamic_category_list = [] # Categories
-    dynamic_accessor_list = [] # Accessors
-    found_accessors = {}       # Accessor names : filled by PortalType-level
-                               # scan, and used in PropertySheet-level scan.
-    dochelper = newTempDocumentationHelper(self.getParentValue(), self.getId(),
-                  title=item_id, type=item_class.__name__,
-                  description=inspect.getdoc(documented_item),
-                )
-    dochelper.setInheritanceList([x.__name__ for x in item_class.__bases__])
-    try:
-      dochelper.setSourcePath(inspect.getsourcefile(item_class))
-    except (IOError, TypeError):
-      pass
-    # dochelper.setSecurity() # (maybe) TODO: Add class instance security gthering.
-
-    # Class-level method & properties
-    for k, v in item_class.__dict__.items():
-      subdochelper = newTempDocumentationHelper(dochelper, k,
-                  title=k, description=inspect.getdoc(v),
-                  security=repr(getattr(documented_item, '%s__roles__' % (k,),None)))
-      try:
-        subdochelper.setType(v.__class__.__name__)
-      except AttributeError:
-        pass
-      try:
-        subdochelper.setSourcePath(inspect.getsourcefile(v))
-      except (IOError, TypeError), err:
-        pass
-      try:
-        subdochelper.setSourceCode(inspect.getsource(v))
-      except (IOError, TypeError), err:
-        pass
-      try:
-        subdochelper.setArgumentList(inspect.getargspec(v))
-      except (IOError, TypeError), err:
-        pass
-      if subdochelper.getType() in ('function',): # This is a method
-        static_method_list.append(subdochelper)
-      elif subdochelper.getType() in ('int', 'float', 'long', 'str', 'tuple', 'dict', 'list') \
-           and not subdochelper.getTitle().startswith('__'): # This is a property
-        subdochelper.setContent(pformat(v))
-        static_property_list.append(subdochelper)
-      # FIXME: Is there any other interesting type ?
-
-    # PortalType-level methods
-    # XXX: accessing portal_type directly because accessors are not generated on instances
-    if getattr(documented_item, 'portal_type', None) is not None:
-      for k, v in Base.aq_portal_type[documented_item.portal_type].__dict__.items():
-        if callable(v) and not (k.startswith('_base') or k.startswith('_category')):
-          subdochelper = newTempDocumentationHelper(dochelper, k,
-                    title=k, description=inspect.getdoc(v),
-                    security=repr(getattr(documented_item, '%s__roles__' % (k,),None)))
-          try:
-            my_type = v.__class__.__name__
-            subdochelper.setType(my_type)
-          except AttributeError:
-            pass
-          if 'Setter' not in my_type and \
-             'Getter' not in my_type and \
-             'Tester' not in my_type: # Accessors are handled separatelly.
-            dynamic_method_list.append(subdochelper)
-# KEEPME: usefull to track the differences between accessors defined on
-# PortalType and the one detected on the documented item.
-#          else:
-#            found_accessors[k] = v
-
-    def generatePropertyAccessorNameList(property):
-      """
-        Generates the possible accessor names for given property.
-
-        FIXME: Should not exist here, but as accessor generation system.
-      """
-      from Products.ERP5Type.Utils import UpperCase
-      res=[]
-      cased_id = UpperCase(property['id'])
-      for hidden in ('', '_'):
-        for getset in ('get', 'set', 'has'): # 'is',
-          for default in ('', 'Default', 'Translated'):
-            for value in ('', 'Value', 'TranslationDomain'):
-              for multivalued in ('', 'List', 'Set'):
-                res.append('%s%s%s%s%s%s' % (hidden, getset, default, cased_id, value, multivalued))
-      if property.has_key('acquired_property_id') and \
-         property['type'] == 'content':
-        for aq_property_id in property['acquired_property_id']:
-          cased_id = UpperCase('%s_%s' % (property['id'], aq_property_id))
-          for hidden in ('', '_'):
-            for getset in ('get', 'set'):
-              for default in ('', 'Default'):
-                for multivalued in ('', 'List'):
-                  res.append('%s%s%s%s%s' % (hidden, getset, default, cased_id, multivalued))
-      return res
-
-    def generateCategoryAccessorNameList(category):
-      """
-        Generates the possible accessor names for given category.
-
-        FIXME: Should not exist here, but as accessor generation system.
-      """
-      from Products.ERP5Type.Utils import UpperCase
-      cased_id=UpperCase(category)
-      res=['%s%sIds' % (cased_id[0].lower(), cased_id[1:]),
-           '%s%sValues' % (cased_id[0].lower(), cased_id[1:])]
-      for hidden in ('', '_'):
-        for default in ('', 'Default'):
-          for multivalued in ('', 'List', 'Set'):
-            for attribute in ('', 'TranslatedTitle', 'Uid', 'LogicalPath', 'Id', 'TitleOrId', 'Reference', 'Title'):
-              res.append('%sget%s%s%s%s' % (hidden, default, cased_id, attribute, multivalued))
-            for attribute in ('', 'Value', 'Uid'):
-              res.append('%sset%s%s%s%s' % (hidden, default, cased_id, attribute, multivalued))
-      return res
-
-    def accessorAsDocumentationHelper(accessor):
-      """
-        Generates a documentation helper about a given accessor.
-      """
-      accessor_dochelper = newTempDocumentationHelper(subdochelper, accessor_name,
-                                                      title=accessor_name,
-                                                      description=inspect.getdoc(accessor))
-      try:
-        accessor_dochelper.setSourcePath(inspect.getsourcefile(accessor))
-      except (IOError, TypeError), err:
-        pass
-      try:
-        accessor_dochelper.setSourceCode(inspect.getsource(accessor))
-      except (IOError, TypeError), err:
-        pass
-# KEEPME: usefull to track the differences between accessors defined on
-# PortalType and the one detected on the documented item.
-#      if found_accessors.has_key(accessor_name):
-#        del(found_accessors[accessor_name])
-#      else:
-#        LOG('asDocumentationHelper', 0,
-#            'Found but not in the accessor list : %s of type %s' % \
-#            (accessor_name, accessor.__class__.__name__))
-      return accessor_dochelper
-
-    # PropertySheet-level properties & categories
-    # Also handles accessors.
-    seen_properties=[]
-    seen_categories=[]
-    if getattr(documented_item, 'property_sheets', None) is not None:
-      for property_sheet in documented_item.property_sheets:
-        if getattr(property_sheet, '_properties', None) is not None:
-          for property in property_sheet._properties:
-            if property in seen_properties:
-              continue
-            seen_properties.append(property)
-            subdochelper = newTempDocumentationHelper(dochelper, k,
-                      title=property['id'], description=property['description'],
-                      type=property['type'], security=property['mode'],
-                      content=pformat(documented_item.getProperty(property['id'])))
-            subdochelper_dynamic_accessor_list = []
-            for accessor_name in generatePropertyAccessorNameList(property):
-              accessor = getattr(item_class, accessor_name, getattr(documented_item, accessor_name, None))
-              # First get it on the class, and if not on the instance, thereby among dynamic accessors.
-              if accessor is not None:
-                subdochelper_dynamic_accessor_list.append(accessorAsDocumentationHelper(accessor))
-            subdochelper_dynamic_accessor_list.sort()
-            subdochelper.setDynamicAccessorList(subdochelper_dynamic_accessor_list)
-            dynamic_accessor_list.append(subdochelper)
-            if getattr(documented_item, property['id'], None) is not None:
-              dynamic_property_list.append(subdochelper)
-        if getattr(property_sheet, '_categories', None) is not None:
-          for category in property_sheet._categories:
-            if category in seen_categories:
-              continue
-            seen_categories.append(category)
-            subdochelper = newTempDocumentationHelper(dochelper, category, title=category,
-                      content=pformat(documented_item.getCategoryMembershipList(category)))
-            subdochelper_dynamic_accessor_list = []
-            for accessor_name in generateCategoryAccessorNameList(category):
-              accessor = getattr(item_class, accessor_name, getattr(documented_item, accessor_name, None))
-              # First get it on the class, and if not on the instance, thereby among dynamic accessors.
-              if accessor is not None:
-                subdochelper_dynamic_accessor_list.append(accessorAsDocumentationHelper(accessor))
-            subdochelper_dynamic_accessor_list.sort()
-            subdochelper.setDynamicAccessorList(subdochelper_dynamic_accessor_list)
-            dynamic_accessor_list.append(subdochelper)
-            dynamic_category_list.append(subdochelper)
-
-# KEEPME: usefull to track the differences between accessors defined on
-# PortalType and the one detected on the documented item.
-#    LOG('asDocumentationHelper', 0, found_accessors)
-    static_method_list.sort()
-    dochelper.setStaticMethodList(static_method_list)
-    static_property_list.sort()
-    dochelper.setStaticPropertyList(static_property_list)
-    dynamic_method_list.sort()
-    dochelper.setDynamicMethodList(dynamic_method_list)
-    dynamic_accessor_list.sort()
-    dochelper.setDynamicAccessorList(dynamic_accessor_list)
-    dynamic_category_list.sort()
-    dochelper.setDynamicCategoryList(dynamic_category_list)
-    dynamic_property_list.sort()
-    dochelper.setDynamicPropertyList(dynamic_property_list)
-    return dochelper
-
diff --git a/product/ERP5Type/DocumentationHelper/AccessorMethodDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/AccessorMethodDocumentationHelper.py
new file mode 100644
index 0000000000..bac73e85c4
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/AccessorMethodDocumentationHelper.py
@@ -0,0 +1,119 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+#return the definition string of an object representing a workflow method or a class method or an accessor
+def getDefinitionString(obj=None):
+  if obj == None:
+    return ""
+  else:
+    fc_var_names = obj.func_code.co_varnames
+    fc = []
+    for i in range(len(fc_var_names)):
+      if fc_var_names[i] == 'args':
+        fc.append('*args')
+      elif fc_var_names[i] == 'kw':
+        fc.append('**kw')
+      else:
+        fc.append(fc_var_names[i])
+    fd = obj.func_defaults
+    acc_def = obj.__name__ + ' ('
+    if fd == None:
+      acc_def += ', '.join(fc)
+    else:
+      for x in range(len(fc)):
+        if (len(fc)-(x+1)<len(fd)):
+          if (x == len(fc)-1):
+            acc_def += " "+str(fc[x])+"='"+str(fd[x-len(fd)])+"'"
+          else:
+            acc_def += " "+str(fc[x])+"='"+str(fd[x-len(fd)])+"',"
+        else:
+          if (x == len(fc)-1):
+            acc_def += " "+str(fc[x])
+          else:
+            acc_def += " "+str(fc[x])+","
+    acc_def += ")"
+    return acc_def
+
+
+class AccessorMethodDocumentationHelper(DocumentationHelper):
+  """
+    Provides documentation about an accessor
+  """
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  def __init__(self, uri):
+    self.uri = uri
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDescription')
+  def getDescription(self):
+    return self.getDocumentedObject().__doc__
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
+  def getType(self):
+    """
+    Returns the type of the documentation helper
+    """
+    return "Accessor Method"
+    #return self.getDocumentedObject().func_code.__module__
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
+  def getTitle(self):
+    """
+    Returns the title of the documentation helper
+    """
+    return self.getDocumentedObject().__name__
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getArgCount' )
+  def getArgCount(self):
+    """
+    Returns the number of args of the accessor
+    """
+    return self.getDocumentedObject().func_code.co_argcount
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getVarNames' )
+  def getVarNames(self):
+    """
+    Returns the list of args of the accessor
+    """
+    return self.getDocumentedObject().func_code.co_varnames
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getDefinition' )
+  def getDefinition(self):
+    """
+    Returns the definition of the accessor_method with the name and arguments
+    """
+    return getDefinitionString(self.getDocumentedObject())
+
+
+InitializeClass(AccessorMethodDocumentationHelper)
diff --git a/product/ERP5Type/DocumentationHelper/BusinessTemplateDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/BusinessTemplateDocumentationHelper.py
new file mode 100644
index 0000000000..52bd6a4b15
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/BusinessTemplateDocumentationHelper.py
@@ -0,0 +1,101 @@
+
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+
+class BusinessTemplateDocumentationHelper(DocumentationHelper):
+  """
+    Provides access to all documentation information
+    of a business template.
+  """
+
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  # API Implementation
+  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
+  def getTitle(self):
+    """
+    Returns the title of the documentation helper
+    """
+    return self.getDocumentedObject().getTitleOrId()
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
+  def getType(self):
+    """
+    Returns the type of the documentation helper
+    """
+    return "Business Template"
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getSectionList' )
+  def getSectionList(self):
+    """
+    Returns a list of documentation sections
+    """
+    return map(lambda x: x.__of__(self), [
+      DocumentationSection(
+        id='portal_type',
+        title='Portal Types',
+        class_name='PortalTypeDocumentationHelper',
+        uri_list=self.getPortalTypeURIList(),
+      ),
+      DocumentationSection(
+        id='workflow',
+        title='Workflows',
+        class_name='DCWorkflowDocumentationHelper',
+        uri_list=self.getDCWorkflowURIList(),
+      ),
+      DocumentationSection(
+        id='interaction',
+        title='Interaction Workflows',
+        class_name='InteractionWorkflowStateDocumentationHelper',
+        uri_list=self.getInteractionWorkflowURIList(),
+      ),
+      DocumentationSection(
+        id='skin_folder',
+        title='Skin Folders',
+        class_name='SkinFolderDocumentationHelper',
+        uri_list=self.getSkinFolderURIList(),
+      ),
+    ])
+
+  # Specific methods
+  security.declareProtected( Permissions.AccessContentsInformation, 'getDescription' )
+  def getDescription(self):
+    """
+    Returns the title of the documentation helper
+    """
+    raise NotImplemented
+
+
+InitializeClass(BusinessTemplateDocumentationHelper)
diff --git a/product/ERP5Type/DocumentationHelper/CallableDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/CallableDocumentationHelper.py
new file mode 100644
index 0000000000..7665d88ba7
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/CallableDocumentationHelper.py
@@ -0,0 +1,36 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+class CallableDocumentationHelper(DocumentationHelper):
+  """
+  """
diff --git a/product/ERP5Type/DocumentationHelper/ClassDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/ClassDocumentationHelper.py
new file mode 100644
index 0000000000..d90cdfcd9b
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/ClassDocumentationHelper.py
@@ -0,0 +1,36 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+class ClassDocumentationHelper(DocumentationHelper):
+  """
+  """
diff --git a/product/ERP5Type/DocumentationHelper/ClassMethodDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/ClassMethodDocumentationHelper.py
new file mode 100644
index 0000000000..20eb1fc459
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/ClassMethodDocumentationHelper.py
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+class ClassMethodDocumentationHelper(DocumentationHelper):
+  """
+    Provides documentation about a class method
+  """
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDescription')
+  def getDescription(self):
+    return self.getDocumentedObject().__doc__
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
+  def getType(self):
+    """
+    Returns the type of the documentation helper
+    """
+    return "Class Method"
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
+  def getTitle(self):
+    """
+    Returns the type of the documentation helper
+    """
+    return self.getDocumentedObject().__name__
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getDefinition' )
+  def getDefinition(self):
+    """
+    Returns the definition of the class_method with the name and arguments
+    """
+    return getDefinitionString(self.getDocumentedObject())
+
+
+InitializeClass(ClassMethodDocumentationHelper)
diff --git a/product/ERP5Type/DocumentationHelper/DCWorkflowDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/DCWorkflowDocumentationHelper.py
new file mode 100644
index 0000000000..9c8cd7d816
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/DCWorkflowDocumentationHelper.py
@@ -0,0 +1,136 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+class DCWorkflowDocumentationHelper(DocumentationHelper):
+  """
+    Provides access to all documentation information
+    of a workflow.
+  """
+
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  # API Implementation
+  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
+  def getTitle(self):
+    """
+    Returns the title of the documentation helper
+    """
+    return self.getDocumentedObject().getTitleOrId()
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
+  def getType(self):
+    """
+    Returns the type of the documentation helper
+    """
+    return "DC Workflow"
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getSectionList' )
+  def getSectionList(self):
+    """
+    Returns a list of documentation sections
+    """
+    return map(lambda x: x.__of__(self), [
+      DocumentationSection(
+        id='state',
+        title='Workflow States',
+        class_name='DCWorkflowStateDocumentationHelper',
+        uri_list=self.getStateURIList(),
+      ),
+      DocumentationSection(
+        id='transition',
+        title='Workflow Transitions',
+        class_name='DCWorkflowTransitionDocumentationHelper',
+        uri_list=self.getStateURIList(),
+      ),
+      DocumentationSection(
+        id='variable',
+        title='Workflow Variables',
+        class_name='DCWorkflowVariableDocumentationHelper',
+        uri_list=self.getVariableURIList(),
+      ),
+      DocumentationSection(
+        id='variable',
+        title='Workflow Permissions',
+        class_name='PermissionDocumentationHelper',
+        uri_list=self.getPermissionURIList(),
+      ),
+    ])
+
+  # Specific methods
+  security.declareProtected( Permissions.AccessContentsInformation, 'getDescription' )
+  def getDescription(self):
+    """
+    Returns the title of the documentation helper
+    """
+    raise NotImplemented
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getVariableURIList' )
+  def getVariableURIList(self):
+    """
+    """
+    raise NotImplemented
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getStateURIList' )
+  def getStateURIList(self):
+    """
+    """
+    raise NotImplemented
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getVariableURIList' )
+  def getVariableURIList(self):
+    """
+    """
+    raise NotImplemented
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getPermissionURIList' )
+  def getPermissionURIList(self):
+    """
+    """
+    raise NotImplemented
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getGraphImageURL' )
+  def getGraphImageURL(self):
+    """
+      Returns a URL to a graphic representation of the workflow
+    """
+    raise NotImplemented
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getGraphImageData' )
+  def getGraphImageData(self):
+    """
+      Returns the graphic representation of the workflow as a PNG file
+    """
+    raise NotImplemented
+
+InitializeClass(DCWorkflowDocumentationHelper)
diff --git a/product/ERP5Type/DocumentationHelper/DocumentationHelper.py b/product/ERP5Type/DocumentationHelper/DocumentationHelper.py
new file mode 100644
index 0000000000..5753eeb396
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/DocumentationHelper.py
@@ -0,0 +1,143 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from Products.ERP5Type import Permissions
+
+class DocumentationHelper(Implicit):
+  """
+    Example URIs
+
+    person_module/23
+    person_module/23#title
+    person_module/23#getTitle
+    portal_worklows/validation_workflow
+    portal_worklows/validation_workflow/states/draft
+    portal_worklows/validation_workflow/states/draft#title
+    Products.ERP5Type.Document.Person.notify
+    Products.ERP5Type.Document.Person.isRAD
+    portal_types/Person
+    portal_types/Person/actions#view
+  """
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  # Methods to override
+  def __init__(self, uri):
+    self.uri = uri
+
+  def getDocumentedObject(self):
+    if '/' in self.uri and '#' not in self.uri:
+      # URI refers to a portal object
+      # and is a relative URL
+      documented_object = self.getPortalObject().portal_categories.resolveCategory(self.uri)  
+    elif '/' in self.uri and '#' in self.uri:
+      url, method = self.uri.split('#') 
+      # if / in method, method's not an acessor but a workflow method
+      documented_object = self.getPortalObject().unrestrictedTraverse(url)
+      if '/' not in method:
+        documented_object = self.getPortalObject().unrestrictedTraverse(url)
+        documented_object = getattr(documented_object, method, None)
+      else:
+        #wf_url = 'erp5/portal_workflow/'+method
+        #documented_object = self.getPortalObject().unrestrictedTraverse(wf_url)
+        path_method = method.split('/')
+        wf_method = path_method[len(path_method)-1]
+        documented_object = getattr(documented_object, wf_method, None)
+    else:
+      # URI refers to a python class / method
+      import imp
+      module_list = self.uri.split('.')
+      base_module = module_list[0]
+      if base_module == 'Products':
+        # For now, we do not even try to import
+        # or locate objects which are not in Products
+        import Products
+        documented_object = Products
+        for key in module_list[1:]:
+          LOG('loop in module_list', 0, repr(documented_object))
+          documented_object = getattr(documented_object, key)
+      else:
+        raise NotImplemented
+        #fp, pathname, description = imp.find_module(base_module)
+        #documented_object = imp.load_module(fp, pathname, description)
+
+    return documented_object
+
+  def getTitle(self):
+    """
+    Returns the title of the documentation helper
+    (ex. class name)
+    """
+    raise NotImplemented
+
+  def getType(self):
+    """
+    Returns the type of the documentation helper
+    (ex. Class, float, string, Portal Type, etc.)
+    """
+    raise NotImplemented
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getSectionList')
+  def getSectionList(self):
+    """
+    Returns a list of documentation sections
+    """
+    raise NotImplemented
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getURI')
+  def getURI(self):
+    """
+    Returns a URI to later access this documentation
+    from portal_classes
+    """
+    return self.uri
+
+  # Generic methods which all subclasses should inherit
+  security.declareProtected(Permissions.AccessContentsInformation, 'getClassName')
+  def getClassName(self):
+    """
+    Returns our own class name
+    """
+    return self.__class__.__name__
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'view')
+  def view(self):
+    """
+    Renders the documentation with a standard form
+    ex. PortalTypeInstanceDocumentationHelper_view
+    """
+    return getattr(self, '%s_view' % self.getClassName())()
+
+  security.declareProtected(Permissions.AccessContentsInformation, '__call__')
+  def __call__(self):
+    return self.view()
+
+InitializeClass(DocumentationHelper)
diff --git a/product/ERP5Type/DocumentationHelper/DocumentationSection.py b/product/ERP5Type/DocumentationHelper/DocumentationSection.py
new file mode 100644
index 0000000000..00b0d7efe0
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/DocumentationSection.py
@@ -0,0 +1,56 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from Products.ERP5Type import Permissions
+
+
+class DocumentationSection(Implicit):
+
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  def __init__(self, id, title, class_name, uri_list):
+    self.id = id
+    self.title = title
+    self.class_name = class_name
+    self.uri_list = uri_list
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getClassName')
+  def getClassName(self):
+    return self.class_name
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getURIList')
+  def getURIList(self):
+    return self.uri_list
+
+  # more API needed XXX
+
+InitializeClass(DocumentationSection)
diff --git a/product/ERP5Type/DocumentationHelper/InstancePropertyDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/InstancePropertyDocumentationHelper.py
new file mode 100644
index 0000000000..efadb8c78f
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/InstancePropertyDocumentationHelper.py
@@ -0,0 +1,36 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+class InstancePropertyDocumentationHelper(DocumentationHelper):
+  """
+  """
diff --git a/product/ERP5Type/DocumentationHelper/Legacy.py b/product/ERP5Type/DocumentationHelper/Legacy.py
new file mode 100644
index 0000000000..c5dc4bf557
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/Legacy.py
@@ -0,0 +1,302 @@
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+
+from Products.CMFCore.utils import getToolByName
+
+from Products.ERP5Type.Accessor.Accessor import Accessor
+from Products.ERP5Type.Base import WorkflowMethod
+from Products.ERP5Type import Permissions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#############################################################################
+#############################################################################
+
+if 0:
+  if 0:
+    static_method_list = []    # Class methods
+    static_property_list = []  # Class attributes
+    dynamic_method_list = []   # Workflow methods
+    dynamic_property_list = [] # Document properties
+    dynamic_category_list = [] # Categories
+    dynamic_accessor_list = [] # Accessors
+
+
+  security.declareProtected( Permissions.ManagePortal, 'asDocumentationHelper' )
+  def asDocumentationHelper(self, item_id=None):
+    """
+      Fills and return a DocHelper object from context.
+      Overload this in any object the has to fill the DocHelper in its own way.
+
+      item_id : If specified, the documented item will be
+                getattr(self, item_title) if it exists, otherwise None will
+                be returned.
+
+      TODO:
+       - Check that filtering is correct : display only and every things
+         defined on the class itself.
+       - Add a list of all accessible things in the documented item context
+         (heritated methods & attributes) in a light way that still allows to
+         link directly to the corresponding documentation.
+       - Rewrite accessor generation system so that it can generate accessor
+         names when given a property/category.
+
+       KEEPMEs:
+         There are pieces of code in this function that can have interesting
+         results, but who are also very verbose. They are disabled (commented
+         out) by default, but they should be kept.
+         Explanation of the interest :
+         The accessors are gathered from 2 sources : the ones defined on the
+         PortalType, and systematically generated names, and tested for
+         presence on the documented item.
+         There are 4 cases then :
+         -Accessor whose name was generated exists both on the PortalType and
+          on the documented item. That's normal.
+         -Accessor whose name was generated exists neither on the PortalType
+          nor on the documented item. That's normal, but could mean that the
+          accessor name generator isn't optimal.
+         -Accessor whose name was generated is found on the object but not on
+          the PortalType. This is a problem.
+         -Accessors gathered from PortalType aren't all found by guessing
+          systematically the names. That means that the accessor name
+          generation is not perfect and requires improvement.
+
+         nb: the accessors are gathered from 2 sources, the first is somehow
+         accidental when searching for workflow methods defined on the
+         PortalType, and are browsed a second time to be able to group them
+         by property or category.
+    """
+    if item_id is None:
+      documented_item = self
+      item_id = documented_item.getTitle()
+    elif getattr(self, item_id, None) is not None:
+      documented_item = getattr(self, item_id)
+    else:
+      return None
+
+    # The documented object is an instance (or not) of this class.
+    item_class = getattr(documented_item, '__bases__', None) is None \
+                 and documented_item.__class__ \
+                 or documented_item
+
+    static_method_list = []    # Class methods
+    static_property_list = []  # Class attributes
+    dynamic_method_list = []   # Workflow methods
+    dynamic_property_list = [] # Document properties
+    dynamic_category_list = [] # Categories
+    dynamic_accessor_list = [] # Accessors
+    found_accessors = {}       # Accessor names : filled by PortalType-level
+                               # scan, and used in PropertySheet-level scan.
+    dochelper = newTempDocumentationHelper(self.getParentValue(), self.getId(),
+                  title=item_id, type=item_class.__name__,
+                  description=inspect.getdoc(documented_item),
+                )
+    dochelper.setInheritanceList([x.__name__ for x in item_class.__bases__])
+    try:
+      dochelper.setSourcePath(inspect.getsourcefile(item_class))
+    except (IOError, TypeError):
+      pass
+    # dochelper.setSecurity() # (maybe) TODO: Add class instance security gthering.
+
+    # Class-level method & properties
+    for k, v in item_class.__dict__.items():
+      subdochelper = newTempDocumentationHelper(dochelper, k,
+                  title=k, description=inspect.getdoc(v),
+                  security=repr(getattr(documented_item, '%s__roles__' % (k,),None)))
+      try:
+        subdochelper.setType(v.__class__.__name__)
+      except AttributeError:
+        pass
+      try:
+        subdochelper.setSourcePath(inspect.getsourcefile(v))
+      except (IOError, TypeError), err:
+        pass
+      try:
+        subdochelper.setSourceCode(inspect.getsource(v))
+      except (IOError, TypeError), err:
+        pass
+      try:
+        subdochelper.setArgumentList(inspect.getargspec(v))
+      except (IOError, TypeError), err:
+        pass
+      if subdochelper.getType() in ('function',): # This is a method
+        static_method_list.append(subdochelper)
+      elif subdochelper.getType() in ('int', 'float', 'long', 'str', 'tuple', 'dict', 'list') \
+           and not subdochelper.getTitle().startswith('__'): # This is a property
+        subdochelper.setContent(pformat(v))
+        static_property_list.append(subdochelper)
+      # FIXME: Is there any other interesting type ?
+
+    # PortalType-level methods
+    # XXX: accessing portal_type directly because accessors are not generated on instances
+    if getattr(documented_item, 'portal_type', None) is not None:
+      for k, v in Base.aq_portal_type[documented_item.portal_type].__dict__.items():
+        if callable(v) and not (k.startswith('_base') or k.startswith('_category')):
+          subdochelper = newTempDocumentationHelper(dochelper, k,
+                    title=k, description=inspect.getdoc(v),
+                    security=repr(getattr(documented_item, '%s__roles__' % (k,),None)))
+          try:
+            my_type = v.__class__.__name__
+            subdochelper.setType(my_type)
+          except AttributeError:
+            pass
+          if 'Setter' not in my_type and \
+             'Getter' not in my_type and \
+             'Tester' not in my_type: # Accessors are handled separatelly.
+            dynamic_method_list.append(subdochelper)
+# KEEPME: usefull to track the differences between accessors defined on
+# PortalType and the one detected on the documented item.
+#          else:
+#            found_accessors[k] = v
+
+    def generatePropertyAccessorNameList(property):
+      """
+        Generates the possible accessor names for given property.
+
+        FIXME: Should not exist here, but as accessor generation system.
+      """
+      from Products.ERP5Type.Utils import UpperCase
+      res=[]
+      cased_id = UpperCase(property['id'])
+      for hidden in ('', '_'):
+        for getset in ('get', 'set', 'has'): # 'is',
+          for default in ('', 'Default', 'Translated'):
+            for value in ('', 'Value', 'TranslationDomain'):
+              for multivalued in ('', 'List', 'Set'):
+                res.append('%s%s%s%s%s%s' % (hidden, getset, default, cased_id, value, multivalued))
+      if property.has_key('acquired_property_id') and \
+         property['type'] == 'content':
+        for aq_property_id in property['acquired_property_id']:
+          cased_id = UpperCase('%s_%s' % (property['id'], aq_property_id))
+          for hidden in ('', '_'):
+            for getset in ('get', 'set'):
+              for default in ('', 'Default'):
+                for multivalued in ('', 'List'):
+                  res.append('%s%s%s%s%s' % (hidden, getset, default, cased_id, multivalued))
+      return res
+
+    def generateCategoryAccessorNameList(category):
+      """
+        Generates the possible accessor names for given category.
+
+        FIXME: Should not exist here, but as accessor generation system.
+      """
+      from Products.ERP5Type.Utils import UpperCase
+      cased_id=UpperCase(category)
+      res=['%s%sIds' % (cased_id[0].lower(), cased_id[1:]),
+           '%s%sValues' % (cased_id[0].lower(), cased_id[1:])]
+      for hidden in ('', '_'):
+        for default in ('', 'Default'):
+          for multivalued in ('', 'List', 'Set'):
+            for attribute in ('', 'TranslatedTitle', 'Uid', 'LogicalPath', 'Id', 'TitleOrId', 'Reference', 'Title'):
+              res.append('%sget%s%s%s%s' % (hidden, default, cased_id, attribute, multivalued))
+            for attribute in ('', 'Value', 'Uid'):
+              res.append('%sset%s%s%s%s' % (hidden, default, cased_id, attribute, multivalued))
+      return res
+
+    def accessorAsDocumentationHelper(accessor):
+      """
+        Generates a documentation helper about a given accessor.
+      """
+      accessor_dochelper = newTempDocumentationHelper(subdochelper, accessor_name,
+                                                      title=accessor_name,
+                                                      description=inspect.getdoc(accessor))
+      try:
+        accessor_dochelper.setSourcePath(inspect.getsourcefile(accessor))
+      except (IOError, TypeError), err:
+        pass
+      try:
+        accessor_dochelper.setSourceCode(inspect.getsource(accessor))
+      except (IOError, TypeError), err:
+        pass
+# KEEPME: usefull to track the differences between accessors defined on
+# PortalType and the one detected on the documented item.
+#      if found_accessors.has_key(accessor_name):
+#        del(found_accessors[accessor_name])
+#      else:
+#        LOG('asDocumentationHelper', 0,
+#            'Found but not in the accessor list : %s of type %s' % \
+#            (accessor_name, accessor.__class__.__name__))
+      return accessor_dochelper
+
+    # PropertySheet-level properties & categories
+    # Also handles accessors.
+    seen_properties=[]
+    seen_categories=[]
+    if getattr(documented_item, 'property_sheets', None) is not None:
+      for property_sheet in documented_item.property_sheets:
+        if getattr(property_sheet, '_properties', None) is not None:
+          for property in property_sheet._properties:
+            if property in seen_properties:
+              continue
+            seen_properties.append(property)
+            subdochelper = newTempDocumentationHelper(dochelper, k,
+                      title=property['id'], description=property['description'],
+                      type=property['type'], security=property['mode'],
+                      content=pformat(documented_item.getProperty(property['id'])))
+            subdochelper_dynamic_accessor_list = []
+            for accessor_name in generatePropertyAccessorNameList(property):
+              accessor = getattr(item_class, accessor_name, getattr(documented_item, accessor_name, None))
+              # First get it on the class, and if not on the instance, thereby among dynamic accessors.
+              if accessor is not None:
+                subdochelper_dynamic_accessor_list.append(accessorAsDocumentationHelper(accessor))
+            subdochelper_dynamic_accessor_list.sort()
+            subdochelper.setDynamicAccessorList(subdochelper_dynamic_accessor_list)
+            dynamic_accessor_list.append(subdochelper)
+            if getattr(documented_item, property['id'], None) is not None:
+              dynamic_property_list.append(subdochelper)
+        if getattr(property_sheet, '_categories', None) is not None:
+          for category in property_sheet._categories:
+            if category in seen_categories:
+              continue
+            seen_categories.append(category)
+            subdochelper = newTempDocumentationHelper(dochelper, category, title=category,
+                      content=pformat(documented_item.getCategoryMembershipList(category)))
+            subdochelper_dynamic_accessor_list = []
+            for accessor_name in generateCategoryAccessorNameList(category):
+              accessor = getattr(item_class, accessor_name, getattr(documented_item, accessor_name, None))
+              # First get it on the class, and if not on the instance, thereby among dynamic accessors.
+              if accessor is not None:
+                subdochelper_dynamic_accessor_list.append(accessorAsDocumentationHelper(accessor))
+            subdochelper_dynamic_accessor_list.sort()
+            subdochelper.setDynamicAccessorList(subdochelper_dynamic_accessor_list)
+            dynamic_accessor_list.append(subdochelper)
+            dynamic_category_list.append(subdochelper)
+
+# KEEPME: usefull to track the differences between accessors defined on
+# PortalType and the one detected on the documented item.
+#    LOG('asDocumentationHelper', 0, found_accessors)
+    static_method_list.sort()
+    dochelper.setStaticMethodList(static_method_list)
+    static_property_list.sort()
+    dochelper.setStaticPropertyList(static_property_list)
+    dynamic_method_list.sort()
+    dochelper.setDynamicMethodList(dynamic_method_list)
+    dynamic_accessor_list.sort()
+    dochelper.setDynamicAccessorList(dynamic_accessor_list)
+    dynamic_category_list.sort()
+    dochelper.setDynamicCategoryList(dynamic_category_list)
+    dynamic_property_list.sort()
+    dochelper.setDynamicPropertyList(dynamic_property_list)
+    return dochelper
+
diff --git a/product/ERP5Type/DocumentationHelper/PortalDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/PortalDocumentationHelper.py
new file mode 100644
index 0000000000..840aa9b8bc
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/PortalDocumentationHelper.py
@@ -0,0 +1,36 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+class PortalDocumentationHelper(DocumentationHelper):
+  """
+  """
\ No newline at end of file
diff --git a/product/ERP5Type/DocumentationHelper/PortalTypeDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/PortalTypeDocumentationHelper.py
new file mode 100644
index 0000000000..da727c5c25
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/PortalTypeDocumentationHelper.py
@@ -0,0 +1,91 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+class PortalTypeDocumentationHelper(DocumentationHelper):
+  """
+    Provides access to all documentation information
+    of a portal type. Accessors and methods are documented
+    by generating a temporary instance which provides
+    an access to the property holder and allows
+    reusing PortalTypeInstanceDocumentationHelper
+  """
+
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  # API Implementation
+  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
+  def getTitle(self):
+    """
+    Returns the title of the documentation helper
+    """
+    return self.getDocumentedObject().getTitleOrId()
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
+  def getType(self):
+    """
+    Returns the type of the documentation helper
+    """
+    return "Portal Type"
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getSectionList' )
+  def getSectionList(self):
+    """
+    Returns a list of documentation sections
+    """
+    return map(lambda x: x.__of__(self), [
+      DocumentationSection(
+        id='action',
+        title='Actions',
+        class_name='ActionDocumentationHelper',
+        uri_list=self.getActionURIList(),
+      ),
+      DocumentationSection(
+        id='local_role',
+        title='Local Role Definitions',
+        class_name='LocalRoleDefinitionDocumentationHelper',
+        uri_list=self.getDCWorkflowURIList(),
+      ),
+      # XXX - add here all sections of a portal type instance
+    ])
+
+  # Specific methods
+  security.declareProtected( Permissions.AccessContentsInformation, 'getDescription' )
+  def getDescription(self):
+    """
+    Returns the title of the documentation helper
+    """
+    raise NotImplemented
+
+
+InitializeClass(PortalTypeDocumentationHelper)
diff --git a/product/ERP5Type/DocumentationHelper/PortalTypeInstanceDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/PortalTypeInstanceDocumentationHelper.py
new file mode 100644
index 0000000000..c95b841b65
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/PortalTypeInstanceDocumentationHelper.py
@@ -0,0 +1,228 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+
+class PortalTypeInstanceDocumentationHelper(DocumentationHelper):
+  """
+    Provides access to all documentation information
+    of a portal type instance.
+  """
+
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  def __init__(self, uri):
+    self.uri = uri
+
+  def getInstance(self):
+    return self.getPortalObject().restrictedTraverse(self.uri)
+
+  # API Implementation
+  security.declareProtected( Permissions.AccessContentsInformation, 'getTitle' )
+  def getTitle(self):
+    """
+    Returns the title of the documentation helper
+    """
+    return self.getInstance().getTitleOrId()
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getType' )
+  def getType(self):
+    """
+    Returns the type of the documentation helper
+    """
+    return "Portal Type Instance"
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getSectionList' )
+  def getSectionList(self):
+    """
+    Returns a list of documentation sections
+    """
+    return [
+      #DocumentationSection(
+        #id='instance_property',
+        #title='Instance Properties',
+        #class_name='InstancePropertyDocumentationHelper',
+        #uri_list=self.getClassPropertyURIList(),
+      #),
+      DocumentationSection(
+        id='workflow_method',
+        title='Workflow Method',
+        class_name='WorkflowMethodDocumentationHelper',
+        uri_list=self.getWorkflowMethodURIList(inherited=0),
+      ),
+      DocumentationSection(
+        id='accessor',
+        title='Accessor',
+        class_name='AccessorMethodDocumentationHelper',
+        uri_list=self.getAccessorMethodURIList(inherited=0),
+      ),
+      DocumentationSection(
+        id='class_method',
+        title='Class Methods',
+        class_name='ClassMethodDocumentationHelper',
+        uri_list=self.getClassMethodURIList(inherited=0),
+      ).__of__(self.getInstance()),
+    ]
+
+  # Specific methods
+  security.declareProtected( Permissions.AccessContentsInformation, 'getPortalType' )
+  def getPortalType(self):
+    """
+    """
+    return self.getInstance().getPortalType()
+
+  def _getPropertyHolder(self):
+    from Products.ERP5Type.Base import Base
+    return Base.aq_portal_type[(self.getPortalType(), self.getInstance().__class__)]
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getAccessorMethodItemList' )
+  def getAccessorMethodItemList(self):
+    """
+    """
+    return self._getPropertyHolder().getAccessorMethodItemList()
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getAccessorMethodIdList' )
+  def getAccessorMethodIdList(self):
+    """
+    """
+    return self._getPropertyHolder().getAccessorMethodIdList()
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getAccessorMethodURIList' )
+  def getAccessorMethodURIList(self, inherited=1, local=1):
+    """
+    Returns a list of URIs to accessor methods
+    """
+    method_id_list = self.getAccessorMethodIdList(inherited=inherited, local=local)
+    klass = self.getInstance().__class__
+    class_name = klass.__name__
+    module = klass.__module__
+    uri_prefix = '%s.%s.' % (module, class_name)
+    return map(lambda x: '%s%s' % (uri_prefix, x), method_id_list)
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getWorkflowMethodItemList' )
+  def getWorkflowMethodItemList(self):
+    """
+    """
+    return self._getPropertyHolder().getWorkflowMethodItemList()
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getWorkflowObject' )
+  def getWorkflowObject(self):
+    """
+    """
+    return self._getPropertyHolder()
+  
+  security.declareProtected(Permissions.AccessContentsInformation, 'getWorkflowMethodIdList' )
+  def getWorkflowMethodIdList(self):
+    """
+    """
+    return self._getPropertyHolder().getWorkflowMethodIdList()    
+
+  def getWorkflowMethodURIList(self, inherited=1, local=1):
+    """
+    Returns a list of URIs to workflow  methods
+    """
+    method_id_list = self.getWorkflowMethodIdList(inherited=inherited, local=local)
+    klass = self.getInstance().__class__
+    class_name = klass.__name__
+    module = klass.__module__
+    uri_prefix = '%s.%s.' % (module, class_name)
+    return map(lambda x: '%s%s' % (uri_prefix, x), method_id_list)
+
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getActionMethodItemList' )
+  def getActionMethodItemList(self):
+    """
+    """
+    return self._getPropertyHolder().getActionMethodItemList()
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getActionMethodIdList' )
+  def getActionMethodIdList(self):
+    """
+    """
+    return self._getPropertyHolder().getActionMethodIdList()
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getClassMethodItemList' )
+  def getClassMethodItemList(self, inherited=1, local=1):
+    """
+    Return a list of tuple (id, method) for every class method
+    """
+    klass = self.getInstance().__class__
+    return self._getPropertyHolder().getClassMethodItemList(klass, inherited=inherited, local=local)
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getClassMethodIdList' )
+  def getClassMethodIdList(self, inherited=1, local=1):
+    """
+    Return a list of tuple (id, method) for every class method
+    """
+    klass = self.getInstance().__class__
+    return self._getPropertyHolder().getClassMethodIdList(klass, inherited=inherited, local=local)
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getClassMethodURIList' )
+  def getClassMethodURIList(self, inherited=1, local=1):
+    """
+    Returns a list of URIs to class methods
+    """
+    method_id_list = self.getClassMethodIdList(inherited=inherited, local=local)
+    klass = self.getInstance().__class__
+    class_name = klass.__name__
+    module = klass.__module__
+    uri_prefix = '%s.%s.' % (module, class_name)
+    return map(lambda x: '%s%s' % (uri_prefix, x), method_id_list)
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getClassPropertyItemList' )
+  def getClassPropertyItemList(self, inherited=1, local=1):
+    """
+    Return a list of tuple (id, method) for every class method
+    """
+    klass = self.getInstance().__class__
+    return self._getPropertyHolder().getClassPropertyItemList(klass, inherited=inherited, local=local)
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getClassPropertyIdList' )
+  def getClassPropertyIdList(self, inherited=1, local=1):
+    """
+    Return a list of tuple (id, method) for every class method
+    """
+    klass = self.getInstance().__class__
+    return self._getPropertyHolder().getClassPropertyIdList(klass, inherited=inherited, local=local)
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getGeneratedPropertyIdList' )
+  def getGeneratedPropertyIdList(self):
+    """
+    """
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getGeneratedBaseCategoryIdList' )
+  def getGeneratedBaseCategoryIdList(self):
+    """
+    """
+
+InitializeClass(PortalTypeInstanceDocumentationHelper)
diff --git a/product/ERP5Type/DocumentationHelper/PropertyDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/PropertyDocumentationHelper.py
new file mode 100644
index 0000000000..30500efcbf
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/PropertyDocumentationHelper.py
@@ -0,0 +1,37 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+class PropertyDocumentationHelper(DocumentationHelper):
+  """
+  """
+
diff --git a/product/ERP5Type/DocumentationHelper/WorkflowMethodDocumentationHelper.py b/product/ERP5Type/DocumentationHelper/WorkflowMethodDocumentationHelper.py
new file mode 100644
index 0000000000..1b1668b2a0
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/WorkflowMethodDocumentationHelper.py
@@ -0,0 +1,101 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from Acquisition import Implicit
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass
+from DocumentationHelper import DocumentationHelper
+
+class WorkflowMethodDocumentationHelper(DocumentationHelper):
+  """
+    Provides documentation about a workflow method
+  """
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  def __init__(self, uri):
+    self.uri = uri
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDescription')
+  def getDescription(self):
+    return self.getDocumentedObject().__doc__
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getType' )
+  def getType(self):
+    """
+    Returns the type of the documentation helper
+    """
+    return "Workflow Method"
+    #return self.getDocumentedObject().__module__
+
+  security.declareProtected(Permissions.AccessContentsInformation, 'getTitle' )
+  def getTitle(self):
+    """
+    Returns the title of the documentation helper
+    """
+    return self.getDocumentedObject().__name__
+
+  #security.declareProtected(Permissions.AccessContentsInformation, 'getDestinationState' )
+  #def getDestinationState(self):
+  #  """
+  #  Returns the destination_state of the transition workflow method
+  #  """
+  #  return self.getDocumentedObject().__dict__['new_state_id']
+
+  #security.declareProtected(Permissions.AccessContentsInformation, 'getTriggerType' )
+  #def getTriggerType(self):
+  #  """
+  #  Returns the trigger type of the workflow method
+  #  """
+  #  TT = ['Automatic','Initiated by user action','Initiated by WorkflowMethod']
+  #  TT_id = self.getDocumentedObject().__dict__['trigger_type']
+  #  return TT[TT_id]
+
+  #security.declareProtected(Permissions.AccessContentsInformation, 'getLocalRoles' )
+  #def getLocalRoles(self):
+  #  """
+  #  Returns the local roles of the workflow method
+  #  """
+  #  return self.getDocumentedObject().__ac_local_roles__
+
+  #security.declareProtected(Permissions.AccessContentsInformation, 'getAvailableStateIds' )
+  #def getAvailableStateIds(self):
+  #  """
+  #  Returns available states in the workflow
+  #  """
+  #  return self.getDocumentedObject().getAvailableStateIds()
+
+  security.declareProtected( Permissions.AccessContentsInformation, 'getDefinition' )
+  def getDefinition(self):
+    """
+    Returns the definition of the workflow_method with the name and arguments
+    """
+    return getDefinitionString(self.getDocumentedObject())
+
+
+InitializeClass(WorkflowMethodDocumentationHelper)
diff --git a/product/ERP5Type/DocumentationHelper/__init__.py b/product/ERP5Type/DocumentationHelper/__init__.py
new file mode 100644
index 0000000000..b23aa16050
--- /dev/null
+++ b/product/ERP5Type/DocumentationHelper/__init__.py
@@ -0,0 +1,45 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from DocumentationSection import DocumentationSection
+
+# Automatic import "脿 la" Document would be more consistent
+# I even wonder whether using Document classes everywhere would be better
+# from a reflexive point of view (ie. to build persistent documentation)
+from DocumentationHelper import DocumentationHelper
+from AccessorMethodDocumentationHelper import AccessorMethodDocumentationHelper
+from BusinessTemplateDocumentationHelper import BusinessTemplateDocumentationHelper
+from CallableDocumentationHelper import CallableDocumentationHelper
+from ClassMethodDocumentationHelper import ClassMethodDocumentationHelper
+from DCWorkflowDocumentationHelper import DCWorkflowDocumentationHelper
+from InstancePropertyDocumentationHelper import InstancePropertyDocumentationHelper
+from PortalDocumentationHelper import PortalDocumentationHelper
+from PortalTypeDocumentationHelper import PortalTypeDocumentationHelper
+from PortalTypeInstanceDocumentationHelper import PortalTypeInstanceDocumentationHelper
+from PropertyDocumentationHelper import PropertyDocumentationHelper
+from WorkflowMethodDocumentationHelper import WorkflowMethodDocumentationHelper
\ No newline at end of file
-- 
2.30.9