-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Verifies correct usage of link events: * name must be specified * only a single pair of link {throw/catch} (no fork/join) * no linking across scopes Related to camunda/camunda-modeler#3532
- Loading branch information
Showing
8 changed files
with
438 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
const { | ||
groupBy | ||
} = require('min-dash'); | ||
|
||
const { | ||
is | ||
} = require('bpmnlint-utils'); | ||
|
||
|
||
/** | ||
* A rule that verifies that link events are properly used. | ||
* | ||
* This implies: | ||
* | ||
* * for every link throw there exists a link catch within | ||
* the same scope, and vice versa | ||
* * there exists only a single pair of [ throw, catch ] links | ||
* with a given name, per scope | ||
* * link events have a name | ||
* | ||
*/ | ||
module.exports = function() { | ||
|
||
function check(node, reporter) { | ||
|
||
if (!is(node, 'bpmn:FlowElementsContainer')) { | ||
return; | ||
} | ||
|
||
const links = (node.flowElements || []).filter(isLinkEvent); | ||
|
||
for (const link of links) { | ||
if (!link.name) { | ||
reporter.report(link.id, 'Link event is missing name'); | ||
} | ||
} | ||
|
||
const names = groupBy(links, (link) => link.name); | ||
|
||
for (const [ name, events ] of Object.entries(names)) { | ||
|
||
// ignore unnamed (validated earlier) | ||
if (!name) { | ||
continue; | ||
} | ||
|
||
// missing catch or throw event | ||
if (events.length === 1) { | ||
const event = events[0]; | ||
|
||
reporter.report(event.id, `Link ${isThrowEvent(event) ? 'catch' : 'throw' } event with name <${ name }> missing in scope`); | ||
} | ||
|
||
const throwEvents = events.filter(isThrowEvent); | ||
|
||
if (throwEvents.length > 1) { | ||
for (const event of throwEvents) { | ||
reporter.report(event.id, `Duplicate link throw event with name <${name}> in scope`); | ||
} | ||
} | ||
|
||
const catchEvents = events.filter(isCatchEvent); | ||
|
||
if (catchEvents.length > 1) { | ||
for (const event of catchEvents) { | ||
reporter.report(event.id, `Duplicate link catch event with name <${name}> in scope`); | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
return { | ||
check | ||
}; | ||
}; | ||
|
||
|
||
// helpers ///////////////// | ||
|
||
function isLinkEvent(node) { | ||
|
||
var eventDefinitions = node.eventDefinitions || []; | ||
|
||
if (!is(node, 'bpmn:Event')) { | ||
return false; | ||
} | ||
|
||
return eventDefinitions.some( | ||
definition => is(definition, 'bpmn:LinkEventDefinition') | ||
); | ||
} | ||
|
||
function isThrowEvent(node) { | ||
return is(node, 'bpmn:ThrowEvent'); | ||
} | ||
|
||
function isCatchEvent(node) { | ||
return is(node, 'bpmn:CatchEvent'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import RuleTester from '../../lib/testers/rule-tester.js'; | ||
|
||
import rule from '../../rules/link-event.js'; | ||
|
||
import { | ||
readModdle | ||
} from '../../lib/testers/helper.js'; | ||
|
||
import { stubCJS } from '../helper.mjs'; | ||
|
||
const { | ||
__dirname | ||
} = stubCJS(import.meta.url); | ||
|
||
|
||
RuleTester.verify('link-event', rule, { | ||
valid: [ | ||
{ | ||
moddleElement: readModdle(__dirname + '/link-event/valid.bpmn') | ||
}, | ||
{ | ||
moddleElement: readModdle(__dirname + '/link-event/valid-collaboration.bpmn') | ||
} | ||
], | ||
invalid: [ | ||
{ | ||
moddleElement: readModdle(__dirname + '/link-event/invalid.bpmn'), | ||
report: [ | ||
{ | ||
'id': 'THROW_NO_NAME', | ||
'message': 'Link event is missing name', | ||
'category': 'error' | ||
}, | ||
{ | ||
'id': 'CATCH_NO_NAME', | ||
'message': 'Link event is missing name', | ||
'category': 'error' | ||
}, | ||
{ | ||
'id': 'NO_CATCH', | ||
'message': 'Link catch event with name <NO_CATCH> missing in scope', | ||
'category': 'error' | ||
}, | ||
{ | ||
'id': 'NO_THROW', | ||
'message': 'Link throw event with name <NO_THROW> missing in scope', | ||
'category': 'error' | ||
}, | ||
{ | ||
'id': 'SCOPE_BOUNDARY_THROW', | ||
'message': 'Link catch event with name <SCOPE_BOUNDARY> missing in scope', | ||
'category': 'error' | ||
}, | ||
{ | ||
'id': 'DUPLICATE_NAME_THROW_1', | ||
'message': 'Duplicate link throw event with name <DUPLICATE_NAME> in scope', | ||
'category': 'error' | ||
}, | ||
{ | ||
'id': 'DUPLICATE_NAME_THROW_2', | ||
'message': 'Duplicate link throw event with name <DUPLICATE_NAME> in scope', | ||
'category': 'error' | ||
}, | ||
{ | ||
'id': 'DUPLICATE_NAME_CATCH_1', | ||
'message': 'Duplicate link catch event with name <DUPLICATE_NAME> in scope', | ||
'category': 'error' | ||
}, | ||
{ | ||
'id': 'DUPLICATE_NAME_CATCH_2', | ||
'message': 'Duplicate link catch event with name <DUPLICATE_NAME> in scope', | ||
'category': 'error' | ||
}, | ||
{ | ||
'id': 'SCOPE_BOUNDARY_CATCH', | ||
'message': 'Link throw event with name <SCOPE_BOUNDARY> missing in scope', | ||
'category': 'error' | ||
} | ||
] | ||
} | ||
] | ||
}); |
Oops, something went wrong.