MCPcopy
hub / github.com/sartography/SpiffWorkflow / parse_node

Method parse_node

SpiffWorkflow/bpmn/parser/TaskParser.py:180–242  ·  view source on GitHub ↗

Parse this node, and all children, returning the connected task spec.

(self)

Source from the content-addressed store, hash-verified

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

Callers 1

_add_boundary_eventMethod · 0.45

Calls 15

create_taskMethod · 0.95
_add_loop_taskMethod · 0.95
_add_boundary_eventMethod · 0.95
connect_outgoingMethod · 0.95
ValidationExceptionClass · 0.90
oneFunction · 0.85
xpathMethod · 0.80
parse_io_specMethod · 0.80
doc_xpathMethod · 0.80

Tested by

no test coverage detected