Commit 914bda0a authored by Jean-Paul Smets's avatar Jean-Paul Smets

Imp)lemented dynamic workflow status / transiton method generation


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@1332 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 62745101
...@@ -33,6 +33,9 @@ from Acquisition import aq_base, aq_inner, aq_acquire, aq_chain ...@@ -33,6 +33,9 @@ from Acquisition import aq_base, aq_inner, aq_acquire, aq_chain
from Products.CMFCore.WorkflowCore import WorkflowMethod from Products.CMFCore.WorkflowCore import WorkflowMethod
from Products.CMFCore.PortalContent import PortalContent from Products.CMFCore.PortalContent import PortalContent
from Products.CMFCore.utils import getToolByName
from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD
from Products.CMFActivity.ActiveObject import ActiveObject from Products.CMFActivity.ActiveObject import ActiveObject
...@@ -40,10 +43,11 @@ from Products.ERP5Type import _dtmldir ...@@ -40,10 +43,11 @@ from Products.ERP5Type import _dtmldir
from Products.ERP5Type import PropertySheet from Products.ERP5Type import PropertySheet
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5Type.Utils import UpperCase from Products.ERP5Type.Utils import UpperCase
from Products.ERP5Type.Utils import convertToUpperCase from Products.ERP5Type.Utils import convertToUpperCase, convertToMixedCase
from Products.ERP5Type.Utils2 import _getListFor from Products.ERP5Type.Utils2 import _getListFor
from Products.ERP5Type.Accessor.TypeDefinition import list_types from Products.ERP5Type.Accessor.TypeDefinition import list_types
from Products.ERP5Type.XMLExportImport import Base_asXML from Products.ERP5Type.XMLExportImport import Base_asXML
from Accessor import WorkflowState
from Products.Base18.Base18 import Base18 from Products.Base18.Base18 import Base18
...@@ -63,19 +67,85 @@ from email import Encoders ...@@ -63,19 +67,85 @@ from email import Encoders
from socket import gethostname, gethostbyaddr from socket import gethostname, gethostbyaddr
import random import random
from zLOG import LOG from zLOG import LOG, INFO, ERROR, WARNING
# Dynamic method acquisition system (code generation) # Dynamic method acquisition system (code generation)
aq_method_generated = {} aq_method_generated = {}
def _initializeDefaultProperties(klass): def initializeDynamicProperties(self, klass):
id = ''
LOG('before aq_method_generated %s' % id, 0, str(klass.__name__))
if not aq_method_generated.has_key(klass): if not aq_method_generated.has_key(klass):
aq_method_generated[klass] = 1
# Recurse to superclasses
for super_klass in klass.__bases__:
if getattr(super_klass, 'isRADContent', 0): initializeDynamicProperties(None, super_klass)
# Initialize default properties
LOG('in aq_method_generated %s' % id, 0, str(klass.__name__)) LOG('in aq_method_generated %s' % id, 0, str(klass.__name__))
from Utils import initializeDefaultProperties from Utils import initializeDefaultProperties
initializeDefaultProperties([klass]) initializeDefaultProperties([klass])
if self is not None:
# We should now make sure workflow methods are defined
# and also make sure simulation state is defined
portal_workflow = getToolByName(self, 'portal_workflow')
for wf in portal_workflow.getWorkflowsFor(self):
wf_id = wf.id
try:
#LOG('in aq_method_generated %s' % id, 0, "found state workflow %s" % wf.id)
if wf.__class__.__name__ in ('DCWorkflowDefinition', ):
# Create state var accessor
state_var = wf.variables.getStateVar()
method_id = 'get%s' % UpperCase(state_var)
if not hasattr(klass, method_id):
method = WorkflowState.Getter(method_id, wf_id)
setattr(klass, method_id, method)
klass.security.declareProtected( Permissions.AccessContentsInformation, method_id )
#LOG('in aq_method_generated %s' % id, 0, "added state method %s" % method_id)
except:
LOG('Base', ERROR,
'Could not generate worklow state method for workflow %s on class %s.' % (wf_id, klass),
error=sys.exc_info())
try:
LOG('in aq_method_generated %s' % id, 0, "found transition workflow %s" % wf.id)
if wf.__class__.__name__ in ('DCWorkflowDefinition', ):
for tr_id in wf.transitions.objectIds():
tdef = wf.transitions.get(tr_id, None)
if tdef.trigger_type == TRIGGER_WORKFLOW_METHOD:
method_id = convertToMixedCase(tr_id)
if not hasattr(klass, method_id):
method = WorkflowMethod(klass._doNothing, method_id)
setattr(klass, method_id, method)
klass.security.declareProtected( Permissions.AccessContentsInformation, method_id )
#LOG('in aq_method_generated %s' % id, 0, "added transition method %s" % method_id)
else:
# Wrap method into WorkflowMethod is needed
method = getattr(klass, method_id)
if callable(method):
if not isinstance(method, WorkflowMethod):
setattr(klass, method_id, WorkflowMethod(method))
elif wf.__class__.__name__ in ('InteractionWorkflowDefinition', ):
for tr_id in wf.interactions.objectIds():
tdef = wf.interactions.get(tr_id, None)
if tdef.trigger_type == TRIGGER_WORKFLOW_METHOD:
for imethod_id in tdef.method_id:
method_id = convertToMixedCase(imethod_id)
if not hasattr(klass, method_id):
method = WorkflowMethod(klass._doNothing, method_id)
setattr(klass, method_id, method)
klass.security.declareProtected( Permissions.AccessContentsInformation, method_id )
#LOG('in aq_method_generated %s' % id, 0, "added interaction method %s" % method_id)
else:
# Wrap method into WorkflowMethod is needed
method = getattr(klass, method_id)
if callable(method):
if not isinstance(method, WorkflowMethod):
setattr(klass, method_id, WorkflowMethod(method))
except:
LOG('Base', ERROR,
'Could not generate worklow transition methods for workflow %s on class %s.' % (wf_id, klass),
error=sys.exc_info())
# Mark as generated
aq_method_generated[klass] = 1 aq_method_generated[klass] = 1
for super_klass in klass.__bases__:
_initializeDefaultProperties(super_klass)
class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyManager ): class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyManager ):
""" """
...@@ -123,11 +193,17 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -123,11 +193,17 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
# We want to use a default property view # We want to use a default property view
manage_propertiesForm = DTMLFile( 'dtml/properties', _dtmldir ) manage_propertiesForm = DTMLFile( 'dtml/properties', _dtmldir )
security.declareProtected( Permissions.AccessContentsInformation, 'test_dyn' )
def test_dyn(self):
"""
"""
initializeDynamicProperties(self, self.__class__)
def _aq_dynamic(self, id): def _aq_dynamic(self, id):
global aq_method_generated global aq_method_generated
klass = self.__class__ klass = self.__class__
if not aq_method_generated.has_key(klass): if not aq_method_generated.has_key(klass):
_initializeDefaultProperties(klass) initializeDynamicProperties(self, klass)
return getattr(self, id) return getattr(self, id)
return None return None
...@@ -149,6 +225,10 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana ...@@ -149,6 +225,10 @@ class Base( CopyContainer, PortalContent, Base18, ActiveObject, ERP5PropertyMana
def _getCategoryTool(self): def _getCategoryTool(self):
return aq_inner(self.getPortalObject().portal_categories) return aq_inner(self.getPortalObject().portal_categories)
def _doNothing(self):
# A method which does nothing (and can be used to build WorkflowMethods which trigger worklow transitions)
pass
# Generic accessor # Generic accessor
def _getDefaultAcquiredProperty(self, key, default_value, null_value, def _getDefaultAcquiredProperty(self, key, default_value, null_value,
base_category=None, portal_type=None, copy_value=0, mask_value=0, sync_value=0, base_category=None, portal_type=None, copy_value=0, mask_value=0, sync_value=0,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment