feat(bpmn-rules): replace start events only allowed in event sub process
this includes the following event definitions: * error * escalation * compensate Closes #583
This commit is contained in:
parent
42a40494a7
commit
d5fa27ead2
|
@ -13,7 +13,10 @@ var getParents = require('../modeling/util/ModelingUtil').getParents,
|
||||||
getBusinessObject = require('../../util/ModelUtil').getBusinessObject,
|
getBusinessObject = require('../../util/ModelUtil').getBusinessObject,
|
||||||
isExpanded = require('../../util/DiUtil').isExpanded,
|
isExpanded = require('../../util/DiUtil').isExpanded,
|
||||||
isEventSubProcess = require('../../util/DiUtil').isEventSubProcess,
|
isEventSubProcess = require('../../util/DiUtil').isEventSubProcess,
|
||||||
isInterrupting = require('../../util/DiUtil').isInterrupting;
|
isInterrupting = require('../../util/DiUtil').isInterrupting,
|
||||||
|
hasErrorEventDefinition = require('../../util/DiUtil').hasErrorEventDefinition,
|
||||||
|
hasEscalationEventDefinition = require('../../util/DiUtil').hasEscalationEventDefinition,
|
||||||
|
hasCompensateEventDefinition = require('../../util/DiUtil').hasCompensateEventDefinition;
|
||||||
|
|
||||||
|
|
||||||
var RuleProvider = require('diagram-js/lib/features/rules/RuleProvider');
|
var RuleProvider = require('diagram-js/lib/features/rules/RuleProvider');
|
||||||
|
@ -564,20 +567,32 @@ function canReplace(elements, target, position) {
|
||||||
|
|
||||||
forEach(elements, function(element) {
|
forEach(elements, function(element) {
|
||||||
|
|
||||||
// replace a non-interrupting start event by a blank interrupting start event
|
|
||||||
// when the target is not an event sub process
|
|
||||||
if (!isEventSubProcess(target)) {
|
if (!isEventSubProcess(target)) {
|
||||||
|
|
||||||
if (is(element, 'bpmn:StartEvent') &&
|
if (is(element, 'bpmn:StartEvent') &&
|
||||||
!isInterrupting(element) &&
|
|
||||||
element.type !== 'label' &&
|
element.type !== 'label' &&
|
||||||
canDrop(element, target)) {
|
canDrop(element, target)) {
|
||||||
|
|
||||||
|
// replace a non-interrupting start event by a blank interrupting start event
|
||||||
|
// when the target is not an event sub process
|
||||||
|
if (!isInterrupting(element)) {
|
||||||
canExecute.replacements.push({
|
canExecute.replacements.push({
|
||||||
oldElementId: element.id,
|
oldElementId: element.id,
|
||||||
newElementType: 'bpmn:StartEvent'
|
newElementType: 'bpmn:StartEvent'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// replace an error/escalation/compansate start event by a blank interrupting start event
|
||||||
|
// when the target is not an event sub process
|
||||||
|
if (hasErrorEventDefinition(element) ||
|
||||||
|
hasEscalationEventDefinition(element) ||
|
||||||
|
hasCompensateEventDefinition(element)) {
|
||||||
|
canExecute.replacements.push({
|
||||||
|
oldElementId: element.id,
|
||||||
|
newElementType: 'bpmn:StartEvent'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is(target, 'bpmn:Transaction')) {
|
if (!is(target, 'bpmn:Transaction')) {
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
var is = require('./ModelUtil').is,
|
var is = require('./ModelUtil').is,
|
||||||
getBusinessObject = require('./ModelUtil').getBusinessObject;
|
getBusinessObject = require('./ModelUtil').getBusinessObject;
|
||||||
|
|
||||||
|
var forEach = require('lodash/collection/forEach');
|
||||||
|
|
||||||
module.exports.isExpanded = function(element) {
|
module.exports.isExpanded = function(element) {
|
||||||
|
|
||||||
if (is(element, 'bpmn:CallActivity')) {
|
if (is(element, 'bpmn:CallActivity')) {
|
||||||
|
@ -27,3 +29,32 @@ module.exports.isInterrupting = function(element) {
|
||||||
module.exports.isEventSubProcess = function(element) {
|
module.exports.isEventSubProcess = function(element) {
|
||||||
return element && !!getBusinessObject(element).triggeredByEvent;
|
return element && !!getBusinessObject(element).triggeredByEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function hasEventDefinition(element, eventType) {
|
||||||
|
var bo = getBusinessObject(element),
|
||||||
|
hasEventDefinition = false;
|
||||||
|
|
||||||
|
if (bo.eventDefinitions) {
|
||||||
|
forEach(bo.eventDefinitions, function(event) {
|
||||||
|
if (is(event, eventType)) {
|
||||||
|
hasEventDefinition = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasEventDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.hasEventDefinition = hasEventDefinition;
|
||||||
|
|
||||||
|
module.exports.hasErrorEventDefinition = function(element) {
|
||||||
|
return hasEventDefinition(element, 'bpmn:ErrorEventDefinition');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.hasEscalationEventDefinition = function(element) {
|
||||||
|
return hasEventDefinition(element, 'bpmn:EscalationEventDefinition');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.hasCompensateEventDefinition = function(element) {
|
||||||
|
return hasEventDefinition(element, 'bpmn:CompensateEventDefinition');
|
||||||
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
|
<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" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.2.2">
|
||||||
<bpmn:process id="Process_1" isExecutable="false">
|
<bpmn:process id="Process_1" isExecutable="false">
|
||||||
<bpmn:subProcess id="SubProcess_1" name="SubProcess_1">
|
<bpmn:subProcess id="SubProcess_1" name="SubProcess_1">
|
||||||
<bpmn:incoming>SequenceFlow_1</bpmn:incoming>
|
<bpmn:incoming>SequenceFlow_1</bpmn:incoming>
|
||||||
|
@ -31,6 +31,16 @@
|
||||||
</bpmn:task>
|
</bpmn:task>
|
||||||
<bpmn:sequenceFlow id="SequenceFlow_1" sourceRef="Task_3" targetRef="SubProcess_1" />
|
<bpmn:sequenceFlow id="SequenceFlow_1" sourceRef="Task_3" targetRef="SubProcess_1" />
|
||||||
<bpmn:sequenceFlow id="SequenceFlow_2" sourceRef="SubProcess_1" targetRef="Task_4" />
|
<bpmn:sequenceFlow id="SequenceFlow_2" sourceRef="SubProcess_1" targetRef="Task_4" />
|
||||||
|
<bpmn:subProcess id="SubProcess_3" name="SubProcess_3" triggeredByEvent="true">
|
||||||
|
<bpmn:startEvent id="StartEvent_3" name="StartEvent_3">
|
||||||
|
<bpmn:outgoing>SequenceFlow_094t9fa</bpmn:outgoing>
|
||||||
|
<bpmn:errorEventDefinition />
|
||||||
|
</bpmn:startEvent>
|
||||||
|
<bpmn:task id="Task_5">
|
||||||
|
<bpmn:incoming>SequenceFlow_094t9fa</bpmn:incoming>
|
||||||
|
</bpmn:task>
|
||||||
|
<bpmn:sequenceFlow id="SequenceFlow_094t9fa" sourceRef="StartEvent_3" targetRef="Task_5" />
|
||||||
|
</bpmn:subProcess>
|
||||||
</bpmn:process>
|
</bpmn:process>
|
||||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
|
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
|
||||||
|
@ -92,6 +102,25 @@
|
||||||
<dc:Bounds x="400" y="142" width="90" height="20" />
|
<dc:Bounds x="400" y="142" width="90" height="20" />
|
||||||
</bpmndi:BPMNLabel>
|
</bpmndi:BPMNLabel>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNShape id="SubProcess_09cm4qb_di" bpmnElement="SubProcess_3" isExpanded="true">
|
||||||
|
<dc:Bounds x="816" y="59" width="350" height="200" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="StartEvent_1v1eve6_di" bpmnElement="StartEvent_3">
|
||||||
|
<dc:Bounds x="858" y="134" width="36" height="36" />
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<dc:Bounds x="831" y="170" width="90" height="20" />
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Task_1j96pnq_di" bpmnElement="Task_5">
|
||||||
|
<dc:Bounds x="972" y="112" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNEdge id="SequenceFlow_094t9fa_di" bpmnElement="SequenceFlow_094t9fa">
|
||||||
|
<di:waypoint xsi:type="dc:Point" x="894" y="152" />
|
||||||
|
<di:waypoint xsi:type="dc:Point" x="972" y="152" />
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<dc:Bounds x="888" y="127" width="90" height="20" />
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
</bpmndi:BPMNPlane>
|
</bpmndi:BPMNPlane>
|
||||||
</bpmndi:BPMNDiagram>
|
</bpmndi:BPMNDiagram>
|
||||||
</bpmn:definitions>
|
</bpmn:definitions>
|
||||||
|
|
|
@ -12,7 +12,8 @@ var modelingModule = require('../../../../lib/features/modeling'),
|
||||||
var is = require('../../../../lib/util/ModelUtil').is,
|
var is = require('../../../../lib/util/ModelUtil').is,
|
||||||
isExpanded = require('../../../../lib/util/DiUtil').isExpanded,
|
isExpanded = require('../../../../lib/util/DiUtil').isExpanded,
|
||||||
isInterrupting = require('../../../../lib/util/DiUtil').isInterrupting,
|
isInterrupting = require('../../../../lib/util/DiUtil').isInterrupting,
|
||||||
isEventSubProcess = require('../../../../lib/util/DiUtil').isEventSubProcess;
|
isEventSubProcess = require('../../../../lib/util/DiUtil').isEventSubProcess,
|
||||||
|
hasErrorEventDefinition = require('../../../../lib/util/DiUtil').hasErrorEventDefinition;
|
||||||
|
|
||||||
|
|
||||||
describe('features/replace - bpmn replace', function() {
|
describe('features/replace - bpmn replace', function() {
|
||||||
|
@ -1030,6 +1031,115 @@ describe('features/replace - bpmn replace', function() {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
it('should replace error start event after moving it outside event sub process',
|
||||||
|
inject(function(elementRegistry, bpmnReplace, modeling) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var startEvent = elementRegistry.get('StartEvent_3'),
|
||||||
|
root = elementRegistry.get('Process_1');
|
||||||
|
|
||||||
|
// when
|
||||||
|
modeling.moveElements([startEvent], { x: 0, y: 200 }, root);
|
||||||
|
|
||||||
|
var startEventAfter = elementRegistry.filter(function(element) {
|
||||||
|
return is(element, 'bpmn:StartEvent') && element.parent === root;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(hasErrorEventDefinition(startEventAfter)).to.be.false;
|
||||||
|
expect(startEventAfter.parent).to.equal(root);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
it('should replace error start event after moving it to a regular sub process',
|
||||||
|
inject(function(bpmnReplace, elementRegistry, modeling) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var startEvent = elementRegistry.get('StartEvent_3'),
|
||||||
|
subProcess = elementRegistry.get('SubProcess_1');
|
||||||
|
|
||||||
|
// when
|
||||||
|
modeling.moveElements([startEvent], { x: 260, y: 60 }, subProcess);
|
||||||
|
|
||||||
|
var startEventAfter = elementRegistry.filter(function(element) {
|
||||||
|
return is(element, 'bpmn:StartEvent') && element.parent === subProcess;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(hasErrorEventDefinition(startEventAfter)).to.be.false;
|
||||||
|
expect(startEventAfter.parent).to.equal(subProcess);
|
||||||
|
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
it('should not replace error start event after moving it to another event sub process',
|
||||||
|
inject(function(bpmnReplace, elementRegistry, modeling) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var startEvent = elementRegistry.get('StartEvent_3'),
|
||||||
|
subProcess = elementRegistry.get('SubProcess_1');
|
||||||
|
|
||||||
|
var eventSubProcess = bpmnReplace.replaceElement(subProcess, {
|
||||||
|
type: 'bpmn:SubProcess',
|
||||||
|
triggeredByEvent: true,
|
||||||
|
isExpanded: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// when
|
||||||
|
modeling.moveElements([startEvent], { x: 260, y: 60 }, eventSubProcess);
|
||||||
|
|
||||||
|
var startEventAfter = elementRegistry.filter(function(element) {
|
||||||
|
return is(element, 'bpmn:StartEvent') && element.parent === eventSubProcess && element.type !== 'label';
|
||||||
|
})[1];
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(hasErrorEventDefinition(startEventAfter)).to.be.true;
|
||||||
|
expect(startEventAfter.parent).to.equal(eventSubProcess);
|
||||||
|
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
it('should replace error start event when replacing parent event sub process',
|
||||||
|
inject(function(elementRegistry, bpmnReplace) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var eventSubProcess = elementRegistry.get('SubProcess_3');
|
||||||
|
|
||||||
|
// when
|
||||||
|
var subProcess = bpmnReplace.replaceElement(eventSubProcess, { type: 'bpmn:SubProcess' });
|
||||||
|
|
||||||
|
// then
|
||||||
|
var replacedStartEvent = elementRegistry.filter(function(element) {
|
||||||
|
return (element.parent === subProcess && element.type !== 'label');
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
expect(hasErrorEventDefinition(replacedStartEvent)).to.be.false;
|
||||||
|
expect(replacedStartEvent.parent).to.equal(subProcess);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
it('should not replace error start event when moving parent event sub process',
|
||||||
|
inject(function(elementRegistry, bpmnReplace, modeling) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var eventSubProcess = elementRegistry.get('SubProcess_3'),
|
||||||
|
startEvent = elementRegistry.get('StartEvent_3');
|
||||||
|
|
||||||
|
// when
|
||||||
|
modeling.moveElements([eventSubProcess], { x: 20, y: 30 });
|
||||||
|
|
||||||
|
// start event after moving parent
|
||||||
|
var startEventAfter = elementRegistry.filter(function(element) {
|
||||||
|
return (element.parent === eventSubProcess && element.type !== 'label');
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(startEventAfter).to.equal(startEvent);
|
||||||
|
expect(startEventAfter.parent).to.eql(eventSubProcess);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue