Commit 35bc8338 authored by wenjie.zheng's avatar wenjie.zheng Committed by Sebastien Robin

Base.py: MERGE ALL TOGETHER.

parent 2ff4d690
...@@ -123,119 +123,6 @@ def resetRegisteredERP5WorkflowMethod(portal_type=None): ...@@ -123,119 +123,6 @@ def resetRegisteredERP5WorkflowMethod(portal_type=None):
for method in erp5workflow_method_registry: for method in erp5workflow_method_registry:
method.reset(portal_type=portal_type) method.reset(portal_type=portal_type)
class ERP5WorkflowMethod(Method):
### to get the name of the class
def __init__(self, method, id=None, reindex=1):
self._m = method
if id is None:
self._transition_id = method.__name__
else:
self._transition_id = id
LOG("134 initializing method '%s'"%self._transition_id, WARNING, " in Base.py")
if not method.__name__.startswith('_'):
self.__name__ = method.__name__
for func_id in ['func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']:
setattr(self, func_id, getattr(method, func_id, None))
self._invoke_once = {}
self._invoke_always = {} # Store in a dict all workflow IDs which require to
# invoke wrapWorkflowMethod at every call
# during the same transaction
def getTransitionId(self):
return self._transition_id
def __call__(self, instance, *args, **kw):
LOG("148 Calling method '%s' by '%s'"%(self._transition_id, instance.getId()), WARNING, " in Base.py")
if getattr(self, '__name__', None) in ('getPhysicalPath', 'getId',):
return self._m(instance, *args, **kw)
# Build a list of transitions which may need to be invoked
instance_path = instance.getPhysicalPath()
portal_type = instance.portal_type
transactional_variable = getTransactionalVariable()
invoke_once_dict = self._invoke_once.get(portal_type, {})
valid_invoke_once_item_list = []
# Only keep those transitions which were never invoked
once_transition_dict = {}
# New implementation does not use any longer wrapWorkflowMethod
# but directly calls the workflow methods
for wf_id, transition_list in invoke_once_dict.iteritems():
valid_transition_list = []
for transition_id in transition_list:
once_transition_key = ('Products.ERP5Type.Base.ERP5WorkflowMethod.__call__',
wf_id, transition_id, instance_path)
once_transition_dict[(wf_id, transition_id)] = once_transition_key
if once_transition_key not in transactional_variable:
valid_transition_list.append(transition_id)
if valid_transition_list:
valid_invoke_once_item_list.append((wf_id, valid_transition_list))
LOG("173 _invoke_always list contains: '%s'"%self._invoke_always,WARNING," in Base.py")
candidate_transition_item_list = valid_invoke_once_item_list + \
self._invoke_always.get(portal_type, {}).items()
# Try to return immediately if there are no transition to invoke
if not candidate_transition_item_list:
return apply(self.__dict__['_m'], (instance,) + args, kw)
try:
wf_module = instance.getPortalObject().portal_workflow
except AttributeError:
return self._m(instance, *arge, **kw)
valid_transition_item_list = []
for wf_id, transition_list in candidate_transition_item_list:
valid_list = []
workflow = wf_module._getOb(wf_id)
for transition_id in transition_list:
LOG("191 Type '%s' is checking transition '%s' of workflow '%s'" %(instance.getPortalType(), transition_id, wf_id), WARNING, " in Base.py")
if workflow.isERP5WorkflowMethodSupported(instance, workflow._getOb(transition_id)):
valid_list.append(transition_id)
once_transition_key = once_transition_dict.get((wf_id, transition_id))
transactional_variable[once_transition_key] = 1
else:
raise UnsupportedWorkflowMethod(instance, wf_id, transition_id)
if valid_list:
valid_transition_item_list.append((wf_id, valid_list))
result = apply(self.__dict__['_m'], (instance,) + args, kw)
### zwj: Execute method
for wf_id, transition_list in valid_transition_item_list:
try:
for tr_id in transition_list:
method = wf_module._getOb(wf_id)._getOb(tr_id)
LOG(" 208 executing method '%s' of workflow '%s'"%(tr_id, wf_id), WARNING, " in Base.py")
method.execute(instance)
except ObjectDeleted:
raise ObjectDeleted(result)
except ObjectMoved, ex:
raise ObjectMoved(ex.getNewObject(), result)
def registerERP5TransitionAlways(self, portal_type, workflow_id, transition_id):
LOG(" 216 register transition-always '%s' of workflow '%s'"%(transition_id, workflow_id), WARNING, " in Base.py")
transition_list = self._invoke_always.setdefault(portal_type, {}).setdefault(workflow_id, [])
if transition_id not in transition_list: transition_list.append(transition_id)
self.registerERP5()
def registerERP5TransitionOncePerTransaction(self, portal_type, workflow_id, transition_id):
LOG(" 222 register transition-once '%s' of workflow '%s'"%(transition_id, worfklow_id), WARNING, " in Base.py")
transition_list = self._invoke_once.setdefault(portal_type, {}).setdefault(workflow_id, [])
if transition_id not in transition_list: transition_list.append(transition_id)
self.registerERP5()
def registerERP5(self):
erp5workflow_method_registry.append(self)
def reset(self, portal_type=None):
if portal_type:
self._invoke_once[portal_type] = {}
self._invoke_always[portal_type] = {}
else:
self._invoke_once = {}
self._invoke_always = {}
### ==========================================================================
class WorkflowMethod(Method): class WorkflowMethod(Method):
def __init__(self, method, id=None, reindex=1): def __init__(self, method, id=None, reindex=1):
...@@ -342,7 +229,8 @@ class WorkflowMethod(Method): ...@@ -342,7 +229,8 @@ class WorkflowMethod(Method):
# a run-once transition, prevent it from running again in # a run-once transition, prevent it from running again in
# the same transaction # the same transaction
transactional_variable[once_transition_key] = 1 transactional_variable[once_transition_key] = 1
elif candidate_workflow.__class__.__name__ == 'DCWorkflowDefinition': elif candidate_workflow.__class__.__name__ == 'DCWorkflowDefinition' or \
candidate_workflow.__class__.__name__ == 'Workflow':
raise UnsupportedWorkflowMethod(instance, wf_id, transition_id) raise UnsupportedWorkflowMethod(instance, wf_id, transition_id)
# XXX Keep the log for projects that needs to comment out # XXX Keep the log for projects that needs to comment out
# the previous line. # the previous line.
...@@ -642,195 +530,7 @@ def getClassPropertyList(klass): ...@@ -642,195 +530,7 @@ def getClassPropertyList(klass):
if p not in ps_list]) if p not in ps_list])
return ps_list return ps_list
def initializePortalTypeERP5WorkflowMethod(ptype_klass, portal_workflow): def initializePortalTypeWorkflowMethods(ptype_klass, portal_workflow):
portal_type = ptype_klass.__name__
workflow_dict = {}
interaction_workflow_dict = {}
portal_workflow = aq_inner(portal_workflow)
portal_type_module = portal_workflow.getPortalObject().getDefaultModule(portal_type="portal_types")
portal_type_value = portal_type_module._getOb(portal_type, None)
for ERP5Workflow in portal_workflow.getWorkflowValueListFor(portal_type_value):
ERP5Workflow_id = ERP5Workflow.getId()
workflow_type = ERP5Workflow.__class__.__name__
LOG(" 661 initializing portal type '%s' "%ptype_klass.__name__, WARNING, " in Base.py")
LOG(" 664 Found Workflow type = %s"%workflow_type, WARNING, " in Base.py.")
if workflow_type == 'Workflow' or workflow_type == 'DCWorkflowDefinition':
state_var = ERP5Workflow.getStateVariable()
LOG(" 666 Found Workflow '%s' with state_var '%s'"%(ERP5Workflow_id, state_var), WARNING, " in Base.py.")
for method_id, getter in (
('get%s' % UpperCase(state_var), WorkflowState.Getter),
('get%sTitle' % UpperCase(state_var), WorkflowState.TitleGetter),
('getTranslated%s' % UpperCase(state_var),
WorkflowState.TranslatedGetter),
('getTranslated%sTitle' % UpperCase(state_var),
WorkflowState.TranslatedTitleGetter),
('serialize%s' % UpperCase(state_var), WorkflowState.SerializeGetter),
):
method = getter(method_id, ERP5Workflow_id)
ptype_klass.registerAccessor(method,
Permissions.AccessContentsInformation)
if workflow_type == 'Workflow':
LOG(" 681 Generating methods of Workflow type workflow '%s'"%ERP5Workflow_id, WARNING, " in Base.py")
transition_id_list = [] #ERP5Workflow.objectIds(portal_type='Transition')
transition_list = ERP5Workflow.objectValues(portal_type='Transition')
for tr in transition_list:
transition_id_list.append(tr.getReference())### getRef, this id list is actually a reference list
LOG(" 686 transition_id_list = '%s'"%transition_id_list, WARNING, " in Base.py")
elif workflow_type == 'DCWorkflowDefinition':
LOG(" 688 Generating methods of DCWorkflow '%s'"%ERP5Workflow_id, WARNING, " in Base.py")
transition_id_list = ERP5Workflow.transitions
transition_list = []
for transition_id in transition_id_list:
LOG(" 692 register transition '%s' to transition_list"%transition_id, WARNING, " in Base.py")
transition = ERP5Workflow.transitions.get(transition_id)
transition_list.append(transition)
storage = workflow_dict
elif workflow_type == 'Interaction Workflow' or workflow_type == 'InteractionWorkflowDefinition':
if workflow_type == 'Interaction Workflow':
LOG(" 698 Generating methods of Interaction Workflow '%s'"%ERP5Workflow_id, WARNING, ' in Base.py')
transition_id_list = []
transition_list = ERP5Workflow.objectValues(portal_type='Interaction')
for tr in transition_list:
transition_id_list.append(tr.getReference()) # remove suffinx
LOG(" 703 transition_id_list = '%s'"%transition_id_list, WARNING, ' in Base.py')
elif workflow_type == 'InteractionWorkflowDefinition':
LOG(" 705 Generating methods of DC Interaction Workflow '%s'"%ERP5Workflow_id, WARNING, ' in Base.py')
transition_id_list = ERP5Workflow.interactions
transition_list = []
for interaction_id in transition_id_list:
interaction = ERP5Workflow.interactions.get(interaction_id)
transition_list.append(interaction)
storage = interaction_workflow_dict
else:
LOG("Please check workflow list definded. '%s' '%s' is ignored "%(workflow_type, ERP5Workflow_id),WARNING,"in Base.py/initializePortalTypeWorkflowMethod.")
continue
### zwj: compatibility for Interaction Workflow and Workflow ===============
transition_id_set = set(transition_id_list)
trigger_dict = {}
for transition in transition_list:
transition_id = transition.getReference()
LOG("722 Found transition '%s'"%transition_id,WARNING, " in Base.py")
if transition.trigger_type == TRIGGER_WORKFLOW_METHOD:
LOG("723 Register Trigger by workflow method transition %s"%transition_id,WARNING, " in Base.py")
trigger_dict[transition_id] = transition
storage[ERP5Workflow_id] = (transition_id_set, trigger_dict)
### zwj: generate Workflow methods
for ERP5Workflow_id, v in workflow_dict.iteritems():
LOG("730 Generating methods of Workflow '%s'"%ERP5Workflow_id, WARNING, " in Base.py")
transition_id_set, trigger_dict = v
for tr_id, tdef in trigger_dict.iteritems():
LOG("733 processing transition '%s' of '%s'"%(tr_id,ERP5Workflow_id), WARNING, "in Base.py")
method_id = convertToMixedCase(tr_id)
LOG(" 731 register transition '%s' as method '%s'"%(tr_id, method_id), WARNING, " in Base.py")
try:
method = getattr(ptype_klass, method_id)
except AttributeError:
LOG("738 processing new method '%s'"%method_id, WARNING, " in Base.py.")
ptype_klass.security.declareProtected(Permissions.AccessContentsInformation,
method_id)
ptype_klass.registerERP5WorkflowMethod(method_id, ERP5Workflow_id, tr_id, 0)
continue
LOG("743 check if method '%s' is callable"%method_id, WARNING, " in Base.py")
# Wrap method
if not callable(method):
LOG('initializePortalTypeDynamicWorkflowMethods', 100,
'WARNING! Can not initialize %s on %s' % \
(method_id, portal_type))
continue
LOG("751 check if workflow method '%s' is an ERP5 WorkflowMethod"%method_id, WARNING, " in Base.py")
if not isinstance(method, ERP5WorkflowMethod):
method = ERP5WorkflowMethod(method, method_id)
setattr(ptype_klass, method_id, method)
else:
transition_id = method.getTransitionId()
if transition_id in transition_id_set:
method.registerERP5TransitionAlways(portal_type, ERP5Workflow_id, transition_id)
method.registerERP5TransitionAlways(portal_type, ERP5Workflow_id, tr_id)
### zwj: generate interaction workflow methods
if not interaction_workflow_dict:
return
class_method_id_list = ptype_klass.getClassMethodIdList(ptype_klass)
interaction_queue = []
LOG(" 767 Initializing Interaction Workflow methods",WARNING," in Base.py")
for wf_id, v in interaction_workflow_dict.iteritems():
transition_id_set, trigger_dict = v
for tr_id, tdef in trigger_dict.iteritems():
# check portal type filter
LOG(" 772 processing transition '%s' of workflow '%s'"%(tdef.getId(), wf_id), WARNING, " in Base.py.")
type_filter = list(tdef.portal_type_filter)
if (type_filter != [] and portal_type not in type_filter):
continue
# check portal type group filter
group_filter = list(tdef.portal_type_group_filter) ### not use property sheet accessor
if group_filter != []:
getPortalGroupedTypeSet = portal_workflow.getPortalObject()._getPortalGroupedTypeSet
if not any(portal_type in getPortalGroupedTypeSet(portal_type_group) for
portal_type_group in group_filter):
continue
# gather trigger method id
if list(tdef.method_id) == []:
raise NotImplementedError ("Please give a trigger method for interaction: %s in interaction workflow: %s."%(tr_id, wf_id))
for imethod_id in list(tdef.method_id):
if wildcard_interaction_method_id_match(imethod_id):
method_id_matcher = re.compile(imethod_id).match
# queue transitions using regexps for later examination
interaction_queue.append((wf_id,
tr_id,
transition_id_set,
tdef.once_per_transaction,
method_id_matcher))
method_id_list = filter(method_id_matcher, class_method_id_list)
else:
method_id_list = [imethod_id]
for method_id in method_id_list:
method = getattr(ptype_klass, method_id, _MARKER)
if method is _MARKER:
if method_id not in ptype_klass.security.names:
ptype_klass.security.declareProtected(
Permissions.AccessContentsInformation, method_id)
ptype_klass.registerERP5WorkflowMethod(method_id, wf_id, tr_id, tdef.once_per_transaction)
continue
# wrap method
if not callable(method):
LOG('initializePortalTypeDynamicWorkflowMethods', 100,
'WARNING! Can not initialize %s on %s' % \
(method_id, portal_type))
continue
if not isinstance(method, ERP5WorkflowMethod):
method = ERP5WorkflowMethod(method, method_id)
setattr(ptype_klass, method_id, method)
else:
transition_id = method.getTransitionId()
if transition_id in transition_id_set:
method.registerERP5TransitionAlways(portal_type, wf_id, transition_id)
if tdef.once_per_transaction:
method.registerERP5TransitionOncePerTransaction(portal_type, wf_id, tr_id)
else:
method.registerERP5TransitionAlways(portal_type, wf_id, tr_id)
if not interaction_queue:
return
new_method_set = set(ptype_klass.getWorkflowMethodIdList())
added_method_set = new_method_set.difference(class_method_id_list)
for wf_id, tr_id, transition_id_set, once, method_id_matcher in interaction_queue:
for method_id in filter(method_id_matcher, added_method_set):
# method must already exist and be a workflow method
method = getattr(ptype_klass, method_id)
transition_id = method.getTransitionId()
if transition_id in transition_id_set:
method.registerERP5TransitionAlways(portal_type, wf_id, transition_id)
if once:
method.registerERP5TransitionOncePerTransaction(portal_type, wf_id, tr_id)
else:
method.registerERP5TransitionAlways(portal_type, wf_id, tr_id)
def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow):
"""We should now make sure workflow methods are defined """We should now make sure workflow methods are defined
and also make sure simulation state is defined.""" and also make sure simulation state is defined."""
# aq_inner is required to prevent extra name lookups from happening # aq_inner is required to prevent extra name lookups from happening
...@@ -841,15 +541,15 @@ def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow): ...@@ -841,15 +541,15 @@ def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow):
portal_workflow = aq_inner(portal_workflow) portal_workflow = aq_inner(portal_workflow)
portal_type = ptype_klass.__name__ portal_type = ptype_klass.__name__
dc_workflow_dict = {} workflow_dict = {}
interaction_workflow_dict = {} interaction_workflow_dict = {}
for wf in portal_workflow.getWorkflowsFor(portal_type): for wf in portal_workflow.getWorkflowValueListFor(portal_type):
wf_id = wf.id wf_id = wf.getId()
wf_type = wf.__class__.__name__ wf_type = wf.__class__.__name__
if wf_type == "DCWorkflowDefinition": if wf_type == "DCWorkflowDefinition" or wf_type == "Workflow":
# Create state var accessor # Create state var accessor
# and generate methods that support the translation of workflow states # and generate methods that support the translation of workflow states
state_var = wf.variables.getStateVar() state_var = wf.getStateVariable()
for method_id, getter in ( for method_id, getter in (
('get%s' % UpperCase(state_var), WorkflowState.Getter), ('get%s' % UpperCase(state_var), WorkflowState.Getter),
('get%sTitle' % UpperCase(state_var), WorkflowState.TitleGetter), ('get%sTitle' % UpperCase(state_var), WorkflowState.TitleGetter),
...@@ -865,16 +565,17 @@ def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow): ...@@ -865,16 +565,17 @@ def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow):
ptype_klass.registerAccessor(method, ptype_klass.registerAccessor(method,
Permissions.AccessContentsInformation) Permissions.AccessContentsInformation)
storage = dc_workflow_dict storage = workflow_dict
transitions = wf.transitions transitions = wf.getTransitionValueList()
elif wf_type == "InteractionWorkflowDefinition": elif wf_type == "InteractionWorkflowDefinition" or wf_type == "InteractionWorkflow":
storage = interaction_workflow_dict storage = interaction_workflow_dict
transitions = wf.interactions transitions = wf.getTransitionValueList()
else: else:
continue continue
# extract Trigger transitions from workflow definitions for later # extract Trigger transitions from workflow definitions for later
transition_id_set = set(transitions.objectIds()) transition_id_set = set(wf.getTransitionIdList())
trigger_dict = {} trigger_dict = {}
for tr_id in transition_id_set: for tr_id in transition_id_set:
tdef = transitions[tr_id] tdef = transitions[tr_id]
...@@ -883,8 +584,8 @@ def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow): ...@@ -883,8 +584,8 @@ def initializePortalTypeDynamicWorkflowMethods(ptype_klass, portal_workflow):
storage[wf_id] = (transition_id_set, trigger_dict) storage[wf_id] = (transition_id_set, trigger_dict)
# Generate Workflow method: # Generate Workflow method
for wf_id, v in dc_workflow_dict.iteritems(): for wf_id, v in workflow_dict.iteritems():
transition_id_set, trigger_dict = v transition_id_set, trigger_dict = v
for tr_id, tdef in trigger_dict.iteritems(): for tr_id, tdef in trigger_dict.iteritems():
method_id = convertToMixedCase(tr_id) method_id = convertToMixedCase(tr_id)
......
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