Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/hotfixes' into ft-change-to-agpl
Browse files Browse the repository at this point in the history
  • Loading branch information
fit-alessandro-berti committed Nov 8, 2024
2 parents 4fdec2b + 2938b26 commit 070387d
Show file tree
Hide file tree
Showing 10 changed files with 428 additions and 137 deletions.
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
# Changelog of pm4py


## pm4py 2.7.12 (2024.03.XX)
## pm4py 2.7.12 (2024.03.21)

### Added
* 458ee9abf2fc155a7531be96992c9a0c27f8cb81
* maximum number of consecutive occurrences of the same activity in pm4py.get_variants
* b4c914722605b37f787e156f407ea9333a8dd959
* more general between and activity split filters

### Changed
* 100b95c22a47eace59fc631541b2c34c9179765d
09d4e7a07f92fddd90c1b1bbe572308380d7c8f3
* changed BPMN visualizer
* f7b44a41a79760e4f092be2bf98087ea48b63de4
* changed BPMN conversion
* db98b6fbf16847eceab4b53216cc1a1096936785
* improved BPMN support (collaboration, gateways, ...)

### Deprecated

Expand All @@ -14,6 +25,10 @@
* fixing random variables support
* bb759da149b434d0e279256c8c6d397b06079729
* fixing sampling
* a816fb5f000a907b603b44aba1470463109028f0
* bug fix OC-DFG visualization
* 419a95362472c0807b73f4eb3d601f70b3d7c986
* bug fix POWL visualizer

### Removed

