Skip to content
This repository was archived by the owner on Aug 16, 2022. It is now read-only.

Commit 17987c3

Browse files
author
Felix Mueller
committed
Add conditional sequence flow rule
1 parent 118ce38 commit 17987c3

10 files changed

Lines changed: 300 additions & 5 deletions

index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ module.exports = {
77
'no-script-task': 'error',
88
'no-send-task': 'error',
99
'no-undefined-task': 'error',
10-
'no-type': 'error'
10+
'no-type': 'error',
11+
'conditional-sequence-flows': 'error'
1112
}
1213
},
1314
zeebe_1_1: {
1415
rules: {
1516
'no-manual-task': 'error',
1617
'no-undefined-task': 'error',
17-
'no-type': 'error'
18+
'no-type': 'error',
19+
'conditional-sequence-flows': 'error'
1820
}
1921
}
2022
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@camunda-cloud/bpmnlint-plugin-camunda-cloud",
3-
"version": "0.0.7",
3+
"version": "0.0.8",
44
"description": "The bpmnlint camunda-cloud plug-in",
55
"main": "index.js",
66
"scripts": {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* A rule that checks that sequence flows outgoing from a
3+
* conditional forking gateway or activity are
4+
* either default flows _or_ have a condition attached
5+
*/
6+
module.exports = function() {
7+
8+
function check(node, reporter) {
9+
10+
if (!isConditionalForking(node)) {
11+
return;
12+
}
13+
14+
const outgoing = node.outgoing || [];
15+
16+
outgoing.forEach((flow) => {
17+
const missingCondition = (
18+
!hasCondition(flow) &&
19+
!isDefaultFlow(node, flow)
20+
);
21+
22+
if (missingCondition) {
23+
reporter.report(flow.id, 'Property “Condition expression” is missing. Alternative: Configure this flow as the default flow. ');
24+
}
25+
});
26+
}
27+
28+
return {
29+
check
30+
};
31+
32+
};
33+
34+
35+
// helpers /////////////////////////////
36+
37+
function isConditionalForking(node) {
38+
39+
const defaultFlow = node['default'];
40+
const outgoing = node.outgoing && node.outgoing.length > 0;
41+
42+
return defaultFlow || outgoing;
43+
}
44+
45+
function hasCondition(flow) {
46+
return !!flow.conditionExpression;
47+
}
48+
49+
function isDefaultFlow(node, flow) {
50+
return node['default'] === flow;
51+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?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_0l7t44b" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.9.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="1.0.0">
3+
<bpmn:process id="Process_0jznnxv" isExecutable="true">
4+
<bpmn:exclusiveGateway id="ExclusiveGateway" default="SequenceFlow1">
5+
<bpmn:outgoing>SequenceFlow1</bpmn:outgoing>
6+
<bpmn:outgoing>SequenceFlow2</bpmn:outgoing>
7+
</bpmn:exclusiveGateway>
8+
<bpmn:endEvent id="Event_0ormpsf">
9+
<bpmn:incoming>SequenceFlow1</bpmn:incoming>
10+
</bpmn:endEvent>
11+
<bpmn:sequenceFlow id="SequenceFlow1" sourceRef="ExclusiveGateway" targetRef="Event_0ormpsf" />
12+
<bpmn:endEvent id="Event_0kdkxge">
13+
<bpmn:incoming>SequenceFlow2</bpmn:incoming>
14+
</bpmn:endEvent>
15+
<bpmn:sequenceFlow id="SequenceFlow2" sourceRef="ExclusiveGateway" targetRef="Event_0kdkxge" />
16+
</bpmn:process>
17+
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
18+
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0jznnxv">
19+
<bpmndi:BPMNEdge id="Flow_1o5j6d7_di" bpmnElement="SequenceFlow1">
20+
<di:waypoint x="205" y="150" />
21+
<di:waypoint x="262" y="150" />
22+
</bpmndi:BPMNEdge>
23+
<bpmndi:BPMNEdge id="Flow_0qmevme_di" bpmnElement="SequenceFlow2">
24+
<di:waypoint x="180" y="175" />
25+
<di:waypoint x="180" y="260" />
26+
<di:waypoint x="262" y="260" />
27+
</bpmndi:BPMNEdge>
28+
<bpmndi:BPMNShape id="Gateway_162bt72_di" bpmnElement="ExclusiveGateway" isMarkerVisible="true">
29+
<dc:Bounds x="155" y="125" width="50" height="50" />
30+
</bpmndi:BPMNShape>
31+
<bpmndi:BPMNShape id="Event_0ormpsf_di" bpmnElement="Event_0ormpsf">
32+
<dc:Bounds x="262" y="132" width="36" height="36" />
33+
</bpmndi:BPMNShape>
34+
<bpmndi:BPMNShape id="Event_0kdkxge_di" bpmnElement="Event_0kdkxge">
35+
<dc:Bounds x="262" y="242" width="36" height="36" />
36+
</bpmndi:BPMNShape>
37+
</bpmndi:BPMNPlane>
38+
</bpmndi:BPMNDiagram>
39+
</bpmn:definitions>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?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_0l7t44b" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.9.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="1.0.0">
3+
<bpmn:process id="Process_0jznnxv" isExecutable="true">
4+
<bpmn:exclusiveGateway id="ExclusiveGateway">
5+
<bpmn:outgoing>SequenceFlow1</bpmn:outgoing>
6+
<bpmn:outgoing>SequenceFlow2</bpmn:outgoing>
7+
</bpmn:exclusiveGateway>
8+
<bpmn:endEvent id="Event_0ormpsf">
9+
<bpmn:incoming>SequenceFlow1</bpmn:incoming>
10+
</bpmn:endEvent>
11+
<bpmn:sequenceFlow id="SequenceFlow1" sourceRef="ExclusiveGateway" targetRef="Event_0ormpsf" />
12+
<bpmn:endEvent id="Event_0kdkxge">
13+
<bpmn:incoming>SequenceFlow2</bpmn:incoming>
14+
</bpmn:endEvent>
15+
<bpmn:sequenceFlow id="SequenceFlow2" sourceRef="ExclusiveGateway" targetRef="Event_0kdkxge" />
16+
</bpmn:process>
17+
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
18+
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0jznnxv">
19+
<bpmndi:BPMNEdge id="Flow_1o5j6d7_di" bpmnElement="SequenceFlow1">
20+
<di:waypoint x="205" y="150" />
21+
<di:waypoint x="262" y="150" />
22+
</bpmndi:BPMNEdge>
23+
<bpmndi:BPMNEdge id="Flow_0qmevme_di" bpmnElement="SequenceFlow2">
24+
<di:waypoint x="180" y="175" />
25+
<di:waypoint x="180" y="260" />
26+
<di:waypoint x="262" y="260" />
27+
</bpmndi:BPMNEdge>
28+
<bpmndi:BPMNShape id="Gateway_162bt72_di" bpmnElement="ExclusiveGateway" isMarkerVisible="true">
29+
<dc:Bounds x="155" y="125" width="50" height="50" />
30+
</bpmndi:BPMNShape>
31+
<bpmndi:BPMNShape id="Event_0ormpsf_di" bpmnElement="Event_0ormpsf">
32+
<dc:Bounds x="262" y="132" width="36" height="36" />
33+
</bpmndi:BPMNShape>
34+
<bpmndi:BPMNShape id="Event_0kdkxge_di" bpmnElement="Event_0kdkxge">
35+
<dc:Bounds x="262" y="242" width="36" height="36" />
36+
</bpmndi:BPMNShape>
37+
</bpmndi:BPMNPlane>
38+
</bpmndi:BPMNDiagram>
39+
</bpmn:definitions>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0l7t44b" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.9.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="1.0.0">
3+
<bpmn:process id="Process_0jznnxv" isExecutable="true">
4+
<bpmn:exclusiveGateway id="ExclusiveGateway">
5+
<bpmn:outgoing>SequenceFlow1</bpmn:outgoing>
6+
<bpmn:outgoing>SequenceFlow2</bpmn:outgoing>
7+
</bpmn:exclusiveGateway>
8+
<bpmn:endEvent id="Event_0ormpsf">
9+
<bpmn:incoming>SequenceFlow1</bpmn:incoming>
10+
</bpmn:endEvent>
11+
<bpmn:sequenceFlow id="SequenceFlow1" sourceRef="ExclusiveGateway" targetRef="Event_0ormpsf" />
12+
<bpmn:endEvent id="Event_0kdkxge">
13+
<bpmn:incoming>SequenceFlow2</bpmn:incoming>
14+
</bpmn:endEvent>
15+
<bpmn:sequenceFlow id="SequenceFlow2" sourceRef="ExclusiveGateway" targetRef="Event_0kdkxge">
16+
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">true</bpmn:conditionExpression>
17+
</bpmn:sequenceFlow>
18+
</bpmn:process>
19+
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
20+
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0jznnxv">
21+
<bpmndi:BPMNEdge id="Flow_1o5j6d7_di" bpmnElement="SequenceFlow1">
22+
<di:waypoint x="205" y="150" />
23+
<di:waypoint x="262" y="150" />
24+
</bpmndi:BPMNEdge>
25+
<bpmndi:BPMNEdge id="Flow_0qmevme_di" bpmnElement="SequenceFlow2">
26+
<di:waypoint x="180" y="175" />
27+
<di:waypoint x="180" y="260" />
28+
<di:waypoint x="262" y="260" />
29+
</bpmndi:BPMNEdge>
30+
<bpmndi:BPMNShape id="Gateway_162bt72_di" bpmnElement="ExclusiveGateway" isMarkerVisible="true">
31+
<dc:Bounds x="155" y="125" width="50" height="50" />
32+
</bpmndi:BPMNShape>
33+
<bpmndi:BPMNShape id="Event_0ormpsf_di" bpmnElement="Event_0ormpsf">
34+
<dc:Bounds x="262" y="132" width="36" height="36" />
35+
</bpmndi:BPMNShape>
36+
<bpmndi:BPMNShape id="Event_0kdkxge_di" bpmnElement="Event_0kdkxge">
37+
<dc:Bounds x="262" y="242" width="36" height="36" />
38+
</bpmndi:BPMNShape>
39+
</bpmndi:BPMNPlane>
40+
</bpmndi:BPMNDiagram>
41+
</bpmn:definitions>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0l7t44b" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.9.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="1.0.0">
3+
<bpmn:process id="Process_0jznnxv" isExecutable="true">
4+
<bpmn:exclusiveGateway id="ExclusiveGateway" default="SequenceFlow1">
5+
<bpmn:outgoing>SequenceFlow1</bpmn:outgoing>
6+
<bpmn:outgoing>SequenceFlow2</bpmn:outgoing>
7+
</bpmn:exclusiveGateway>
8+
<bpmn:endEvent id="Event_0ormpsf">
9+
<bpmn:incoming>SequenceFlow1</bpmn:incoming>
10+
</bpmn:endEvent>
11+
<bpmn:sequenceFlow id="SequenceFlow1" sourceRef="ExclusiveGateway" targetRef="Event_0ormpsf" />
12+
<bpmn:endEvent id="Event_0kdkxge">
13+
<bpmn:incoming>SequenceFlow2</bpmn:incoming>
14+
</bpmn:endEvent>
15+
<bpmn:sequenceFlow id="SequenceFlow2" sourceRef="ExclusiveGateway" targetRef="Event_0kdkxge">
16+
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">true</bpmn:conditionExpression>
17+
</bpmn:sequenceFlow>
18+
</bpmn:process>
19+
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
20+
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0jznnxv">
21+
<bpmndi:BPMNEdge id="Flow_1o5j6d7_di" bpmnElement="SequenceFlow1">
22+
<di:waypoint x="205" y="150" />
23+
<di:waypoint x="262" y="150" />
24+
</bpmndi:BPMNEdge>
25+
<bpmndi:BPMNEdge id="Flow_0qmevme_di" bpmnElement="SequenceFlow2">
26+
<di:waypoint x="180" y="175" />
27+
<di:waypoint x="180" y="260" />
28+
<di:waypoint x="262" y="260" />
29+
</bpmndi:BPMNEdge>
30+
<bpmndi:BPMNShape id="Gateway_162bt72_di" bpmnElement="ExclusiveGateway" isMarkerVisible="true">
31+
<dc:Bounds x="155" y="125" width="50" height="50" />
32+
</bpmndi:BPMNShape>
33+
<bpmndi:BPMNShape id="Event_0ormpsf_di" bpmnElement="Event_0ormpsf">
34+
<dc:Bounds x="262" y="132" width="36" height="36" />
35+
</bpmndi:BPMNShape>
36+
<bpmndi:BPMNShape id="Event_0kdkxge_di" bpmnElement="Event_0kdkxge">
37+
<dc:Bounds x="262" y="242" width="36" height="36" />
38+
</bpmndi:BPMNShape>
39+
</bpmndi:BPMNPlane>
40+
</bpmndi:BPMNDiagram>
41+
</bpmn:definitions>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0l7t44b" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.9.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="1.0.0">
3+
<bpmn:process id="Process_0jznnxv" isExecutable="true">
4+
<bpmn:exclusiveGateway id="ExclusiveGateway">
5+
<bpmn:outgoing>SequenceFlow1</bpmn:outgoing>
6+
<bpmn:outgoing>SequenceFlow2</bpmn:outgoing>
7+
</bpmn:exclusiveGateway>
8+
<bpmn:endEvent id="Event_0ormpsf">
9+
<bpmn:incoming>SequenceFlow1</bpmn:incoming>
10+
</bpmn:endEvent>
11+
<bpmn:sequenceFlow id="SequenceFlow1" sourceRef="ExclusiveGateway" targetRef="Event_0ormpsf">
12+
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">abc</bpmn:conditionExpression>
13+
</bpmn:sequenceFlow>
14+
<bpmn:endEvent id="Event_0kdkxge">
15+
<bpmn:incoming>SequenceFlow2</bpmn:incoming>
16+
</bpmn:endEvent>
17+
<bpmn:sequenceFlow id="SequenceFlow2" sourceRef="ExclusiveGateway" targetRef="Event_0kdkxge">
18+
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">true</bpmn:conditionExpression>
19+
</bpmn:sequenceFlow>
20+
</bpmn:process>
21+
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
22+
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0jznnxv">
23+
<bpmndi:BPMNEdge id="Flow_1o5j6d7_di" bpmnElement="SequenceFlow1">
24+
<di:waypoint x="205" y="150" />
25+
<di:waypoint x="262" y="150" />
26+
</bpmndi:BPMNEdge>
27+
<bpmndi:BPMNEdge id="Flow_0qmevme_di" bpmnElement="SequenceFlow2">
28+
<di:waypoint x="180" y="175" />
29+
<di:waypoint x="180" y="260" />
30+
<di:waypoint x="262" y="260" />
31+
</bpmndi:BPMNEdge>
32+
<bpmndi:BPMNShape id="Gateway_162bt72_di" bpmnElement="ExclusiveGateway" isMarkerVisible="true">
33+
<dc:Bounds x="155" y="125" width="50" height="50" />
34+
</bpmndi:BPMNShape>
35+
<bpmndi:BPMNShape id="Event_0ormpsf_di" bpmnElement="Event_0ormpsf">
36+
<dc:Bounds x="262" y="132" width="36" height="36" />
37+
</bpmndi:BPMNShape>
38+
<bpmndi:BPMNShape id="Event_0kdkxge_di" bpmnElement="Event_0kdkxge">
39+
<dc:Bounds x="262" y="242" width="36" height="36" />
40+
</bpmndi:BPMNShape>
41+
</bpmndi:BPMNPlane>
42+
</bpmndi:BPMNDiagram>
43+
</bpmn:definitions>

test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const scriptTaskRule = require('./rules/no-script-task');
1010
const sendTaskRule = require('./rules/no-send-task');
1111
const undefinedTaskRule = require('./rules/no-undefined-task');
1212
const noTypeRule = require('./rules/no-type');
13+
const conditionalSequenceFlowsRule = require('./rules/conditional-sequence-flows.js');
1314

1415
RuleTester.verify('no-business-rule-task', businessRuleTaskRule, {
1516
valid: [
@@ -163,3 +164,41 @@ RuleTester.verify('no-type-tasks', noTypeRule, {
163164
}
164165
]
165166
});
167+
168+
RuleTester.verify('conditional-sequence-flows', conditionalSequenceFlowsRule, {
169+
valid: [
170+
{
171+
moddleElement: readModdle(__dirname + '/rules/conditional-sequence-flows/valid-default-condition.bpmn')
172+
},
173+
{
174+
moddleElement: readModdle(__dirname + '/rules/conditional-sequence-flows/valid-two.bpmn')
175+
}
176+
],
177+
invalid: [
178+
{
179+
moddleElement: readModdle(__dirname + '/rules/conditional-sequence-flows/no-conditions.bpmn'),
180+
report: [{
181+
id: 'SequenceFlow1',
182+
message: 'Property “Condition expression” is missing. Alternative: Configure this flow as the default flow. '
183+
},
184+
{
185+
id: 'SequenceFlow2',
186+
message: 'Property “Condition expression” is missing. Alternative: Configure this flow as the default flow. '
187+
}]
188+
},
189+
{
190+
moddleElement: readModdle(__dirname + '/rules/conditional-sequence-flows/one-condition.bpmn'),
191+
report: {
192+
id: 'SequenceFlow1',
193+
message: 'Property “Condition expression” is missing. Alternative: Configure this flow as the default flow. '
194+
}
195+
},
196+
{
197+
moddleElement: readModdle(__dirname + '/rules/conditional-sequence-flows/default-condition.bpmn'),
198+
report: {
199+
id: 'SequenceFlow2',
200+
message: 'Property “Condition expression” is missing. Alternative: Configure this flow as the default flow. '
201+
}
202+
}
203+
]
204+
});

0 commit comments

Comments
 (0)