def apply(tree, parameters=None): """ Converts the process tree into a BPMN diagram Parameters -------------- tree Process tree parameters Parameters of the algorithm Returns -------------- bpmn_graph BPMN diagram """ from pm4py.objects.bpmn.obj import BPMN counts = Counts() bpmn = BPMN() start_event = BPMN.StartEvent(name="start", isInterrupting=True) end_event = BPMN.EndEvent(name="end") bpmn.add_node(start_event) bpmn.add_node(end_event) bpmn, counts, _, _ = recursively_add_tree(tree, tree, bpmn, start_event, end_event, counts, 0) bpmn = delete_tau_transitions(bpmn, counts) return bpmn
def parse_element(bpmn_graph, counts, curr_el, parents, incoming_dict, outgoing_dict, nodes_dict, nodes_bounds, flow_info, process=None, node=None, bpmn_element=None, flow=None, rec_depth=0): """ Parses a BPMN element from the XML file """ tag = curr_el.tag.lower() if tag.endswith("process"): process = curr_el.get("id") elif tag.endswith("shape"): bpmn_element = curr_el.get("bpmnElement") elif tag.endswith("task"): id = curr_el.get("id") name = curr_el.get("name").replace("\r", "").replace("\n", "") this_type = str(curr_el.tag) this_type = this_type[this_type.index("}") + 1:] task = BPMN.Task(name=name, type=this_type) bpmn_graph.add_node(task) node = task nodes_dict[id] = node elif tag.endswith("startevent"): id = curr_el.get("id") name = curr_el.get("name").replace("\r", " ").replace("\n", " ") if "name" in curr_el else str(uuid.uuid4()) start_event = BPMN.StartEvent(name=name) bpmn_graph.add_node(start_event) node = start_event nodes_dict[id] = node elif tag.endswith("endevent"): id = curr_el.get("id") name = curr_el.get("name").replace("\r", " ").replace("\n", " ") if "name" in curr_el else str(uuid.uuid4()) end_event = BPMN.EndEvent(name=name) bpmn_graph.add_node(end_event) node = end_event nodes_dict[id] = node elif tag.endswith("event"): id = curr_el.get("id") name = curr_el.get("name").replace("\r", " ").replace("\n", " ") if "name" in curr_el else str(uuid.uuid4()) this_type = str(curr_el.tag) this_type = this_type[this_type.index("}") + 1:] other_event = BPMN.OtherEvent(name=name, type=this_type) bpmn_graph.add_node(other_event) node = other_event nodes_dict[id] = node elif tag.endswith("edge"): bpmnElement = curr_el.get("bpmnElement") flow = bpmnElement elif tag.endswith("exclusivegateway"): id = curr_el.get("id") name = curr_el.get("name").replace("\r", "").replace("\n", "") if "name" in curr_el else str(uuid.uuid4()) exclusive_gateway = BPMN.ExclusiveGateway(name=name) bpmn_graph.add_node(exclusive_gateway) node = exclusive_gateway nodes_dict[id] = node elif tag.endswith("parallelgateway"): id = curr_el.get("id") name = curr_el.get("name").replace("\r", "").replace("\n", "") if "name" in curr_el else str(uuid.uuid4()) parallel_gateway = BPMN.ParallelGateway(name=name) bpmn_graph.add_node(parallel_gateway) node = parallel_gateway nodes_dict[id] = node elif tag.endswith("inclusivegateway"): id = curr_el.get("id") name = curr_el.get("name").replace("\r", "").replace("\n", "") if "name" in curr_el else str(uuid.uuid4()) inclusive_gateway = BPMN.InclusiveGateway(name=name) bpmn_graph.add_node(inclusive_gateway) node = inclusive_gateway nodes_dict[id] = node elif tag.endswith("incoming"): if node is not None: incoming_dict[curr_el.text.strip()] = node elif tag.endswith("outgoing"): if node is not None: outgoing_dict[curr_el.text.strip()] = node elif tag.endswith("sequenceflow"): seq_flow_id = curr_el.get("id") source_ref = curr_el.get("sourceRef") target_ref = curr_el.get("targetRef") # fix 28/04/2021: do not assume anymore to read the nodes before the edges incoming_dict[seq_flow_id] = target_ref outgoing_dict[seq_flow_id] = source_ref elif tag.endswith("waypoint"): if flow is not None: x = float(curr_el.get("x")) y = float(curr_el.get("y")) if not flow in flow_info: flow_info[flow] = [] flow_info[flow].append((x, y)) elif tag.endswith("label"): bpmn_element = None elif tag.endswith("bounds"): if bpmn_element is not None: x = float(curr_el.get("x")) y = float(curr_el.get("y")) width = float(curr_el.get("width")) height = float(curr_el.get("height")) nodes_bounds[bpmn_element] = {"x": x, "y": y, "width": width, "height": height} for child in curr_el: bpmn_graph = parse_element(bpmn_graph, counts, child, list(parents) + [child], incoming_dict, outgoing_dict, nodes_dict, nodes_bounds, flow_info, process=process, node=node, bpmn_element=bpmn_element, flow=flow, rec_depth=rec_depth + 1) if rec_depth == 0: for seq_flow_id in incoming_dict: if incoming_dict[seq_flow_id] in nodes_dict: incoming_dict[seq_flow_id] = nodes_dict[incoming_dict[seq_flow_id]] for seq_flow_id in outgoing_dict: if outgoing_dict[seq_flow_id] in nodes_dict: outgoing_dict[seq_flow_id] = nodes_dict[outgoing_dict[seq_flow_id]] for flow_id in flow_info: if flow_id in outgoing_dict and flow_id in incoming_dict: flow = BPMN.Flow(outgoing_dict[flow_id], incoming_dict[flow_id]) bpmn_graph.add_flow(flow) flow.del_waypoints() for waypoint in flow_info[flow_id]: flow.add_waypoint(waypoint) for node_id in nodes_bounds: if node_id in nodes_dict: bounds = nodes_bounds[node_id] node = nodes_dict[node_id] node.set_x(bounds["x"]) node.set_y(bounds["y"]) node.set_width(bounds["width"]) node.set_height(bounds["height"]) return bpmn_graph
def apply(net, im, fm, parameters=None): """ Converts an accepting Petri net into a BPMN diagram Parameters -------------- accepting_petri_net Accepting Petri net (list containing net + im + fm) parameters Parameters of the algorithm Returns -------------- bpmn_graph BPMN diagram """ if parameters is None: parameters = {} from pm4py.objects.bpmn.obj import BPMN from pm4py.objects.bpmn.util import reduction bpmn_graph = BPMN() entering_dictio = {} exiting_dictio = {} for place in net.places: node = BPMN.ExclusiveGateway() bpmn_graph.add_node(node) entering_dictio[place] = node exiting_dictio[place] = node for trans in net.transitions: if trans.label is None: if len(trans.in_arcs) > 1 or len(trans.out_arcs) > 1: node = BPMN.ParallelGateway() else: node = BPMN.ExclusiveGateway() bpmn_graph.add_node(node) entering_dictio[trans] = node exiting_dictio[trans] = node else: if len(trans.in_arcs) > 1: entering_node = BPMN.ParallelGateway() else: entering_node = BPMN.ExclusiveGateway() if len(trans.out_arcs) > 1: exiting_node = BPMN.ParallelGateway() else: exiting_node = BPMN.ExclusiveGateway() task = BPMN.Task(name=trans.label) bpmn_graph.add_node(task) bpmn_graph.add_flow(BPMN.Flow(entering_node, task)) bpmn_graph.add_flow(BPMN.Flow(task, exiting_node)) entering_dictio[trans] = entering_node exiting_dictio[trans] = exiting_node for arc in net.arcs: bpmn_graph.add_flow( BPMN.Flow(exiting_dictio[arc.source], entering_dictio[arc.target])) start_node = BPMN.StartEvent() end_node = BPMN.EndEvent() bpmn_graph.add_node(start_node) bpmn_graph.add_node(end_node) for place in im: bpmn_graph.add_flow(BPMN.Flow(start_node, entering_dictio[place])) for place in fm: bpmn_graph.add_flow(BPMN.Flow(exiting_dictio[place], end_node)) bpmn_graph = reduction.apply(bpmn_graph) return bpmn_graph