diff --git a/SpiffWorkflow/bpmn/parser/ProcessParser.py b/SpiffWorkflow/bpmn/parser/ProcessParser.py index 486be1fe..0a62a16f 100644 --- a/SpiffWorkflow/bpmn/parser/ProcessParser.py +++ b/SpiffWorkflow/bpmn/parser/ProcessParser.py @@ -43,7 +43,6 @@ def __init__(self, p, node, nsmap, data_stores, filename=None, lane=None): """ super().__init__(node, nsmap, filename=filename, lane=lane) self.parser = p - self.parsed_nodes = {} self.lane = lane self.spec = None self.process_executable = self.is_executable() @@ -100,8 +99,8 @@ def parse_node(self, node): can be called by a TaskParser instance, that is owned by this ProcessParser. """ - if node.get('id') in self.parsed_nodes: - return self.parsed_nodes[node.get('id')] + if node.get('id') in self.spec.task_specs: + return self.spec.task_specs[node.get('id')] (node_parser, spec_class) = self.parser._get_parser_class(node.tag) if not node_parser or not spec_class: diff --git a/SpiffWorkflow/bpmn/parser/TaskParser.py b/SpiffWorkflow/bpmn/parser/TaskParser.py index 8026a86c..ba48565a 100644 --- a/SpiffWorkflow/bpmn/parser/TaskParser.py +++ b/SpiffWorkflow/bpmn/parser/TaskParser.py @@ -203,7 +203,6 @@ def parse_node(self): boundary_event_nodes = self.doc_xpath('.//bpmn:boundaryEvent[@attachedToRef="%s"]' % self.bpmn_id) if boundary_event_nodes: parent = self._add_boundary_event(boundary_event_nodes) - self.process_parser.parsed_nodes[self.node.get('id')] = self.task children = [] outgoing = self.doc_xpath('.//bpmn:sequenceFlow[@sourceRef="%s"]' % self.bpmn_id) @@ -217,9 +216,10 @@ def parse_node(self): self.raise_validation_exception('When looking for a task spec, we found two items, ' 'perhaps a form has the same ID? (%s)' % target_ref) - c = self.process_parser.parse_node(target_node) + split_task = self.spec.task_specs.get(f'{target_ref}.BoundaryEventSplit') + c = self.process_parser.parse_node(target_node) if split_task is None else split_task position = self.get_position(target_node) - children.append((position, c, target_node, sequence_flow)) + children.append((position, c, sequence_flow)) if children: # Sort children by their y coordinate. @@ -229,11 +229,11 @@ def parse_node(self): default_outgoing = self.node.get('default') if len(children) == 1 and isinstance(self.task, (ExclusiveGateway, InclusiveGateway)): - (position, c, target_node, sequence_flow) = children[0] + (position, c, sequence_flow) = children[0] if self.parse_condition(sequence_flow) is None: default_outgoing = sequence_flow.get('id') - for (position, c, target_node, sequence_flow) in children: + for (position, c, sequence_flow) in children: self.connect_outgoing(c, sequence_flow, sequence_flow.get('id') == default_outgoing) return parent if boundary_event_nodes else self.task diff --git a/tests/SpiffWorkflow/bpmn/ParserTest.py b/tests/SpiffWorkflow/bpmn/ParserTest.py index b9e7dfbc..1c09a1af 100644 --- a/tests/SpiffWorkflow/bpmn/ParserTest.py +++ b/tests/SpiffWorkflow/bpmn/ParserTest.py @@ -46,3 +46,16 @@ def testInvalidProcessID(self): self.assertRaisesRegex( ValidationException, "The process '\w+' was not found*", self.parser.get_spec, "Process") + + def testBoundaryEvent(self): + bpmn_file = os.path.join(os.path.dirname(__file__), 'data', 'boundary_event_split.bpmn') + self.parser.add_bpmn_file(bpmn_file) + spec = self.parser.get_spec('Process_0ymnx41') + gw1 = spec.task_specs.get('gw_1') + gw2 = spec.task_specs.get('gw_2') + task = spec.task_specs.get('task_2') + split_task = spec.task_specs.get(f'{task.name}.BoundaryEventSplit') + self.assertNotIn(task, gw1.outputs) + self.assertIn(split_task, gw1.outputs) + self.assertNotIn(task, gw2.outputs) + self.assertIn(split_task, gw2.outputs) diff --git a/tests/SpiffWorkflow/bpmn/data/boundary_event_split.bpmn b/tests/SpiffWorkflow/bpmn/data/boundary_event_split.bpmn new file mode 100644 index 00000000..f0dd4b13 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/boundary_event_split.bpmn @@ -0,0 +1,108 @@ + + + + + Flow_01pj69c + + + Flow_01pj69c + Flow_1imjpib + Flow_1e2doc4 + + + + Flow_1imjpib + Flow_1baqf6p + Flow_0a5mw5g + + + False + + + Flow_1baqf6p + Flow_0qrmpxi + + + + Flow_0a5mw5g + Flow_1e2doc4 + Flow_1or38ex + + + True + + + + Flow_0qrmpxi + Flow_1or38ex + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +