Commit 92e4a9c0 authored by Nicolas Dumazet's avatar Nicolas Dumazet

and finally avoid iterating twice over the interaction list

It seems that the only methods that we wanted to match in the second pass
are class methods created during the first pass:
finding the newly created candidates is easy if we keep track of class methods before and after the first pass

And then, the ony interactions than *can* augment the existing workflow definitions
are the ones using regular expressions, according to the code comments.
Queue those interactions during the first pass to reduce the space search.

Finally, the second pass is cheaper because we *know* that methods do exist
and _are_ Workflow methods already.


The overall cost of creating workflow methods should be lower thanks to those
efforts.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@42497 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent ab223cf8
...@@ -700,25 +700,29 @@ def initializePortalTypeDynamicWorkflowMethods(self, klass, ptype, prop_holder, ...@@ -700,25 +700,29 @@ def initializePortalTypeDynamicWorkflowMethods(self, klass, ptype, prop_holder,
if not interaction_workflow_dict: if not interaction_workflow_dict:
return return
class_method_list = prop_holder.getClassMethodIdList(klass)
# only compute once this (somehow) costly list # only compute once this (somehow) costly list
all_method_id_list = prop_holder.getAccessorMethodIdList() + \ all_method_id_list = prop_holder.getAccessorMethodIdList() + \
prop_holder.getWorkflowMethodIdList() + \ prop_holder.getWorkflowMethodIdList() + \
prop_holder.getClassMethodIdList(klass) class_method_list
interaction_queue = []
# XXX This part is (more or less...) a copy and paste # XXX This part is (more or less...) a copy and paste
# We need to run this part twice in order to handle interactions of interactions for wf_id, v in interaction_workflow_dict.iteritems():
# ex. an interaction workflow creates a workflow method which matches transition_id_set, trigger_dict = v
# the regexp of another interaction workflow
for wf_id in interaction_workflow_dict.keys()*2:
transition_id_set, trigger_dict = interaction_workflow_dict[wf_id]
for tr_id, tdef in trigger_dict.iteritems(): for tr_id, tdef in trigger_dict.iteritems():
# XXX Prefiltering per portal type would be more efficient # XXX Prefiltering per portal type would be more efficient
for imethod_id in tdef.method_id: for imethod_id in tdef.method_id:
if wildcard_interaction_method_id_match(imethod_id): if wildcard_interaction_method_id_match(imethod_id):
# Interactions workflows can use regexp based wildcard methods # Interactions workflows can use regexp based wildcard methods
method_id_matcher = re.compile(imethod_id) # XXX What happens if exception ? # XXX What happens if exception ?
method_id_matcher = re.compile(imethod_id).match
# queue transitions using regexps for later examination
interaction_queue.append((wf_id, tr_id, tdef, method_id_matcher))
# XXX - class stuff is missing here # XXX - class stuff is missing here
method_id_list = filter(method_id_matcher.match, all_method_id_list) method_id_list = filter(method_id_matcher, all_method_id_list)
else: else:
# Single method # Single method
# XXX What if the method does not exist ? # XXX What if the method does not exist ?
...@@ -757,6 +761,26 @@ def initializePortalTypeDynamicWorkflowMethods(self, klass, ptype, prop_holder, ...@@ -757,6 +761,26 @@ def initializePortalTypeDynamicWorkflowMethods(self, klass, ptype, prop_holder,
else: else:
method.registerTransitionAlways(ptype, wf_id, tr_id) method.registerTransitionAlways(ptype, wf_id, tr_id)
if not interaction_queue:
return
new_method_set = set(prop_holder.getClassMethodItemList(klass))
added_method_set = new_method_set.difference(class_method_list)
# We need to run this part twice in order to handle interactions of interactions
# ex. an interaction workflow creates a workflow method which matches
# the regexp of another interaction workflow
for wf_id, tr_id, tdef, 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(klass, method_id)
transition_id = method.getTransitionId()
if transition_id in transition_id_set:
method.registerTransitionAlways(ptype, wf_id, transition_id)
if tdef.once_per_transaction:
method.registerTransitionOncePerTransaction(ptype, wf_id, tr_id)
else:
method.registerTransitionAlways(ptype, wf_id, tr_id)
class Base( CopyContainer, class Base( CopyContainer,
PortalContent, PortalContent,
ActiveObject, ActiveObject,
......
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