feat(bpmntreewalker): improve 'boundary event' handling

- correct z-index of boundary event close #75
- also render 'boundary events' that have no flowNodeRef close #66
This commit is contained in:
jdotzki 2014-07-15 12:43:30 +02:00
parent a5668bfac7
commit 551b445837
6 changed files with 309 additions and 39 deletions

View File

@ -118,8 +118,7 @@ function BpmnTreeWalker(handler) {
if (is(rootElement, 'bpmn:Process')) {
handleProcess(rootElement);
} else
if (is(rootElement, 'bpmn:Collaboration')) {
} else if (is(rootElement, 'bpmn:Collaboration')) {
handleCollaboration(rootElement);
// force drawing of everything not yet drawn that is part of the target DI
@ -129,17 +128,37 @@ function BpmnTreeWalker(handler) {
}
}
function handleProcess(process, context) {
handleFlowElementsContainer(process, context);
handleIoSpecification(process.ioSpecification, context);
handleArtifacts(process.artifacts, context);
// log process handled
handledProcesses.push(process);
}
function handleUnhandledProcesses(rootElements) {
// walk through all processes that have not yet been drawn and draw them
// (in case they contain lanes with DI information)
var processes = _.filter(rootElements, function(e) {
//Need this fix to get run test-case "01"
return e.$type === 'bpmn:Process' && e.laneSets && handledProcesses.indexOf(e) === -1;
});
processes.forEach(contextual(handleProcess));
}
function handleMessageFlow(messageFlow, context) {
visitIfDi(messageFlow, context);
}
function handleMessageFlows(messageFlows, context) {
if (messageFlows) {
_.forEach(messageFlows, contextual(handleMessageFlow, context));
}
}
function handleDataAssociation(association, context) {
visitIfDi(association, context);
}
@ -203,13 +222,20 @@ function BpmnTreeWalker(handler) {
visitIfDi(dataObject, context);
}
function handleBoundaryElement(dataObject, context) {
visitIfDi(dataObject, context);
}
function handleLane(lane, context) {
var newContext = visitIfDi(lane, context);
if (lane.childLaneSet) {
handleLaneSet(lane.childLaneSet, newContext || context);
} else {
handleFlowElements(lane.flowNodeRef, newContext || context);
var filterList = _.filter(lane.flowNodeRef, function(e) {
return e.$type !== 'bpmn:BoundaryEvent';
});
handleFlowElements(filterList, newContext || context);
}
}
@ -233,43 +259,45 @@ function BpmnTreeWalker(handler) {
function handleNonFlowNodes(flowElements, context) {
var sequenceFlows = [];
var boundaryEvents = [];
_.forEach(flowElements, function(e) {
if (is(e, 'bpmn:SequenceFlow')) {
sequenceFlows.push(e);
} else
if (is(e, 'bpmn:DataObject')) {
} else if (is(e, 'bpmn:DataObject')) {
// SKIP (assume correct referencing via DataObjectReference)
} else
if (is(e, 'bpmn:DataStoreReference')) {
} else if (is(e, 'bpmn:DataStoreReference')) {
handleDataElement(e, context);
} else
if (is(e, 'bpmn:DataObjectReference')) {
} else if (is(e, 'bpmn:DataObjectReference')) {
handleDataElement(e, context);
} else if (is(e, 'bpmn:BoundaryEvent')) {
boundaryEvents.push(e);
}
});
// handle boundary events
_.forEach(boundaryEvents, contextual(handleBoundaryElement, context));
// handle SequenceFlows
_.forEach(sequenceFlows, contextual(handleSequenceFlow, context));
}
function handleFlowElements(flowElements, context) {
var sequenceFlows = [];
var boundaryEvents = [];
_.forEach(flowElements, function(e) {
if (is(e, 'bpmn:SequenceFlow')) {
sequenceFlows.push(e);
} else
if (is(e, 'bpmn:FlowNode')) {
} else if (is(e, 'bpmn:BoundaryEvent')) {
boundaryEvents.push(e);
} else if (is(e, 'bpmn:FlowNode')) {
handleFlowNode(e, context);
} else
if (is(e, 'bpmn:DataObject')) {
} else if (is(e, 'bpmn:DataObject')) {
// SKIP (assume correct referencing via DataObjectReference)
} else
if (is(e, 'bpmn:DataStoreReference')) {
} else if (is(e, 'bpmn:DataStoreReference')) {
handleDataElement(e, context);
} else
if (is(e, 'bpmn:DataObjectReference')) {
} else if (is(e, 'bpmn:DataObjectReference')) {
handleDataElement(e, context);
} else {
logError(
@ -278,6 +306,9 @@ function BpmnTreeWalker(handler) {
}
});
// handle boundary events
_.forEach(boundaryEvents, contextual(handleBoundaryElement, context));
// handle SequenceFlows
_.forEach(sequenceFlows, contextual(handleSequenceFlow, context));
}
@ -291,26 +322,6 @@ function BpmnTreeWalker(handler) {
}
}
function handleProcess(process, context) {
handleFlowElementsContainer(process, context);
handleIoSpecification(process.ioSpecification, context);
handleArtifacts(process.artifacts, context);
// log process handled
handledProcesses.push(process);
}
function handleMessageFlow(messageFlow, context) {
visitIfDi(messageFlow, context);
}
function handleMessageFlows(messageFlows, context) {
if (messageFlows) {
_.forEach(messageFlows, contextual(handleMessageFlow, context));
}
}
function handleCollaboration(collaboration) {
_.forEach(collaboration.participants, contextual(handleParticipant));

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
expressionLanguage="http://www.w3.org/1999/XPath"
id="sid-3c77c04a-c5e4-4b00-ad92-873ca1d8f28f"
name="B.2.0"
targetNamespace="http://www.trisotech.com/definitions/_1373638079286"
typeLanguage="http://www.w3.org/2001/XMLSchema"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd">
<collaboration id="sid-4af1c293-f0f4-49e8-bb38-f0f65c8ac107">
<participant id="_55bb31e8-9e62-48ea-8f0e-1a748c04bbf6" name="Pool-Testcase" processRef="WFP-6-2">
</participant>
</collaboration>
<process id="WFP-6-2" isClosed="false" isExecutable="false" name="Pool-Testcase 2" processType="None">
<extensionElements/>
<laneSet id="sid-ec28d4f4-3755-4416-a5f9-8c2583ced576">
<lane id="_3400f56a-4565-47d1-91db-0ba17b958cb2" name="Lane - Testcase">
<flowNodeRef>_d58753a7-d38b-49cd-914d-14e4cdaa4449</flowNodeRef>
<flowNodeRef>End_Event</flowNodeRef>
<flowNodeRef>Boundary_Event</flowNodeRef>
</lane>
</laneSet>
<task completionQuantity="1" id="_d58753a7-d38b-49cd-914d-14e4cdaa4449" isForCompensation="false" name="A Task" startQuantity="1" />
<endEvent id="End_Event" name="The End">
<incoming>sid-4F795442-BADE-4AD2-AC9A-C51F90503931</incoming>
</endEvent>
<boundaryEvent attachedToRef="_d58753a7-d38b-49cd-914d-14e4cdaa4449" cancelActivity="true" id="Boundary_Event" parallelMultiple="false">
<outgoing>sid-4F795442-BADE-4AD2-AC9A-C51F90503931</outgoing>
<signalEventDefinition id="sid-a736556b-1648-4b13-9d51-d1b8b302715c"/>
</boundaryEvent>
<sequenceFlow id="sid-4F795442-BADE-4AD2-AC9A-C51F90503931" sourceRef="Boundary_Event" targetRef="End_Event" />
</process>
<bpmndi:BPMNDiagram id="sid-af59fa1e-e6f6-442f-8b8f-10d8b342a601" name="B.2.0">
<bpmndi:BPMNPlane bpmnElement="sid-4af1c293-f0f4-49e8-bb38-f0f65c8ac107" id="sid-c22f3e5f-ea4d-4216-81b3-f130d759d52a">
<bpmndi:BPMNShape bpmnElement="_55bb31e8-9e62-48ea-8f0e-1a748c04bbf6" id="_55bb31e8-9e62-48ea-8f0e-1a748c04bbf6_gui" isHorizontal="true">
<omgdc:Bounds height="307.0" width="480.0" x="60.0" y="30.0"/>
<bpmndi:BPMNLabel labelStyle="sid-77e078a7-1f31-4117-b678-7326d5e5a6a7">
<omgdc:Bounds height="84.0" width="12.000000000000014" x="65.0" y="141.5"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3400f56a-4565-47d1-91db-0ba17b958cb2" id="_3400f56a-4565-47d1-91db-0ba17b958cb2_gui" isHorizontal="true">
<omgdc:Bounds height="307.0" width="450.0" x="90.0" y="30.0"/>
<bpmndi:BPMNLabel labelStyle="sid-77e078a7-1f31-4117-b678-7326d5e5a6a7">
<omgdc:Bounds height="96.0" width="12.000000000000014" x="94.99999999999999" y="135.5"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_d58753a7-d38b-49cd-914d-14e4cdaa4449" id="_d58753a7-d38b-49cd-914d-14e4cdaa4449_gui">
<omgdc:Bounds height="68.0" width="83.0" x="195.0" y="105.0"/>
<bpmndi:BPMNLabel labelStyle="sid-77e078a7-1f31-4117-b678-7326d5e5a6a7">
<omgdc:Bounds height="12.0" width="41.142852783203125" x="215.92857360839844" y="131.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="End_Event" id="End_Event_gui">
<omgdc:Bounds height="28.0" width="28.0" x="382.0" y="218.0"/>
<bpmndi:BPMNLabel labelStyle="sid-5bb14c58-e378-46dc-9d3e-8b2b6e051656">
<omgdc:Bounds height="11.0" width="45.57143020629883" x="374.2142848968506" y="264.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="Boundary_Event" id="Boundary_Event_gui">
<omgdc:Bounds height="30.0" width="30.0" x="213.60714285714286" y="158.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-4F795442-BADE-4AD2-AC9A-C51F90503931" id="sid-4F795442-BADE-4AD2-AC9A-C51F90503931_gui">
<omgdi:waypoint x="228.58355308951846" y="188.0"/>
<omgdi:waypoint x="228.51435643782017" y="232.0"/>
<omgdi:waypoint x="382.0" y="232.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="sid-5bb14c58-e378-46dc-9d3e-8b2b6e051656">
<omgdc:Font isBold="false" isItalic="false" isStrikeThrough="false" isUnderline="false" name="Arial" size="11.0"/>
</bpmndi:BPMNLabelStyle>
<bpmndi:BPMNLabelStyle id="sid-77e078a7-1f31-4117-b678-7326d5e5a6a7">
<omgdc:Font isBold="false" isItalic="false" isStrikeThrough="false" isUnderline="false" name="Arial" size="12.0"/>
</bpmndi:BPMNLabelStyle>
</bpmndi:BPMNDiagram>
</definitions>

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
expressionLanguage="http://www.w3.org/1999/XPath"
id="sid-3c77c04a-c5e4-4b00-ad92-873ca1d8f28f"
name="B.2.0"
targetNamespace="http://www.trisotech.com/definitions/_1373638079286"
typeLanguage="http://www.w3.org/2001/XMLSchema"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd">
<collaboration id="sid-4af1c293-f0f4-49e8-bb38-f0f65c8ac107">
<participant id="_55bb31e8-9e62-48ea-8f0e-1a748c04bbf6" name="Pool-Testcase" processRef="WFP-6-2">
</participant>
</collaboration>
<process id="WFP-6-2" isClosed="false" isExecutable="false" name="Pool-Testcase 2" processType="None">
<extensionElements/>
<laneSet id="sid-ec28d4f4-3755-4416-a5f9-8c2583ced576">
<lane id="_3400f56a-4565-47d1-91db-0ba17b958cb2" name="Lane - Testcase">
<flowNodeRef>_d58753a7-d38b-49cd-914d-14e4cdaa4449</flowNodeRef>
<flowNodeRef>End_Event</flowNodeRef>
<!--<flowNodeRef>Boundary_Event</flowNodeRef>--> <!-- Reference is not mandatory -->
</lane>
</laneSet>
<task completionQuantity="1" id="_d58753a7-d38b-49cd-914d-14e4cdaa4449" isForCompensation="false" name="A Task" startQuantity="1" />
<endEvent id="End_Event" name="The End">
<incoming>sid-4F795442-BADE-4AD2-AC9A-C51F90503931</incoming>
</endEvent>
<boundaryEvent attachedToRef="_d58753a7-d38b-49cd-914d-14e4cdaa4449" cancelActivity="true" id="Boundary_Event" parallelMultiple="false">
<outgoing>sid-4F795442-BADE-4AD2-AC9A-C51F90503931</outgoing>
<signalEventDefinition id="sid-a736556b-1648-4b13-9d51-d1b8b302715c"/>
</boundaryEvent>
<sequenceFlow id="sid-4F795442-BADE-4AD2-AC9A-C51F90503931" sourceRef="Boundary_Event" targetRef="End_Event" />
</process>
<bpmndi:BPMNDiagram id="sid-af59fa1e-e6f6-442f-8b8f-10d8b342a601" name="B.2.0">
<bpmndi:BPMNPlane bpmnElement="sid-4af1c293-f0f4-49e8-bb38-f0f65c8ac107" id="sid-c22f3e5f-ea4d-4216-81b3-f130d759d52a">
<bpmndi:BPMNShape bpmnElement="_55bb31e8-9e62-48ea-8f0e-1a748c04bbf6" id="_55bb31e8-9e62-48ea-8f0e-1a748c04bbf6_gui" isHorizontal="true">
<omgdc:Bounds height="307.0" width="480.0" x="60.0" y="30.0"/>
<bpmndi:BPMNLabel labelStyle="sid-77e078a7-1f31-4117-b678-7326d5e5a6a7">
<omgdc:Bounds height="84.0" width="12.000000000000014" x="65.0" y="141.5"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3400f56a-4565-47d1-91db-0ba17b958cb2" id="_3400f56a-4565-47d1-91db-0ba17b958cb2_gui" isHorizontal="true">
<omgdc:Bounds height="307.0" width="450.0" x="90.0" y="30.0"/>
<bpmndi:BPMNLabel labelStyle="sid-77e078a7-1f31-4117-b678-7326d5e5a6a7">
<omgdc:Bounds height="96.0" width="12.000000000000014" x="94.99999999999999" y="135.5"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_d58753a7-d38b-49cd-914d-14e4cdaa4449" id="_d58753a7-d38b-49cd-914d-14e4cdaa4449_gui">
<omgdc:Bounds height="68.0" width="83.0" x="195.0" y="105.0"/>
<bpmndi:BPMNLabel labelStyle="sid-77e078a7-1f31-4117-b678-7326d5e5a6a7">
<omgdc:Bounds height="12.0" width="41.142852783203125" x="215.92857360839844" y="131.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="End_Event" id="End_Event_gui">
<omgdc:Bounds height="28.0" width="28.0" x="382.0" y="218.0"/>
<bpmndi:BPMNLabel labelStyle="sid-5bb14c58-e378-46dc-9d3e-8b2b6e051656">
<omgdc:Bounds height="11.0" width="45.57143020629883" x="374.2142848968506" y="264.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="Boundary_Event" id="Boundary_Event_gui">
<omgdc:Bounds height="30.0" width="30.0" x="213.60714285714286" y="158.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-4F795442-BADE-4AD2-AC9A-C51F90503931" id="sid-4F795442-BADE-4AD2-AC9A-C51F90503931_gui">
<omgdi:waypoint x="228.58355308951846" y="188.0"/>
<omgdi:waypoint x="228.51435643782017" y="232.0"/>
<omgdi:waypoint x="382.0" y="232.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="sid-5bb14c58-e378-46dc-9d3e-8b2b6e051656">
<omgdc:Font isBold="false" isItalic="false" isStrikeThrough="false" isUnderline="false" name="Arial" size="11.0"/>
</bpmndi:BPMNLabelStyle>
<bpmndi:BPMNLabelStyle id="sid-77e078a7-1f31-4117-b678-7326d5e5a6a7">
<omgdc:Font isBold="false" isItalic="false" isStrikeThrough="false" isUnderline="false" name="Arial" size="12.0"/>
</bpmndi:BPMNLabelStyle>
</bpmndi:BPMNDiagram>
</definitions>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmn2="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"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL
BPMN20.xsd">
<bpmn2:process id="Process_1" isExecutable="false">
<!-- Even if boundary Event is before Task element it should drawn with higher z index -->
<bpmn2:boundaryEvent id="BoundaryEvent_1" name="Event should be drawn above the Task" attachedToRef="Task_1">
<bpmn2:escalationEventDefinition id="_EscalationEventDefinition_1"/>
</bpmn2:boundaryEvent>
<bpmn2:task id="Task_1" name="Task">
<bpmn2:standardLoopCharacteristics/>
</bpmn2:task>
<!-- Normal order should work also -->
<bpmn2:task id="Task_2" name="Task">
<bpmn2:standardLoopCharacteristics/>
</bpmn2:task>
<bpmn2:boundaryEvent id="BoundaryEvent_2" name="Event should be drawn above the Task" attachedToRef="Task_2">
<bpmn2:escalationEventDefinition id="_EscalationEventDefinition_2"/>
</bpmn2:boundaryEvent>
<!-- Another one -->
<bpmn2:boundaryEvent attachedToRef="Task_3" name="Event should be drawn above the Task" cancelActivity="false"
id="BoundaryEvent_3" parallelMultiple="false">
<bpmn2:signalEventDefinition id="5555"/>
</bpmn2:boundaryEvent>
<bpmn2:task completionQuantity="1" id="Task_3" isForCompensation="false" startQuantity="1">
</bpmn2:task>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_Task_30" bpmnElement="Task_1">
<dc:Bounds height="80.0" width="100.0" x="138.0" y="48.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_BoundaryEvent_1" bpmnElement="BoundaryEvent_1">
<dc:Bounds height="36.0" width="36.0" x="142.0" y="110.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="22.0" width="84.0" x="172.0" y="145.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_31" bpmnElement="Task_2">
<dc:Bounds height="80.0" width="100.0" x="138.0" y="248.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_BoundaryEvent_2" bpmnElement="BoundaryEvent_2">
<dc:Bounds height="36.0" width="36.0" x="142.0" y="310.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="22.0" width="84.0" x="172.0" y="345.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_32" bpmnElement="Task_3">
<dc:Bounds height="80.0" width="100.0" x="138.0" y="448.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_BoundaryEvent_3" bpmnElement="BoundaryEvent_3">
<dc:Bounds height="36.0" width="36.0" x="142.0" y="510.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="22.0" width="84.0" x="172.0" y="545.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View File

@ -22,7 +22,6 @@
<bpmn2:lane id="nested-lane-1-2" name="A">
<bpmn2:flowNodeRef>call-activity</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>user-task</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>boundary-event</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:childLaneSet>
</bpmn2:lane>

View File

@ -132,4 +132,19 @@ describe('draw - bpmn renderer', function() {
bootstrapBpmnJS(xml)(done);
});
it('should render boundary events with correct z-index', function(done) {
var xml = fs.readFileSync(__dirname + '/../../../fixtures/bpmn/draw/boundary-event-z-index.bpmn', 'utf8');
bootstrapBpmnJS(xml)(done);
});
it('should render boundary events without flowNodeRef', function(done) {
var xml = fs.readFileSync(__dirname + '/../../../fixtures/bpmn/draw/boundary-event-without-refnode.bpmn', 'utf8');
bootstrapBpmnJS(xml)(done);
});
it('should render boundary event only once if referenced incorrectly via flowNodeRef (robustness)', function(done) {
var xml = fs.readFileSync(__dirname + '/../../../fixtures/bpmn/draw/boundary-event-with-refnode.bpmn', 'utf8');
bootstrapBpmnJS(xml)(done);
});
});