feat(import): forgive missing bpmnPlane#bpmnElement

Related to #146
This commit is contained in:
Nico Rehwaldt 2014-10-28 15:09:17 +01:00
parent 86f66bc534
commit 05b044e64d
2 changed files with 57 additions and 20 deletions

View File

@ -6,6 +6,20 @@ var Refs = require('object-refs');
var diRefs = new Refs({ name: 'bpmnElement', enumerable: true }, { name: 'di' });
function elementToString(e) {
return '<' + e.$type + (e.id ? ' id="' + e.id : '') + '" />';
}
/**
* Find a suitable display candidate for definitions where the DI does not
* correctly specify one.
*/
function findDisplayCandidate(definitions) {
return _.find(definitions.rootElements, function(e) {
return e.$instanceOf('bpmn:Process') || e.$instanceOf('bpmn:Collaboration');
});
}
function BpmnTreeWalker(handler) {
@ -34,7 +48,7 @@ function BpmnTreeWalker(handler) {
// avoid multiple rendering of elements
if (gfx) {
throw new Error('already rendered <' + element.id + '>');
throw new Error('already rendered ' + elementToString(element));
}
// call handler
@ -68,7 +82,7 @@ function BpmnTreeWalker(handler) {
diRefs.bind(bpmnElement, 'di');
bpmnElement.di = di;
} else {
logError('no bpmnElement for <' + di.$type + '#' + di.id + '>', { element: di });
logError('no bpmnElement referenced in ' + elementToString(di), { element: di });
}
}
@ -110,11 +124,31 @@ function BpmnTreeWalker(handler) {
// load DI from selected diagram only
handleDiagram(diagram);
var plane = diagram.plane,
rootElement = plane.bpmnElement;
var plane = diagram.plane;
if (!plane) {
throw new Error('no plane for ' + elementToString(diagram));
}
var rootElement = plane.bpmnElement;
// ensure we default to a suitable display candidate (process or collaboration),
// even if non is specified in DI
if (!rootElement) {
throw new Error('no rootElement referenced in BPMNPlane <' + diagram.plane.id + '>');
rootElement = findDisplayCandidate(definitions);
if (!rootElement) {
throw new Error('do not know what to display');
} else {
logError('correcting missing bpmnElement on ' + elementToString(plane) + ' to ' + elementToString(rootElement));
// correct DI on the fly
plane.bpmnElement = rootElement;
registerDi(plane);
}
}
@ -128,7 +162,7 @@ function BpmnTreeWalker(handler) {
// force drawing of everything not yet drawn that is part of the target DI
handleUnhandledProcesses(definitions.rootElements, ctx);
} else {
throw new Error('unsupported root element for bpmndi:Diagram <' + rootElement.$type + '>');
throw new Error('unsupported bpmnElement for ' + elementToString(plane) + ' : ' + elementToString(rootElement));
}
// handle all deferred elements
@ -166,9 +200,7 @@ function BpmnTreeWalker(handler) {
}
function handleMessageFlows(messageFlows, context) {
if (messageFlows) {
_.forEach(messageFlows, contextual(handleMessageFlow, context));
}
_.forEach(messageFlows, contextual(handleMessageFlow, context));
}
function handleDataAssociation(association, context) {
@ -313,7 +345,8 @@ function BpmnTreeWalker(handler) {
handleDataElement(e, context);
} else {
logError(
'unrecognized flowElement <' + e.$type + '> in context ' + (context ? context.id : null),
'unrecognized flowElement ' + elementToString(e) + ' in context ' +
(context ? elementToString(context) : null),
{ element: e, context: context });
}
});

View File

@ -26,8 +26,8 @@ describe('viewer', function() {
function createViewer(xml, done) {
var viewer = new Viewer({ container: container });
viewer.importXML(xml, function(err) {
done(err, viewer);
viewer.importXML(xml, function(err, warnings) {
done(err, warnings, viewer);
});
}
@ -93,7 +93,7 @@ describe('viewer', function() {
var xml = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf8');
createViewer(xml, function(err, viewer) {
createViewer(xml, function(err, warnings, viewer) {
// when
var overlays = viewer.get('overlays'),
@ -145,9 +145,13 @@ describe('viewer', function() {
var xml = fs.readFileSync('test/fixtures/bpmn/error/di-plane-no-bpmn-element.bpmn', 'utf8');
createViewer(xml, function(err) {
expect(err).toBeDefined();
expect(err.message).toEqual('no rootElement referenced in BPMNPlane <BPMNPlane_1>');
createViewer(xml, function(err, warnings) {
expect(err).not.toBeDefined();
expect(warnings.length).toBe(2);
expect(warnings[0].message).toEqual('no bpmnElement referenced in <bpmndi:BPMNPlane id="BPMNPlane_1" />');
expect(warnings[1].message).toEqual('correcting missing bpmnElement on <bpmndi:BPMNPlane id="BPMNPlane_1" /> to <bpmn:Process id="Process_1" />');
done();
});
@ -179,7 +183,7 @@ describe('viewer', function() {
var xml = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf8');
createViewer(xml, function(err, viewer) {
createViewer(xml, function(err, warnings, viewer) {
expect(viewer.get('bpmnjs')).toBe(viewer);
@ -220,7 +224,7 @@ describe('viewer', function() {
// given
var xml = fs.readFileSync('test/fixtures/bpmn/empty-definitions.bpmn', 'utf8');
createViewer(xml, function(err, viewer) {
createViewer(xml, function(err, warnings, viewer) {
if (err) {
return done(err);
@ -247,7 +251,7 @@ describe('viewer', function() {
// given
var xml = fs.readFileSync('test/fixtures/bpmn/complex.bpmn', 'utf8');
createViewer(xml, function(err, viewer) {
createViewer(xml, function(err, warnings, viewer) {
if (err) {
return done(err);
@ -287,7 +291,7 @@ describe('viewer', function() {
svgDoc.appendChild(rect);
}
createViewer(xml, function(err, viewer) {
createViewer(xml, function(err, warnings, viewer) {
if (err) {
return done(err);