def process_node_end_event(p: Process, xml_node) -> None: """ Create an end event from the process """ node_name = normalize_name(xml_node.get("name")) task = EndEvent(parent_process=p, id=xml_node.get("id"), name=node_name) p.add_end_event(task)
def process_parallel_gateway(p: Process, xml_node) -> None: """ Create an end event from the process """ node_name = normalize_name(xml_node.get("name")) task = ParallelGateway(parent_process=p, id=xml_node.get("id"), name=node_name) p.add_task(task)
def process_exclusive_gateway(p: Process, xml_node) -> None: """ Create an exclusive gateway from the process """ node_name = normalize_name(xml_node.get("name")) task = ExclusiveGateway(parent_process=p, id=xml_node.get("id"), name=node_name) p.add_task(task)
def process_usertask(p: Process, xml_node) -> None: """ Create a HumanTask element from the process """ node_name = normalize_name(xml_node.get("name")) task = UserTask(parent_process=p, id=xml_node.get("id"), name=node_name) task = process_potential_loop(task, xml_node) p.add_task(task)
def process_node_sequence_flow(p: Process, xml_node) -> None: edge = Edge( id=xml_node.get("id"), source_id=xml_node.get("sourceRef"), target_id=xml_node.get("targetRef"), ) condition_node = find_node(xml_node, "conditionExpression") if condition_node is not None: edge.condition = textwrap.dedent(condition_node.text) p.add_edge(edge)
def read_process(parent_process: Optional[Process], process) -> Process: node_ns, node_name = parse_tag(process) if "process" == node_name: result = Process(id=process.get("id")) elif "subProcess" == node_name: assert parent_process result = SubProcess( parent_process=parent_process, id=process.get("id"), name=normalize_name(process.get("name")), ) else: raise Exception(f"Unknown process node: {process.tag}") # we read first the nodes, then the boundary events, # then only the edges so they are findable # when adding the edges by id. for node in list(process): process_node(result, node) for node in list(process): process_boundary_event(result, node) for node in list(process): process_edge(result, node) for node in list(process): process_lane_set(result, node) for task_id, task in result.tasks.items(): if not isinstance(task, ProcessTask): continue if result.has_incoming_edges(task): continue result.start_events[task.id] = task for task_id, task in result.tasks.items(): if not result.has_outgoing_edges(task): if not isinstance(task, EndEvent) and not isinstance( task, ProcessTask): raise Exception( f"Executable node {task} has no outgoing connections, but can't " f"be used as ae end task.") result.end_events[task.id] = task return result
def route_single_output(process: Process, gateway: Gateway, event: ActiveEvent) -> List[Edge]: default_edge = None result_edge = None edges = process.get_outgoing_edges(gateway.id) for edge in edges: if not edge.condition: if default_edge is not None: raise Exception( f"Duplicate default edge for gateway {gateway.id}.") default_edge = edge continue if eval_edge(edge.condition, event): if result_edge is not None: raise Exception( f"Duplicate output edge for gateway {gateway.id}") result_edge = edge continue if result_edge is None and default_edge is not None: result_edge = default_edge if not result_edge: raise Exception(f"No branch matches on gateway {gateway.id}") return [result_edge]
def __init__( self, parent_builder: Optional["ProcessBuilder"], _build: Optional[Callable] = None, name: Optional[str] = None, ): self.parent_builder = parent_builder if self.parent_builder is None: self.process = Process( id=next_id(), name="<process>" if name is None else name ) else: self.process = SubProcess( id=next_id(), name="<sub-process>" if name is None else name, parent_process=self.parent_builder.process, ) self.current_task: WiredNode = StartEvent( parent_process=self.process, id=next_id(), name="<start>" ) self.pre_current_when_task: WiredNode = self.current_task self.process.add_start_event(self.current_task) self.nested_branches: List[BranchGroup] = list() self._build = _build
def process_node_start_event(p: Process, xml_node) -> None: """ Create a start event from the process """ node_name = normalize_name(xml_node.get("name")) message_event_node = find_node(xml_node, "messageEventDefinition") if message_event_node is not None: message_event = MessageEvent(parent_process=p, id=xml_node.get("id"), name=node_name) p.add_message_event(message_event) return task = StartEvent(parent_process=p, id=xml_node.get("id"), name=node_name) p.add_start_event(task)
def process_script_task(p: Process, xml_node) -> None: """ Create a ScriptTask element from the process """ node_name = normalize_name(xml_node.get("name")) language = xml_node.get("scriptFormat") script_node = find_node(xml_node, "script") task = ScriptTask( parent_process=p, id=xml_node.get("id"), name=node_name, language=language, script=textwrap.dedent(script_node.text), ) task = process_potential_loop(task, xml_node) p.add_task(task)
def process_boundary_task(p: Process, boundary_event_node) -> None: """ Create a Task element from the process """ for node in list(boundary_event_node): node_ns, node_name = parse_tag(node) if node_name in boundary_ignored_elements: continue # node is not ignored, we either found the type # or we die with exception. task_name = normalize_name(boundary_event_node.get("name")) if node_name == "errorEventDefinition": boundary_task = ErrorBoundaryEvent( parent_process=p, id=boundary_event_node.get("id"), name=task_name) boundary_task.attached_task_id = boundary_event_node.get( "attachedToRef", default="not attached") boundary_task.cancel_activity = get_boolean( boundary_event_node, "cancelActivity", True) boundary_task.parallel_multiple = get_boolean( boundary_event_node, "parallelMultiple", True) p.add_boundary_event(boundary_task) return if node_name == "timerEventDefinition": read_timer_event_definition( process=p, boundary_event_node=boundary_event_node, timer_event_definition_node=node, task_name=task_name, ) return raise Exception( "Unable to find the type of the boundary event. Only " "<errorEventDefinition>, and <timerEventDefinition> are supported.")
def process_lane(process: Process, lane_node) -> None: """ Create a lane object """ lane_node_ns, lane_node_name = parse_tag(lane_node) lane = Lane(id=lane_node.get("id"), name=lane_node.get("name"), parent_process=process) process.add_lane(lane) for node in list(lane_node): node_ns, node_name = parse_tag(node) if node_name in boundary_ignored_elements: continue if node_name == "flowNodeRef": process_lane_task(process, lane, node) continue raise Exception( f"Unknown node <{node_name}> inside a <{lane_node_name}>.")
def route_all_outputs(process: Process, task: ProcessTask, event: ActiveEvent) -> List[Edge]: result_edges = [] edges = process.get_outgoing_edges(task.id) for edge in edges: # if we have no condition on the edge, we create an event for it if edge.condition and not eval_edge(edge.condition, event): continue result_edges.append(edge) return result_edges
def __init__(self, id: str) -> None: self.lane_definitions: List[ExecutionLane] = [] self.task_definitions: List[ExecutionTask] = [] self.user_task_definitions: List[ExecutionUserTask] = [] self.message_definitions: List[ExecutionMessageEvent] = [] self.message_callback_definitions: List[ ExecutionMessageCallbackEvent] = [] self.chained_task_definitions: List[Union[ExecutionTask, ExecutionUserTask]] = [] self.process: Process = Process(id=id) # map from lane key, to actual lane self.lanes: Dict[str, AdhesiveLane] = dict()
def process_node_sub_process(p: Process, xml_node) -> None: task = cast(SubProcess, read_process(p, xml_node)) task = process_potential_loop(task, xml_node) p.add_task(task)
def process_lane_task(process: Process, lane: Lane, xml_node) -> None: """ Binds the task for the lane. """ task_id = textwrap.dedent(xml_node.text) process.add_task_to_lane(lane, task_id)