feature(rules): add rule for link events

close #219
This commit is contained in:
jdotzki 2015-03-05 13:57:32 +01:00
parent 6f85d3081f
commit c5af54c1e3
3 changed files with 156 additions and 8 deletions

View File

@ -1,7 +1,8 @@
'use strict';
var groupBy = require('lodash/collection/groupBy'),
size = require('lodash/collection/size');
size = require('lodash/collection/size'),
forEach = require('lodash/collection/forEach');
var RuleProvider = require('diagram-js/lib/features/rules/RuleProvider');
@ -32,9 +33,11 @@ ModelingRules.prototype.init = function() {
var sourceBo = source.businessObject,
targetBo = target.businessObject;
// handle start and end event cases
var startEventCheck = targetBo.$instanceOf('bpmn:StartEvent') ||
sourceBo.$instanceOf('bpmn:EndEvent');
// handle event based gateway cases
var eventBasedGatewayCheck = false;
// Ensure target of event based gateway is one of:
@ -45,18 +48,38 @@ ModelingRules.prototype.init = function() {
if (targetBo.$instanceOf('bpmn:ReceiveTask')) {
eventBasedGatewayCheck = false;
} else if (targetBo.$instanceOf('bpmn:IntermediateCatchEvent') &&
targetBo.eventDefinitions && (
targetBo.eventDefinitions[0].$type === 'bpmn:MessageEventDefinition' ||
targetBo.eventDefinitions[0].$type === 'bpmn:TimerEventDefinition' ||
targetBo.eventDefinitions[0].$type === 'bpmn:ConditionalEventDefinition' ||
targetBo.eventDefinitions[0].$type === 'bpmn:SignalEventDefinition')) {
} else if (isEventType(targetBo, 'bpmn:IntermediateCatchEvent', 'bpmn:MessageEventDefinition') ||
isEventType(targetBo, 'bpmn:IntermediateCatchEvent', 'bpmn:TimerEventDefinition') ||
isEventType(targetBo, 'bpmn:IntermediateCatchEvent', 'bpmn:ConditionalEventDefinition') ||
isEventType(targetBo, 'bpmn:IntermediateCatchEvent', 'bpmn:SignalEventDefinition')) {
eventBasedGatewayCheck = false;
}
}
return startEventCheck || eventBasedGatewayCheck;
// handle link event
var linkEventCheck = false;
if (isEventType(targetBo, 'bpmn:IntermediateCatchEvent', 'bpmn:LinkEventDefinition') ||
isEventType(sourceBo, 'bpmn:IntermediateThrowEvent', 'bpmn:LinkEventDefinition')) {
linkEventCheck = true;
}
return startEventCheck || eventBasedGatewayCheck || linkEventCheck;
}
function isEventType(eventBo, type, definition) {
var isType = eventBo.$instanceOf(type);
var isDefinition = false;
var definitions = eventBo.eventDefinitions || [];
forEach(definitions, function(def) {
if (def.$type === definition) {
isDefinition = true;
}
});
return isType && isDefinition;
}

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:task id="Task_incoming" />
<bpmn:intermediateCatchEvent id="IntermediateCatchEvent" name="">
<bpmn:linkEventDefinition />
</bpmn:intermediateCatchEvent>
<bpmn:intermediateThrowEvent id="IntermediateThrowEvent" name="">
<bpmn:linkEventDefinition />
</bpmn:intermediateThrowEvent>
<bpmn:task id="Task_outgoing" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="Task_incoming_di" bpmnElement="Task_incoming">
<dc:Bounds x="224" y="176" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="IntermediateCatchEvent_di" bpmnElement="IntermediateCatchEvent">
<dc:Bounds x="512" y="128" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="485" y="164" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="IntermediateThrowEvent_di" bpmnElement="IntermediateThrowEvent">
<dc:Bounds x="512" y="247" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="485" y="283" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_outgoing_di" bpmnElement="Task_outgoing">
<dc:Bounds x="713" y="176" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -22,6 +22,7 @@ describe('features/ModelingRules', function() {
var sequenceXML = fs.readFileSync('test/fixtures/bpmn/sequence-flows.bpmn', 'utf8');
var eventGatewaysEdgeXML =
fs.readFileSync('test/fixtures/bpmn/features/rules/event-based-gateway-outgoing-edge.bpmn', 'utf8');
var linkEventXML = fs.readFileSync('test/fixtures/bpmn/features/rules/link-event.bpmn', 'utf8');
var testModules = [ coreModule, modelingModule, rulesModule ];
@ -188,4 +189,93 @@ describe('features/ModelingRules', function() {
}));
});
describe('catch link events', function() {
beforeEach(bootstrapModeler(linkEventXML, { modules: testModules }));
it('should not have incoming sequence flows ', inject(function(elementRegistry, modeling, rules) {
// given
var catchEvent = elementRegistry.get('IntermediateCatchEvent'),
incomingTask = elementRegistry.get('Task_incoming');
// when
var allowed = rules.allowed('connection.create', {
connection: null,
source: incomingTask,
target: catchEvent
});
// then
// connection should not be allowed
expect(allowed).toBe(false);
}));
it('should be allowed to have outgoing sequence flows ', inject(function(elementRegistry, modeling, rules) {
// given
var catchEvent = elementRegistry.get('IntermediateCatchEvent'),
outgoingTask = elementRegistry.get('Task_outgoing');
// when
var allowed = rules.allowed('connection.create', {
connection: null,
source: catchEvent,
target: outgoingTask
});
// then
// connection should not be allowed
expect(allowed).toBe(true);
}));
});
describe('throwing link events', function() {
beforeEach(bootstrapModeler(linkEventXML, { modules: testModules }));
it('should not have outgoing sequence flows ', inject(function(elementRegistry, modeling, rules) {
// given
var catchEvent = elementRegistry.get('IntermediateThrowEvent'),
outgoingTask = elementRegistry.get('Task_outgoing');
// when
var allowed = rules.allowed('connection.create', {
connection: null,
source: catchEvent,
target: outgoingTask
});
// then
// connection should not be allowed
expect(allowed).toBe(false);
}));
it('should be allowed to have incoming sequence flows ', inject(function(elementRegistry, modeling, rules) {
// given
var catchEvent = elementRegistry.get('IntermediateThrowEvent'),
incomingTask = elementRegistry.get('Task_incoming');
// when
var allowed = rules.allowed('connection.create', {
connection: null,
source: incomingTask,
target: catchEvent
});
// then
// connection should not be allowed
expect(allowed).toBe(true);
}));
});
});