Skip to content

Commit 03c0501

Browse files
committed
fix: make link-event rule check only BPMN compliance
* Link name instead of element name is required and checked for duplicates. * Multiple link throw elements with the same link name are allowed. Related to camunda/camunda-modeler#4870
1 parent d0db896 commit 03c0501

10 files changed

+159
-110
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ All notable changes to [bpmnlint](https://github.com/bpmn-io/bpmnlint) are docum
66

77
___Note:__ Yet to be released changes appear here._
88

9+
## 11.4.1
10+
11+
* `FIX`: make `link-event` rule check only BPMN compliance
12+
913
## 11.4.0
1014

1115
* `FEAT`: rework message on elements that should not be used ([#173](https://github.com/bpmn-io/bpmnlint/pull/173))
-997 Bytes
Loading

docs/rules/examples/link-event-incorrect.bpmn

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1x7j8t1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.20.0-nightly.20240107" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.4.0">
2+
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1x7j8t1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.23.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.4.0">
33
<bpmn:process id="Process_0im3pgs" isExecutable="true">
44
<bpmn:intermediateThrowEvent id="Event_0fvzchs" name="JUMP">
55
<bpmn:incoming>Flow_0w6huzu</bpmn:incoming>
@@ -20,7 +20,7 @@
2020
</bpmn:intermediateThrowEvent>
2121
<bpmn:sequenceFlow id="Flow_1v2vhxj" sourceRef="Event_022ctsn" targetRef="Event_0q5xos0" />
2222
</bpmn:subProcess>
23-
<bpmn:intermediateCatchEvent id="Event_0rw1f16">
23+
<bpmn:intermediateCatchEvent id="Event_0rw1f16" name="&#60;no link name&#62;">
2424
<bpmn:outgoing>Flow_1m6xxsl</bpmn:outgoing>
2525
<bpmn:linkEventDefinition id="LinkEventDefinition_00e5m7a" name="" />
2626
</bpmn:intermediateCatchEvent>
@@ -40,12 +40,6 @@
4040
<bpmndi:BPMNShape id="Event_19sw7x6_di" bpmnElement="Event_19sw7x6">
4141
<dc:Bounds x="142" y="82" width="36" height="36" />
4242
</bpmndi:BPMNShape>
43-
<bpmndi:BPMNShape id="Event_17pzlw3_di" bpmnElement="Event_0rw1f16">
44-
<dc:Bounds x="442" y="82" width="36" height="36" />
45-
</bpmndi:BPMNShape>
46-
<bpmndi:BPMNShape id="Event_0rn7sje_di" bpmnElement="Event_0rn7sje">
47-
<dc:Bounds x="532" y="82" width="36" height="36" />
48-
</bpmndi:BPMNShape>
4943
<bpmndi:BPMNShape id="Activity_0jz3rxz_di" bpmnElement="Activity_0jz3rxz" isExpanded="true">
5044
<dc:Bounds x="200" y="190" width="278" height="150" />
5145
</bpmndi:BPMNShape>
@@ -65,6 +59,15 @@
6559
<di:waypoint x="298" y="260" />
6660
<di:waypoint x="372" y="260" />
6761
</bpmndi:BPMNEdge>
62+
<bpmndi:BPMNShape id="Event_17pzlw3_di" bpmnElement="Event_0rw1f16">
63+
<dc:Bounds x="442" y="82" width="36" height="36" />
64+
<bpmndi:BPMNLabel>
65+
<dc:Bounds x="417" y="125" width="86" height="14" />
66+
</bpmndi:BPMNLabel>
67+
</bpmndi:BPMNShape>
68+
<bpmndi:BPMNShape id="Event_0rn7sje_di" bpmnElement="Event_0rn7sje">
69+
<dc:Bounds x="532" y="82" width="36" height="36" />
70+
</bpmndi:BPMNShape>
6871
<bpmndi:BPMNEdge id="Flow_0w6huzu_di" bpmnElement="Flow_0w6huzu">
6972
<di:waypoint x="178" y="100" />
7073
<di:waypoint x="232" y="100" />
-1.13 KB
Loading

docs/rules/link-event.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A rule that checks that link events are used in accordance with the BPMN specification:
44

5-
* A link event must be named
5+
* A link event definition must be named
66
* For every link throw event there exists a matching catch event in the same scope
77

88

rules/link-event.js

+16-14
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ module.exports = function() {
3535
const links = (node.flowElements || []).filter(isLinkEvent);
3636

3737
for (const link of links) {
38-
if (!link.name) {
39-
reporter.report(link.id, 'Link event is missing name');
38+
if (!getLinkName(link)) {
39+
reporter.report(link.id, 'Link event is missing link name');
4040
}
4141
}
4242

43-
const names = groupBy(links, (link) => link.name);
43+
const names = groupBy(links, link => getLinkName(link));
4444

4545
for (const [ name, events ] of Object.entries(names)) {
4646

@@ -53,22 +53,20 @@ module.exports = function() {
5353
if (events.length === 1) {
5454
const event = events[0];
5555

56-
reporter.report(event.id, `Link ${isThrowEvent(event) ? 'catch' : 'throw' } event with name <${ name }> missing in scope`);
57-
}
58-
59-
const throwEvents = events.filter(isThrowEvent);
60-
61-
if (throwEvents.length > 1) {
62-
for (const event of throwEvents) {
63-
reporter.report(event.id, `Duplicate link throw event with name <${name}> in scope`);
64-
}
56+
reporter.report(event.id, `Link ${isThrowEvent(event) ? 'catch' : 'throw' } event with link name <${ name }> missing in scope`);
57+
continue;
6558
}
6659

6760
const catchEvents = events.filter(isCatchEvent);
68-
6961
if (catchEvents.length > 1) {
7062
for (const event of catchEvents) {
71-
reporter.report(event.id, `Duplicate link catch event with name <${name}> in scope`);
63+
reporter.report(event.id, `Duplicate link catch event with link name <${name}> in scope`);
64+
}
65+
} else if (catchEvents.length === 0) {
66+
67+
// all events in scope are throw events
68+
for (const event of events) {
69+
reporter.report(event.id, `Link catch event with link name <${ name }> missing in scope`);
7270
}
7371
}
7472
}
@@ -96,6 +94,10 @@ function isLinkEvent(node) {
9694
);
9795
}
9896

97+
function getLinkName(linkEvent) {
98+
return linkEvent.get('eventDefinitions').find(def => is(def, 'bpmn:LinkEventDefinition')).name;
99+
}
100+
99101
function isThrowEvent(node) {
100102
return is(node, 'bpmn:ThrowEvent');
101103
}

test/rules/link-event.mjs

+10-18
Original file line numberDiff line numberDiff line change
@@ -27,44 +27,36 @@ RuleTester.verify('link-event', rule, {
2727
moddleElement: readModdle(__dirname + '/link-event/invalid.bpmn'),
2828
report: [
2929
{
30-
'id': 'THROW_NO_NAME',
31-
'message': 'Link event is missing name'
30+
'id': 'CATCH_NO_NAME',
31+
'message': 'Link event is missing link name'
3232
},
3333
{
34-
'id': 'CATCH_NO_NAME',
35-
'message': 'Link event is missing name'
34+
'id': 'THROW_NO_NAME',
35+
'message': 'Link event is missing link name'
3636
},
3737
{
3838
'id': 'NO_CATCH',
39-
'message': 'Link catch event with name <NO_CATCH> missing in scope'
39+
'message': 'Link catch event with link name <NO_CATCH> missing in scope'
4040
},
4141
{
4242
'id': 'NO_THROW',
43-
'message': 'Link throw event with name <NO_THROW> missing in scope'
43+
'message': 'Link throw event with link name <NO_THROW> missing in scope'
4444
},
4545
{
4646
'id': 'SCOPE_BOUNDARY_THROW',
47-
'message': 'Link catch event with name <SCOPE_BOUNDARY> missing in scope'
48-
},
49-
{
50-
'id': 'DUPLICATE_NAME_THROW_1',
51-
'message': 'Duplicate link throw event with name <DUPLICATE_NAME> in scope'
52-
},
53-
{
54-
'id': 'DUPLICATE_NAME_THROW_2',
55-
'message': 'Duplicate link throw event with name <DUPLICATE_NAME> in scope'
47+
'message': 'Link catch event with link name <SCOPE_BOUNDARY> missing in scope'
5648
},
5749
{
5850
'id': 'DUPLICATE_NAME_CATCH_1',
59-
'message': 'Duplicate link catch event with name <DUPLICATE_NAME> in scope'
51+
'message': 'Duplicate link catch event with link name <DUPLICATE_LINK_NAME> in scope'
6052
},
6153
{
6254
'id': 'DUPLICATE_NAME_CATCH_2',
63-
'message': 'Duplicate link catch event with name <DUPLICATE_NAME> in scope'
55+
'message': 'Duplicate link catch event with link name <DUPLICATE_LINK_NAME> in scope'
6456
},
6557
{
6658
'id': 'SCOPE_BOUNDARY_CATCH',
67-
'message': 'Link throw event with name <SCOPE_BOUNDARY> missing in scope'
59+
'message': 'Link throw event with link name <SCOPE_BOUNDARY> missing in scope'
6860
}
6961
]
7062
}

test/rules/link-event/invalid.bpmn

+25-40
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,30 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1x7j8t1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.20.0-nightly.20240107" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.4.0">
2+
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1x7j8t1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.23.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.4.0">
33
<bpmn:process id="Process_0im3pgs" isExecutable="true">
44
<bpmn:intermediateThrowEvent id="NO_CATCH" name="NO_CATCH">
5-
<bpmn:linkEventDefinition id="LinkEventDefinition_0l1hwet" name="" />
5+
<bpmn:linkEventDefinition id="LinkEventDefinition_0l1hwet" name="NO_CATCH" />
66
</bpmn:intermediateThrowEvent>
77
<bpmn:intermediateCatchEvent id="NO_THROW" name="NO_THROW">
8-
<bpmn:linkEventDefinition id="LinkEventDefinition_08twe44" name="" />
8+
<bpmn:linkEventDefinition id="LinkEventDefinition_08twe44" name="NO_THROW" />
99
</bpmn:intermediateCatchEvent>
1010
<bpmn:subProcess id="Activity_1l5hieb">
1111
<bpmn:intermediateCatchEvent id="SCOPE_BOUNDARY_CATCH" name="SCOPE_BOUNDARY">
12-
<bpmn:linkEventDefinition id="LinkEventDefinition_0neehpv" name="" />
12+
<bpmn:linkEventDefinition id="LinkEventDefinition_0neehpv" name="SCOPE_BOUNDARY" />
1313
</bpmn:intermediateCatchEvent>
1414
</bpmn:subProcess>
1515
<bpmn:intermediateThrowEvent id="SCOPE_BOUNDARY_THROW" name="SCOPE_BOUNDARY">
16-
<bpmn:linkEventDefinition id="LinkEventDefinition_1h4v9pq" name="" />
16+
<bpmn:linkEventDefinition id="LinkEventDefinition_1h4v9pq" name="SCOPE_BOUNDARY" />
1717
</bpmn:intermediateThrowEvent>
18-
<bpmn:intermediateThrowEvent id="DUPLICATE_NAME_THROW_1" name="DUPLICATE_NAME">
19-
<bpmn:linkEventDefinition id="LinkEventDefinition_0yclygy" name="" />
20-
</bpmn:intermediateThrowEvent>
21-
<bpmn:intermediateThrowEvent id="DUPLICATE_NAME_THROW_2" name="DUPLICATE_NAME">
22-
<bpmn:linkEventDefinition id="LinkEventDefinition_0ftn1rm" name="" />
23-
</bpmn:intermediateThrowEvent>
24-
<bpmn:intermediateCatchEvent id="DUPLICATE_NAME_CATCH_1" name="DUPLICATE_NAME">
25-
<bpmn:linkEventDefinition id="LinkEventDefinition_1fy2jsp" name="" />
18+
<bpmn:intermediateCatchEvent id="DUPLICATE_NAME_CATCH_1" name="DUPLICATE_LINK_NAME">
19+
<bpmn:linkEventDefinition id="LinkEventDefinition_1fy2jsp" name="DUPLICATE_LINK_NAME" />
2620
</bpmn:intermediateCatchEvent>
2721
<bpmn:intermediateCatchEvent id="DUPLICATE_NAME_CATCH_2" name="DUPLICATE_NAME">
28-
<bpmn:linkEventDefinition id="LinkEventDefinition_0qdvq9n" name="" />
22+
<bpmn:linkEventDefinition id="LinkEventDefinition_0qdvq9n" name="DUPLICATE_LINK_NAME" />
2923
</bpmn:intermediateCatchEvent>
30-
<bpmn:intermediateCatchEvent id="THROW_NO_NAME">
24+
<bpmn:intermediateCatchEvent id="CATCH_NO_NAME" name="NO LINK NAME">
3125
<bpmn:linkEventDefinition id="LinkEventDefinition_0l8clut" name="" />
3226
</bpmn:intermediateCatchEvent>
33-
<bpmn:intermediateThrowEvent id="CATCH_NO_NAME">
27+
<bpmn:intermediateThrowEvent id="THROW_NO_NAME" name="NO LINK NAME">
3428
<bpmn:linkEventDefinition id="LinkEventDefinition_112gmrg" name="" />
3529
</bpmn:intermediateThrowEvent>
3630
</bpmn:process>
@@ -48,22 +42,25 @@
4842
<dc:Bounds x="309" y="125" width="65" height="14" />
4943
</bpmndi:BPMNLabel>
5044
</bpmndi:BPMNShape>
51-
<bpmndi:BPMNShape id="Event_0l0jzrg_di" bpmnElement="DUPLICATE_NAME_THROW_1">
52-
<dc:Bounds x="212" y="502" width="36" height="36" />
45+
<bpmndi:BPMNShape id="Activity_1l5hieb_di" bpmnElement="Activity_1l5hieb" isExpanded="true">
46+
<dc:Bounds x="165" y="210" width="350" height="200" />
47+
</bpmndi:BPMNShape>
48+
<bpmndi:BPMNShape id="Event_0mpcq3t_di" bpmnElement="SCOPE_BOUNDARY_CATCH">
49+
<dc:Bounds x="322" y="292" width="36" height="36" />
5350
<bpmndi:BPMNLabel>
54-
<dc:Bounds x="190" y="545" width="83" height="27" />
51+
<dc:Bounds x="298" y="335" width="85" height="27" />
5552
</bpmndi:BPMNLabel>
5653
</bpmndi:BPMNShape>
57-
<bpmndi:BPMNShape id="BPMNShape_1qknzzi" bpmnElement="DUPLICATE_NAME_THROW_2">
58-
<dc:Bounds x="212" y="612" width="36" height="36" />
54+
<bpmndi:BPMNShape id="BPMNShape_1thzuaq" bpmnElement="SCOPE_BOUNDARY_THROW">
55+
<dc:Bounds x="452" y="82" width="36" height="36" />
5956
<bpmndi:BPMNLabel>
60-
<dc:Bounds x="190" y="655" width="83" height="27" />
57+
<dc:Bounds x="429" y="125" width="85" height="27" />
6158
</bpmndi:BPMNLabel>
6259
</bpmndi:BPMNShape>
6360
<bpmndi:BPMNShape id="Event_0gvpdhn_di" bpmnElement="DUPLICATE_NAME_CATCH_1">
6461
<dc:Bounds x="422" y="502" width="36" height="36" />
6562
<bpmndi:BPMNLabel>
66-
<dc:Bounds x="400" y="545" width="83" height="27" />
63+
<dc:Bounds x="403" y="545" width="77" height="27" />
6764
</bpmndi:BPMNLabel>
6865
</bpmndi:BPMNShape>
6966
<bpmndi:BPMNShape id="Event_0qgwzkc_di" bpmnElement="DUPLICATE_NAME_CATCH_2">
@@ -72,28 +69,16 @@
7269
<dc:Bounds x="400" y="655" width="83" height="27" />
7370
</bpmndi:BPMNLabel>
7471
</bpmndi:BPMNShape>
75-
<bpmndi:BPMNShape id="BPMNShape_15n0rzr" bpmnElement="CATCH_NO_NAME">
76-
<dc:Bounds x="692" y="82" width="36" height="36" />
77-
<bpmndi:BPMNLabel>
78-
<dc:Bounds x="669" y="125" width="85" height="27" />
79-
</bpmndi:BPMNLabel>
80-
</bpmndi:BPMNShape>
81-
<bpmndi:BPMNShape id="Event_196apoc_di" bpmnElement="THROW_NO_NAME">
72+
<bpmndi:BPMNShape id="Event_196apoc_di" bpmnElement="CATCH_NO_NAME">
8273
<dc:Bounds x="582" y="82" width="36" height="36" />
83-
</bpmndi:BPMNShape>
84-
<bpmndi:BPMNShape id="Activity_1l5hieb_di" bpmnElement="Activity_1l5hieb" isExpanded="true">
85-
<dc:Bounds x="165" y="210" width="350" height="200" />
86-
</bpmndi:BPMNShape>
87-
<bpmndi:BPMNShape id="Event_0mpcq3t_di" bpmnElement="SCOPE_BOUNDARY_CATCH">
88-
<dc:Bounds x="322" y="292" width="36" height="36" />
8974
<bpmndi:BPMNLabel>
90-
<dc:Bounds x="298" y="335" width="85" height="27" />
75+
<dc:Bounds x="563" y="125" width="79" height="14" />
9176
</bpmndi:BPMNLabel>
9277
</bpmndi:BPMNShape>
93-
<bpmndi:BPMNShape id="BPMNShape_1thzuaq" bpmnElement="SCOPE_BOUNDARY_THROW">
94-
<dc:Bounds x="452" y="82" width="36" height="36" />
78+
<bpmndi:BPMNShape id="BPMNShape_15n0rzr" bpmnElement="THROW_NO_NAME">
79+
<dc:Bounds x="692" y="82" width="36" height="36" />
9580
<bpmndi:BPMNLabel>
96-
<dc:Bounds x="429" y="125" width="85" height="27" />
81+
<dc:Bounds x="671" y="125" width="79" height="14" />
9782
</bpmndi:BPMNLabel>
9883
</bpmndi:BPMNShape>
9984
</bpmndi:BPMNPlane>

0 commit comments

Comments
 (0)