diff --git a/SpiffWorkflow/bpmn/util/subworkflow.py b/SpiffWorkflow/bpmn/util/subworkflow.py index 9ebb1d17..4e1740ef 100644 --- a/SpiffWorkflow/bpmn/util/subworkflow.py +++ b/SpiffWorkflow/bpmn/util/subworkflow.py @@ -19,6 +19,7 @@ from SpiffWorkflow import Workflow from SpiffWorkflow.exceptions import TaskNotFoundException +from .task import BpmnTaskIterator class BpmnBaseWorkflow(Workflow): @@ -31,6 +32,9 @@ def __init__(self, spec, **kwargs): def data_objects(self): return self.data.get('data_objects', {}) + def get_tasks_iterator(self, first_task=None, **kwargs): + return BpmnTaskIterator(first_task or self.task_tree, **kwargs) + class BpmnSubWorkflow(BpmnBaseWorkflow): diff --git a/SpiffWorkflow/bpmn/util/task.py b/SpiffWorkflow/bpmn/util/task.py index c167f8d5..e3aa4937 100644 --- a/SpiffWorkflow/bpmn/util/task.py +++ b/SpiffWorkflow/bpmn/util/task.py @@ -41,10 +41,11 @@ def _catches_event(task): class BpmnTaskIterator(TaskIterator): - def __init__(self, task, end_at_spec=None, max_depth=1000, depth_first=True, task_filter=None, **kwargs): + def __init__(self, task, end_at_spec=None, max_depth=1000, depth_first=True, skip_subpprocesses=False, task_filter=None, **kwargs): task_filter = task_filter or BpmnTaskFilter(**kwargs) super().__init__(task, end_at_spec, max_depth, depth_first, task_filter) + self.skip_subpprocesses = skip_subpprocesses def _next(self): @@ -61,7 +62,11 @@ def _next(self): task.task_spec.name != self.end_at_spec, ]): # Do not descend into a completed subprocess to look for unfinished tasks. - if subprocess is None or (task.state >= TaskState.FINISHED_MASK and self.task_filter.state <= TaskState.FINISHED_MASK): + if ( + subprocess is None + or self.skip_subpprocesses + or (task.state >= TaskState.FINISHED_MASK and self.task_filter.state <= TaskState.FINISHED_MASK) + ): subprocess_tasks = [] else: subprocess_tasks = [subprocess.task_tree] diff --git a/SpiffWorkflow/bpmn/workflow.py b/SpiffWorkflow/bpmn/workflow.py index 02544ce5..1a132d76 100644 --- a/SpiffWorkflow/bpmn/workflow.py +++ b/SpiffWorkflow/bpmn/workflow.py @@ -28,7 +28,6 @@ from SpiffWorkflow.bpmn.specs.control import BoundaryEventSplit from SpiffWorkflow.bpmn.util.subworkflow import BpmnBaseWorkflow, BpmnSubWorkflow -from SpiffWorkflow.bpmn.util.task import BpmnTaskIterator from .script_engine.python_engine import PythonScriptEngine @@ -79,9 +78,6 @@ def parent_workflow(self): def depth(self): return 0 - def get_tasks_iterator(self, first_task=None, **kwargs): - return BpmnTaskIterator(first_task or self.task_tree, **kwargs) - def create_subprocess(self, my_task, spec_name): # This creates a subprocess for an existing task subprocess = BpmnSubWorkflow( @@ -114,30 +110,33 @@ def catch(self, event): :param event: the thrown event """ - if event.target is None: + if event.target is not None: + # This limits results to tasks in the specified workflow + tasks = event.target.get_tasks(skip_subpprocesses=True, state=TaskState.NOT_FINISHED_MASK, catches_event=event) + else: self.update_collaboration(event) tasks = self.get_tasks(state=TaskState.NOT_FINISHED_MASK, catches_event=event) # Figure out if we need to create an external event if len(tasks) == 0: self.bpmn_events.append(event) - else: - tasks = self.get_tasks(state=TaskState.NOT_FINISHED_MASK, catches_event=event) for task in tasks: task.task_spec.catch(task, event) - - self.refresh_waiting_tasks() + if len(tasks) > 0: + self.refresh_waiting_tasks() def send_event(self, event): """Allows this workflow to catch an externally generated event.""" - tasks = self.get_tasks(state=TaskState.NOT_FINISHED_MASK, catches_event=event) - if len(tasks) == 0: - raise WorkflowException(f"This process is not waiting for {event.event_definition.name}") - for task in tasks: - task.task_spec.catch(task, event) - - self.refresh_waiting_tasks() + if event.target is not None: + self.catch(event) + else: + tasks = self.get_tasks(state=TaskState.NOT_FINISHED_MASK, catches_event=event) + if len(tasks) == 0: + raise WorkflowException(f"This process is not waiting for {event.event_definition.name}") + for task in tasks: + task.task_spec.catch(task, event) + self.refresh_waiting_tasks() def get_events(self): """Returns the list of events that cannot be handled from within this workflow."""