diff --git a/product/ERP5Type/Base.py b/product/ERP5Type/Base.py
index 8ed5889a1088a6a88542753d756984ccbe743dd3..3ff16c53cf758adc796d2b2042ec12ca28c42c18 100644
--- a/product/ERP5Type/Base.py
+++ b/product/ERP5Type/Base.py
@@ -124,37 +124,55 @@ class WorkflowMethod(Method):
       # should ne executed. - XXX
       return apply(self._m, (instance,) + args, kw) 
 
-    call_method = 0 # By default, this method was never called
-    if self._invoke_once:
-      # Check if this method has already been called in this transaction
-      # (only check this if we use once only workflow methods)
-      call_method_key = ('Products.ERP5Type.Base.WorkflowMethod.__call__', self._id, instance.getPhysicalPath())
-      transactional_variable = getTransactionalVariable(instance)
-      try:
-        call_method = transactional_variable[call_method_key]
-      except KeyError:
-        transactional_variable[call_method_key] = 1
+    # New implementation does not use any longer wrapWorkflowMethod
+    # but directly calls the workflow methods
+    wf = getToolByName(instance, 'portal_workflow', None)
 
-    if call_method and not self._invoke_always:
-      # Try to return immediately if there are no invoke always workflow methods
+    # Build a list of transitions which may need to be invoked
+    instance_path = instance.getPhysicalPath()
+    portal_type = instance.portal_type
+    transactional_variable = getTransactionalVariable(instance)
+    invoke_once_item_list = self._invoke_once.get(portal_type, {}).items()
+    valid_invoke_once_item_list = []
+    # Only keep those transitions which were never invoked
+    for wf_id, transition_list in invoke_once_item_list:
+      valid_transition_list = []
+      for transition_id in transition_list:
+        once_transition_key = ('Products.ERP5Type.Base.WorkflowMethod.__call__',
+                                wf_id, transition_id, instance_path)
+        try:
+          already_called_transition = transactional_variable[once_transition_key]
+        except KeyError:
+          already_called_transition = 0
+          transactional_variable[once_transition_key] = 1
+        if not already_called_transition:
+          valid_transition_list.append(transition_id)
+      if valid_transition_list:
+        valid_invoke_once_item_list.append((wf_id, valid_transition_list))
+    candidate_transition_item_list = valid_invoke_once_item_list + \
+                                      self._invoke_once.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)
 
-    # Invoke transitions on appropriate workflow
-    portal_type = instance.portal_type # Access by attribute to prevent recursion
-    if call_method:
-      candidate_transition_item_list = self._invoke_always.get(portal_type, {}).items()
-    else:
-      candidate_transition_item_list = self._invoke_always.get(portal_type, {}).items() + \
-                                       self._invoke_once.get(portal_type, {}).items()
-
-    # New implementation does not use any longer wrapWorkflowMethod
-    wf = getToolByName(instance, 'portal_workflow', None)
+    # Prepare a list of transitions which should be invoked
+    #   this list is based on the results of isWorkflowMethodSupported
+    #   XXX - the behaviour of isWorkflowMethodSupported should be extended
+    #         some day so that a workflow method raises an exception
+    #         when it is invoked from a workflow state which does 
+    #         not support it or whenever guards reject it
+    valid_transition_item_list = []
+    for wf_id, transition_list in candidate_transition_item_list:
+      candidate_workflow = wf[wf_id]
+      valid_list = [transition_id for transition_id in transition_list
+                      if candidate_workflow.isWorkflowMethodSupported(instance, transition_id)]
+      if valid_list:
+        valid_transition_item_list.append((wf_id, valid_list))
 
     # Call whatever must be called before changing states
-    after_invoke_once = {}
     for wf_id, transition_list in candidate_transition_item_list:
-      after_invoke_once[wf_id] = wf[wf_id].notifyBefore(instance, self._id,
-                          args=args, kw=kw, transition_list=transition_list)
+       wf[wf_id].notifyBefore(instance, self._id, args=args, kw=kw, transition_list=transition_list)
 
     # Compute expected result
     result = apply(self.__dict__['_m'], (instance,) + args, kw)
@@ -172,11 +190,11 @@ class WorkflowMethod(Method):
       else:
         if getattr(aq_base(instance), 'reindexObject', None) is not None:
           instance.reindexObject()
-        
+
     # Call whatever must be called after changing states
     for wf_id, transition_list in candidate_transition_item_list:
       wf[wf_id].notifySuccess(instance, self._id, result, args=args, kw=kw, transition_list=transition_list)
-      
+
     # Return result finally
     return result
 
@@ -184,14 +202,16 @@ class WorkflowMethod(Method):
     """
       Transitions registered as always will be invoked always
     """
-    self._invoke_always.setdefault(portal_type, {}).setdefault(workflow_id, []).append(transition_id)
+    transition_list = self._invoke_always.setdefault(portal_type, {}).setdefault(workflow_id, [])
+    if transition_id not in transition_list: transition_list.append(transition_id)
 
   def registerTransitionOncePerTransaction(self, portal_type, workflow_id, transition_id):
     """
       Transitions registered as one per transactions will be invoked 
       only once per transaction
     """
-    self._invoke_once.setdefault(portal_type, {}).setdefault(workflow_id, []).append(transition_id)
+    transition_list = self._invoke_once.setdefault(portal_type, {}).setdefault(workflow_id, [])
+    if transition_id not in transition_list: transition_list.append(transition_id)
 
 class ActionMethod(Method):
 
@@ -506,7 +526,9 @@ def initializePortalTypeDynamicWorkflowMethods(self, klass, ptype, prop_holder):
                     (method_id, str(work_method_holder)))
   # 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 in portal_workflow.getWorkflowsFor(self) * 2:
+  # ex. an interaction workflow creates a workflow method which matches
+  # the regexp of another interaction workflow
+  for wf in portal_workflow.getWorkflowsFor(self) * 2: # This is really necesary
     wf_id = wf.id
     if wf.__class__.__name__ in ('InteractionWorkflowDefinition', ):
       for tr_id in wf.interactions.objectIds():