bpmnlint 12.0.0 → 12.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/rules/fake-join.js +51 -2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bpmnlint",
3
3
  "description": "Validate your BPMN diagrams based on configurable lint rules",
4
- "version": "12.0.0",
4
+ "version": "12.1.0",
5
5
  "main": "lib/index.js",
6
6
  "exports": {
7
7
  ".": "./lib/index.js",
@@ -1,4 +1,9 @@
1
1
  const {
2
+ groupBy
3
+ } = require('min-dash');
4
+
5
+ const {
6
+ is,
2
7
  isAny
3
8
  } = require('bpmnlint-utils');
4
9
 
@@ -9,7 +14,9 @@ const {
9
14
 
10
15
  /**
11
16
  * A rule that checks that no fake join is modeled by attempting
12
- * to give a task or event join semantics.
17
+ * to give an element join semantics, i.e. a task or event with
18
+ * multiple incoming flows, or a link catch event targeted by
19
+ * multiple link throw events.
13
20
  *
14
21
  * Users should model a parallel joining gateway
15
22
  * to achieve the desired behavior.
@@ -20,6 +27,10 @@ module.exports = function() {
20
27
 
21
28
  function check(node, reporter) {
22
29
 
30
+ if (is(node, 'bpmn:FlowElementsContainer')) {
31
+ checkLinks(node, reporter);
32
+ }
33
+
23
34
  if (!isAny(node, [
24
35
  'bpmn:Activity',
25
36
  'bpmn:Event'
@@ -34,8 +45,46 @@ module.exports = function() {
34
45
  }
35
46
  }
36
47
 
48
+ function checkLinks(container, reporter) {
49
+
50
+ const links = (container.flowElements || []).filter(isLinkEvent);
51
+
52
+ // links are resolved by name, per scope
53
+ const names = groupBy(links.filter(getLinkName), getLinkName);
54
+
55
+ for (const [ name, events ] of Object.entries(names)) {
56
+ const throwEvents = events.filter(event => is(event, 'bpmn:ThrowEvent'));
57
+ const catchEvents = events.filter(event => is(event, 'bpmn:CatchEvent'));
58
+
59
+ // ignore ambiguous catch
60
+ if (throwEvents.length > 1 && catchEvents.length === 1) {
61
+ reporter.report(
62
+ catchEvents[0].id,
63
+ `Link throw events with link name <${ name }> do not join`
64
+ );
65
+ }
66
+ }
67
+ }
68
+
37
69
  return annotateRule('fake-join', {
38
70
  check
39
71
  });
40
72
 
41
- };
73
+ };
74
+
75
+
76
+ // helpers /////////////////
77
+
78
+ function isLinkEvent(node) {
79
+ return is(node, 'bpmn:Event') && !!getLinkDefinition(node);
80
+ }
81
+
82
+ function getLinkDefinition(linkEvent) {
83
+ return (linkEvent.eventDefinitions || []).find(
84
+ definition => is(definition, 'bpmn:LinkEventDefinition')
85
+ );
86
+ }
87
+
88
+ function getLinkName(linkEvent) {
89
+ return getLinkDefinition(linkEvent).name;
90
+ }