Parse this node, and all children, returning the connected task spec.
(self)
| 178 | return split_task |
| 179 | |
| 180 | def parse_node(self): |
| 181 | """ |
| 182 | Parse this node, and all children, returning the connected task spec. |
| 183 | """ |
| 184 | try: |
| 185 | self.task = self.create_task() |
| 186 | # Why do we just set random attributes willy nilly everywhere in the code???? |
| 187 | # And we still pass around a gigantic kwargs dict whenever we create anything! |
| 188 | self.task.extensions = self.parse_extensions() |
| 189 | |
| 190 | io_spec = self.xpath('./bpmn:ioSpecification') |
| 191 | if len(io_spec) > 0: |
| 192 | self.task.io_specification = self.parse_io_spec() |
| 193 | |
| 194 | loop_characteristics = self.xpath('./bpmn:standardLoopCharacteristics') |
| 195 | if len(loop_characteristics) > 0: |
| 196 | self._add_loop_task(loop_characteristics[0]) |
| 197 | |
| 198 | mi_loop_characteristics = self.xpath('./bpmn:multiInstanceLoopCharacteristics') |
| 199 | if len(mi_loop_characteristics) > 0: |
| 200 | self._add_multiinstance_task(mi_loop_characteristics[0]) |
| 201 | |
| 202 | boundary_event_nodes = self.doc_xpath('.//bpmn:boundaryEvent[@attachedToRef="%s"]' % self.bpmn_id) |
| 203 | if boundary_event_nodes: |
| 204 | parent = self._add_boundary_event(boundary_event_nodes) |
| 205 | |
| 206 | children = [] |
| 207 | outgoing = self.doc_xpath('.//bpmn:sequenceFlow[@sourceRef="%s"]' % self.bpmn_id) |
| 208 | if len(outgoing) > 1 and not self.handles_multiple_outgoing(): |
| 209 | self.raise_validation_exception('Multiple outgoing flows are not supported for tasks of type') |
| 210 | for sequence_flow in outgoing: |
| 211 | target_ref = sequence_flow.get('targetRef') |
| 212 | try: |
| 213 | target_node = one(self.doc_xpath('.//bpmn:*[@id="%s"]'% target_ref)) |
| 214 | except Exception: |
| 215 | self.raise_validation_exception('When looking for a task spec, we found two items, ' |
| 216 | 'perhaps a form has the same ID? (%s)' % target_ref) |
| 217 | |
| 218 | split_task = self.spec.task_specs.get(f'{target_ref}.BoundaryEventSplit') |
| 219 | c = self.process_parser.parse_node(target_node) if split_task is None else split_task |
| 220 | position = self.get_position(target_node) |
| 221 | children.append((position, c, sequence_flow)) |
| 222 | |
| 223 | if children: |
| 224 | # Sort children by their y coordinate. |
| 225 | # Why?? Isn't the point of parallel tasks that they can be executed in any order (or simultaneously)? |
| 226 | # And what if they're arranged horizontally? |
| 227 | children = sorted(children, key=lambda tup: float(tup[0]["y"])) |
| 228 | |
| 229 | default_outgoing = self.node.get('default') |
| 230 | if len(children) == 1 and isinstance(self.task, (ExclusiveGateway, InclusiveGateway)): |
| 231 | (position, c, sequence_flow) = children[0] |
| 232 | if self.parse_condition(sequence_flow) is None: |
| 233 | default_outgoing = sequence_flow.get('id') |
| 234 | |
| 235 | for (position, c, sequence_flow) in children: |
| 236 | self.connect_outgoing(c, sequence_flow, sequence_flow.get('id') == default_outgoing) |
| 237 |
no test coverage detected