Expand Down
2 changes: 1 addition & 1 deletion pm4py/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
'''

__name__ = 'pm4py'
VERSION = '2.7.11.15'
VERSION = '2.7.12'
__version__ = VERSION
__doc__ = 'Process mining for Python'
__author__ = 'Process Intelligence Solutions (Fraunhofer FIT)'
Expand Down
85 changes: 59 additions & 26 deletions pm4py/objects/bpmn/exporter/variants/etree.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,29 +78,37 @@ def get_xml_string(bpmn_graph, parameters=None):
all_processes = set()
process_planes = {}
process_process = {}
process_participants = {}
process_collaboration = None

for node in bpmn_graph.get_nodes():
all_processes.add(node.get_process())
for flow in bpmn_graph.get_flows():
all_processes.add(flow.get_process())

if len(all_processes) > 1:
# when several swimlanes exist, their elements should be annexed to the same BPMN plane
bpmn_plane_id = "id" + str(uuid.uuid4())
collaboration_nodes = [x for x in bpmn_graph.get_nodes() if isinstance(x, BPMN.Collaboration)]
if collaboration_nodes:
bpmn_plane_id = collaboration_nodes[0].get_id()

process_collaboration = ET.SubElement(definitions, "bpmn:collaboration", {"id": bpmn_plane_id})

for process in all_processes:
part_id = "id" + str(uuid.uuid4())
ET.SubElement(process_collaboration, "bpmn:participant", {"id": part_id, "name": process, "processRef": "id" + process })
process_participants[process] = part_id
participant_nodes = [x for x in bpmn_graph.get_nodes() if isinstance(x, BPMN.Participant)]
if participant_nodes:
for process in participant_nodes:
ET.SubElement(process_collaboration, "bpmn:participant", {"id": process.get_id(), "name": process.get_name(), "processRef": "id" + process.process_ref})
all_processes.add(process.process_ref)
else:
bpmn_plane_id = "id" + list(all_processes)[0]

for process in all_processes:
p = ET.SubElement(definitions, "bpmn:process",
{"id": "id" + process, "isClosed": "false", "isExecutable": "false",
"processType": "None"})
process_process[process] = p
if process != bpmn_plane_id:
p = ET.SubElement(definitions, "bpmn:process",
{"id": "id" + process, "isClosed": "false", "isExecutable": "false",
"processType": "None"})
process_process[process] = p
elif process_collaboration is not None:
process_process[process] = process_collaboration

diagram = ET.SubElement(definitions, "bpmndi:BPMNDiagram", {"id": "id" + str(uuid.uuid4()), "name": "diagram"})

Expand All @@ -113,12 +121,13 @@ def get_xml_string(bpmn_graph, parameters=None):
for node in bpmn_graph.get_nodes():
process = node.get_process()

node_shape = ET.SubElement(process_planes[process], "bpmndi:BPMNShape",
{"bpmnElement": node.get_id(), "id": node.get_id() + "_gui"})
node_shape_layout = ET.SubElement(node_shape, "omgdc:Bounds",
{"height": str(layout.get(node).get_height()), "width": str(layout.get(node).get_width()),
"x": str(layout.get(node).get_x()),
"y": str(layout.get(node).get_y())})
if process != bpmn_plane_id:
node_shape = ET.SubElement(process_planes[process], "bpmndi:BPMNShape",
{"bpmnElement": node.get_id(), "id": node.get_id() + "_gui"})
node_shape_layout = ET.SubElement(node_shape, "omgdc:Bounds",
{"height": str(layout.get(node).get_height()), "width": str(layout.get(node).get_width()),
"x": str(layout.get(node).get_x()),
"y": str(layout.get(node).get_y())})

for flow in bpmn_graph.get_flows():
process = flow.get_process()
Expand All @@ -132,7 +141,11 @@ def get_xml_string(bpmn_graph, parameters=None):
for node in bpmn_graph.get_nodes():
process = process_process[node.get_process()]

if isinstance(node, BPMN.StartEvent):
if isinstance(node, BPMN.TextAnnotation):
annotation = ET.SubElement(process, "bpmn:textAnnotation", {"id": node.get_id()})
text = ET.SubElement(annotation, "bpmn:text")
text.text = node.text
elif isinstance(node, BPMN.StartEvent):
isInterrupting = "true" if node.get_isInterrupting() else "false"
parallelMultiple = "true" if node.get_parallelMultiple() else "false"
task = ET.SubElement(process, "bpmn:startEvent",
Expand All @@ -142,28 +155,36 @@ def get_xml_string(bpmn_graph, parameters=None):
task = ET.SubElement(process, "bpmn:endEvent", {"id": node.get_id(), "name": node.get_name()})
elif isinstance(node, BPMN.IntermediateCatchEvent):
task = ET.SubElement(process, "bpmn:intermediateCatchEvent", {"id": node.get_id(), "name": node.get_name()})
messageEventDefinition = ET.SubElement(task, "bpmn:messageEventDefinition")
elif isinstance(node, BPMN.IntermediateThrowEvent):
task = ET.SubElement(process, "bpmn:intermediateThrowEvent", {"id": node.get_id(), "name": node.get_name()})
elif isinstance(node, BPMN.BoundaryEvent):
task = ET.SubElement(process, "bpmn:boundaryEvent", {"id": node.get_id(), "name": node.get_name()})
elif isinstance(node, BPMN.Task):
task = ET.SubElement(process, "bpmn:task", {"id": node.get_id(), "name": node.get_name()})
if isinstance(node, BPMN.UserTask):
task = ET.SubElement(process, "bpmn:userTask", {"id": node.get_id(), "name": node.get_name()})
elif isinstance(node, BPMN.SendTask):
task = ET.SubElement(process, "bpmn:sendTask", {"id": node.get_id(), "name": node.get_name()})
else:
task = ET.SubElement(process, "bpmn:task", {"id": node.get_id(), "name": node.get_name()})
elif isinstance(node, BPMN.SubProcess):
task = ET.SubElement(process, "bpmn:subProcess", {"id": node.get_id(), "name": node.get_name()})
elif isinstance(node, BPMN.ExclusiveGateway):
task = ET.SubElement(process, "bpmn:exclusiveGateway",
{"id": node.get_id(), "gatewayDirection": node.get_gateway_direction().value,
"name": ""})
"name": node.get_name()})
elif isinstance(node, BPMN.ParallelGateway):
task = ET.SubElement(process, "bpmn:parallelGateway",
{"id": node.get_id(), "gatewayDirection": node.get_gateway_direction().value,
"name": ""})
"name": node.get_name()})
elif isinstance(node, BPMN.InclusiveGateway):
task = ET.SubElement(process, "bpmn:inclusiveGateway",
{"id": node.get_id(), "gatewayDirection": node.get_gateway_direction().value,
"name": ""})
else:
raise Exception("Unexpected node type.")
"name": node.get_name()})
elif isinstance(node, BPMN.EventBasedGateway):
task = ET.SubElement(process, "bpmn:eventBasedGateway",
{"id": node.get_id(), "gatewayDirection": node.get_gateway_direction().value,
"name": node.get_name()})

if enable_incoming_outgoing_exporting:
for in_arc in node.get_in_arcs():
Expand All @@ -179,8 +200,20 @@ def get_xml_string(bpmn_graph, parameters=None):

source = flow.get_source()
target = flow.get_target()
flow_xml = ET.SubElement(process, "bpmn:sequenceFlow", {"id": "id" + str(flow.get_id()), "name": flow.get_name(),
"sourceRef": str(source.get_id()),
"targetRef": str(target.get_id())})

if isinstance(flow, BPMN.SequenceFlow):
flow_xml = ET.SubElement(process, "bpmn:sequenceFlow", {"id": "id" + str(flow.get_id()), "name": flow.get_name(),
"sourceRef": str(source.get_id()),
"targetRef": str(target.get_id())})
elif isinstance(flow, BPMN.MessageFlow):
flow_xml = ET.SubElement(process, "bpmn:messageFlow", {"id": "id" + str(flow.get_id()), "name": flow.get_name(),
"sourceRef": str(source.get_id()),
"targetRef": str(target.get_id())})


elif isinstance(flow, BPMN.Association):
flow_xml = ET.SubElement(process, "bpmn:association", {"id": "id" + str(flow.get_id()),
"sourceRef": str(source.get_id()),
"targetRef": str(target.get_id())})

return minidom.parseString(ET.tostring(definitions)).toprettyxml(encoding=encoding)
Loading

0 comments on commit 070387d

Please sign in to comment.