fix(import): handle invisible root elements
This commit ensures we pipe invisible root elements (Process, Collaboration) through our import infrastructure, too. This way we we receive proper events for them. Related to #6
This commit is contained in:
parent
921de712d2
commit
ae60914146
|
@ -137,8 +137,20 @@ BpmnImporter.prototype.add = function(semantic, di, parent) {
|
||||||
data.label = label;
|
data.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle the special case that we deal with a
|
||||||
|
// invisible root element (process or collaboration)
|
||||||
|
if (di.$instanceOf('bpmndi:BPMNPlane')) {
|
||||||
|
|
||||||
|
// we still fire the added event, making sure our
|
||||||
|
// infrastructure pics it up properly
|
||||||
|
fire('add', null);
|
||||||
|
fire('added', null);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (di.$instanceOf('bpmndi:BPMNShape')) {
|
||||||
|
|
||||||
if (di.$type === 'bpmndi:BPMNShape') {
|
|
||||||
var bounds = di.bounds;
|
var bounds = di.bounds;
|
||||||
|
|
||||||
var collapsed = isCollapsed(semantic, di);
|
var collapsed = isCollapsed(semantic, di);
|
||||||
|
|
|
@ -20,6 +20,9 @@ function BpmnRegistry(events, elementRegistry) {
|
||||||
diagramElement: {}
|
diagramElement: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// we attach to element.add rather than element.added to ensure
|
||||||
|
// the meta-data (semantic, di) for the element is already present
|
||||||
|
// during rendering
|
||||||
events.on('bpmn.element.add', function(e) {
|
events.on('bpmn.element.add', function(e) {
|
||||||
var semantic = e.semantic,
|
var semantic = e.semantic,
|
||||||
id = semantic.id;
|
id = semantic.id;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
bpmnRegistry: [ 'type', require('./BpmnRegistry') ]
|
__init__: [ 'bpmnRegistry' ],
|
||||||
|
bpmnRegistry: [ 'type', require('./BpmnRegistry') ],
|
||||||
|
bpmnImporter: [ 'type', require('./BpmnImporter') ]
|
||||||
};
|
};
|
|
@ -38,6 +38,10 @@ function BpmnTreeWalker(handler) {
|
||||||
return gfx;
|
return gfx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function visitRoot(element, diagram) {
|
||||||
|
return handler.root(element, diagram);
|
||||||
|
}
|
||||||
|
|
||||||
function visitIfDi(element, ctx) {
|
function visitIfDi(element, ctx) {
|
||||||
var di = getDi(element);
|
var di = getDi(element);
|
||||||
|
|
||||||
|
@ -96,11 +100,9 @@ function BpmnTreeWalker(handler) {
|
||||||
throw new Error('diagram not part of bpmn:Definitions');
|
throw new Error('diagram not part of bpmn:Definitions');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!diagram) {
|
if (!diagram && diagrams && diagrams.length) {
|
||||||
if (diagrams && diagrams.length) {
|
|
||||||
diagram = diagrams[0];
|
diagram = diagrams[0];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// no diagram -> nothing to import
|
// no diagram -> nothing to import
|
||||||
if (!diagram) {
|
if (!diagram) {
|
||||||
|
@ -110,19 +112,23 @@ function BpmnTreeWalker(handler) {
|
||||||
// load DI from selected diagram only
|
// load DI from selected diagram only
|
||||||
handleDiagram(diagram);
|
handleDiagram(diagram);
|
||||||
|
|
||||||
var rootElement = diagram.plane.bpmnElement;
|
var plane = diagram.plane,
|
||||||
|
rootElement = plane.bpmnElement;
|
||||||
|
|
||||||
if (!rootElement) {
|
if (!rootElement) {
|
||||||
throw new Error('no rootElement referenced in BPMNPlane <' + diagram.plane.id + '>');
|
throw new Error('no rootElement referenced in BPMNPlane <' + diagram.plane.id + '>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var ctx = visitRoot(rootElement, plane);
|
||||||
|
|
||||||
if (is(rootElement, 'bpmn:Process')) {
|
if (is(rootElement, 'bpmn:Process')) {
|
||||||
handleProcess(rootElement);
|
handleProcess(rootElement, ctx);
|
||||||
} else if (is(rootElement, 'bpmn:Collaboration')) {
|
} else if (is(rootElement, 'bpmn:Collaboration')) {
|
||||||
handleCollaboration(rootElement);
|
handleCollaboration(rootElement, ctx);
|
||||||
|
|
||||||
// force drawing of everything not yet drawn that is part of the target DI
|
// force drawing of everything not yet drawn that is part of the target DI
|
||||||
handleUnhandledProcesses(definitions.rootElements);
|
handleUnhandledProcesses(definitions.rootElements, ctx);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('unsupported root element for bpmndi:Diagram <' + rootElement.$type + '>');
|
throw new Error('unsupported root element for bpmndi:Diagram <' + rootElement.$type + '>');
|
||||||
}
|
}
|
||||||
|
@ -141,11 +147,12 @@ function BpmnTreeWalker(handler) {
|
||||||
function handleUnhandledProcesses(rootElements) {
|
function handleUnhandledProcesses(rootElements) {
|
||||||
|
|
||||||
// walk through all processes that have not yet been drawn and draw them
|
// walk through all processes that have not yet been drawn and draw them
|
||||||
// (in case they contain lanes with DI information)
|
// if they contain lanes with DI information.
|
||||||
|
// we do this to pass the free-floating lane test cases in the MIWG test suite
|
||||||
var processes = _.filter(rootElements, function(e) {
|
var processes = _.filter(rootElements, function(e) {
|
||||||
//Need this fix to get run test-case "01"
|
return is(e, 'bpmn:Process') && e.laneSets && handledProcesses.indexOf(e) === -1;
|
||||||
return e.$type === 'bpmn:Process' && e.laneSets && handledProcesses.indexOf(e) === -1;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
processes.forEach(contextual(handleProcess));
|
processes.forEach(contextual(handleProcess));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,10 @@ function importBpmnDiagram(diagram, definitions, done) {
|
||||||
|
|
||||||
var visitor = {
|
var visitor = {
|
||||||
|
|
||||||
|
root: function(element, di) {
|
||||||
|
return importer.add(element, di);
|
||||||
|
},
|
||||||
|
|
||||||
element: function(element, di, parent) {
|
element: function(element, di, parent) {
|
||||||
return importer.add(element, di, parent);
|
return importer.add(element, di, parent);
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Matchers = require('../../Matchers'),
|
||||||
|
TestHelper = require('../../TestHelper');
|
||||||
|
|
||||||
|
/* global bootstrapBpmnJS, inject */
|
||||||
|
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var bpmnCoreModule = require('../../../../lib/core');
|
||||||
|
|
||||||
|
|
||||||
|
describe('core', function() {
|
||||||
|
|
||||||
|
beforeEach(Matchers.add);
|
||||||
|
|
||||||
|
|
||||||
|
var diagramXML = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf-8');
|
||||||
|
|
||||||
|
var testModules = [ bpmnCoreModule ];
|
||||||
|
|
||||||
|
beforeEach(bootstrapBpmnJS(diagramXML, { modules: testModules }));
|
||||||
|
|
||||||
|
|
||||||
|
describe('BpmnRegistry', function() {
|
||||||
|
|
||||||
|
|
||||||
|
it('should get process semantic by ID', inject(function(bpmnRegistry) {
|
||||||
|
|
||||||
|
expect(bpmnRegistry.getSemantic('Process_1')).toBeDefined();
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -64,25 +64,18 @@ describe('import - importer', function() {
|
||||||
// given
|
// given
|
||||||
var xml = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf8');
|
var xml = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf8');
|
||||||
|
|
||||||
var events = [];
|
var eventCount = 0;
|
||||||
|
|
||||||
// log events
|
// log events
|
||||||
diagram.get('eventBus').on('bpmn.element.add', function(e) {
|
diagram.get('eventBus').on('bpmn.element.add', function(e) {
|
||||||
events.push({ type: 'add', semantic: e.semantic.id, di: e.di.id, diagramElement: e.diagramElement.id });
|
eventCount++;
|
||||||
});
|
});
|
||||||
|
|
||||||
// when
|
// when
|
||||||
runImport(diagram, xml, function(err, warnings) {
|
runImport(diagram, xml, function(err, warnings) {
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(events).toEqual([
|
expect(eventCount).toEqual(7);
|
||||||
{ type: 'add', semantic: 'SubProcess_1', di: '_BPMNShape_SubProcess_2', diagramElement: 'SubProcess_1' },
|
|
||||||
{ type: 'add', semantic: 'StartEvent_1', di: '_BPMNShape_StartEvent_2', diagramElement: 'StartEvent_1' },
|
|
||||||
{ type: 'add', semantic: 'Task_1', di: '_BPMNShape_Task_2', diagramElement: 'Task_1' },
|
|
||||||
{ type: 'add', semantic: 'SequenceFlow_1', di: 'BPMNEdge_SequenceFlow_1', diagramElement: 'SequenceFlow_1' },
|
|
||||||
{ type: 'add', semantic: 'EndEvent_1', di: '_BPMNShape_EndEvent_2', diagramElement: 'EndEvent_1' },
|
|
||||||
{ type: 'add', semantic: 'SequenceFlow_2', di: 'BPMNEdge_SequenceFlow_2', diagramElement: 'SequenceFlow_2' }
|
|
||||||
]);
|
|
||||||
|
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
|
@ -102,7 +95,12 @@ describe('import - importer', function() {
|
||||||
|
|
||||||
// log events
|
// log events
|
||||||
diagram.get('eventBus').on('bpmn.element.add', function(e) {
|
diagram.get('eventBus').on('bpmn.element.add', function(e) {
|
||||||
events.push({ type: 'add', semantic: e.semantic.id, di: e.di.id, diagramElement: e.diagramElement.id });
|
events.push({
|
||||||
|
type: 'add',
|
||||||
|
semantic: e.semantic.id,
|
||||||
|
di: e.di.id,
|
||||||
|
diagramElement: e.diagramElement && e.diagramElement.id
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
@ -110,6 +108,7 @@ describe('import - importer', function() {
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(events).toEqual([
|
expect(events).toEqual([
|
||||||
|
{ type: 'add', semantic: 'Process_1', di: 'BPMNPlane_1', diagramElement: null },
|
||||||
{ type: 'add', semantic: 'SubProcess_1', di: '_BPMNShape_SubProcess_2', diagramElement: 'SubProcess_1' },
|
{ type: 'add', semantic: 'SubProcess_1', di: '_BPMNShape_SubProcess_2', diagramElement: 'SubProcess_1' },
|
||||||
{ type: 'add', semantic: 'StartEvent_1', di: '_BPMNShape_StartEvent_2', diagramElement: 'StartEvent_1' },
|
{ type: 'add', semantic: 'StartEvent_1', di: '_BPMNShape_StartEvent_2', diagramElement: 'StartEvent_1' },
|
||||||
{ type: 'add', semantic: 'Task_1', di: '_BPMNShape_Task_2', diagramElement: 'Task_1' },
|
{ type: 'add', semantic: 'Task_1', di: '_BPMNShape_Task_2', diagramElement: 'Task_1' },
|
||||||
|
@ -132,7 +131,12 @@ describe('import - importer', function() {
|
||||||
|
|
||||||
// log events
|
// log events
|
||||||
diagram.get('eventBus').on('bpmn.element.add', function(e) {
|
diagram.get('eventBus').on('bpmn.element.add', function(e) {
|
||||||
events.push({ type: 'add', semantic: e.semantic.id, di: e.di.id, diagramElement: e.diagramElement.id });
|
events.push({
|
||||||
|
type: 'add',
|
||||||
|
semantic: e.semantic.id,
|
||||||
|
di: e.di.id,
|
||||||
|
diagramElement: e.diagramElement && e.diagramElement.id
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
@ -140,6 +144,7 @@ describe('import - importer', function() {
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(events).toEqual([
|
expect(events).toEqual([
|
||||||
|
{ type: 'add', semantic: '_Collaboration_2', di: 'BPMNPlane_1', diagramElement: null },
|
||||||
{ type: 'add', semantic: 'Participant_2', di: '_BPMNShape_Participant_2', diagramElement: 'Participant_2' },
|
{ type: 'add', semantic: 'Participant_2', di: '_BPMNShape_Participant_2', diagramElement: 'Participant_2' },
|
||||||
{ type: 'add', semantic: 'Lane_1', di: '_BPMNShape_Lane_2', diagramElement: 'Lane_1' },
|
{ type: 'add', semantic: 'Lane_1', di: '_BPMNShape_Lane_2', diagramElement: 'Lane_1' },
|
||||||
{ type: 'add', semantic: 'Lane_2', di: '_BPMNShape_Lane_3', diagramElement: 'Lane_2' },
|
{ type: 'add', semantic: 'Lane_2', di: '_BPMNShape_Lane_3', diagramElement: 'Lane_2' },
|
||||||
|
|
Loading…
Reference in New Issue