fix(import): correctly dispatch parse warnings

Fixes our bpmn-moddle integration to correctly dispatch parse warnings
from bpmn-moddle to the client.

Related to bpmn-io/moddle-xml#5

Closes #58
This commit is contained in:
Nico Rehwaldt 2015-02-17 10:55:28 +01:00
parent f3a1c8a42c
commit 4854c96067
6 changed files with 127 additions and 28 deletions

View File

@ -131,14 +131,22 @@ Viewer.prototype.importXML = function(xml, done) {
this.moddle = this.moddle || this.createModdle();
this.moddle.fromXML(xml, 'bpmn:Definitions', function(err, definitions) {
this.moddle.fromXML(xml, 'bpmn:Definitions', function(err, definitions, context) {
if (err) {
err = checkValidationError(err);
return done(err);
}
self.importDefinitions(definitions, done);
var parseWarnings = context.warnings;
self.importDefinitions(definitions, function(err, importWarnings) {
if (err) {
return done(err);
}
done(null, parseWarnings.concat(importWarnings || []));
});
});
};

View File

@ -10,6 +10,18 @@ var elementToString = require('./Util').elementToString;
var diRefs = new Refs({ name: 'bpmnElement', enumerable: true }, { name: 'di' });
/**
* Returns true if an element has the given meta-model type
*
* @param {ModdleElement} element
* @param {String} type
*
* @return {Boolean}
*/
function is(element, type) {
return element.$instanceOf(type);
}
/**
* Find a suitable display candidate for definitions where the DI does not
@ -17,7 +29,7 @@ var diRefs = new Refs({ name: 'bpmnElement', enumerable: true }, { name: 'di' })
*/
function findDisplayCandidate(definitions) {
return find(definitions.rootElements, function(e) {
return e.$instanceOf('bpmn:Process') || e.$instanceOf('bpmn:Collaboration');
return is(e, 'bpmn:Process') || is(e, 'bpmn:Collaboration');
});
}
@ -39,10 +51,6 @@ function BpmnTreeWalker(handler) {
};
}
function is(element, type) {
return element.$instanceOf(type);
}
function visit(element, ctx) {
var gfx = element.gfx;
@ -146,7 +154,7 @@ function BpmnTreeWalker(handler) {
rootElement = findDisplayCandidate(definitions);
if (!rootElement) {
throw new Error('do not know what to display');
return logError('no process or collaboration present to display');
} else {
logError('correcting missing bpmnElement on ' + elementToString(plane) + ' to ' + elementToString(rootElement));

View File

@ -56,7 +56,7 @@
"uglify-js": "^2.4.16"
},
"dependencies": {
"bpmn-moddle": "^0.7.0",
"bpmn-moddle": "^0.8.0",
"diagram-js-direct-editing": "^0.8.0",
"didi": "^0.0.4",
"ids": "^0.1.0",

View File

@ -0,0 +1,27 @@
<?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:signavio="http://www.signavio.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="Signavio Process Editor, http://www.signavio.com" exporterVersion="8.4.1" expressionLanguage="http://www.w3.org/1999/XPath" id="sid-73c85f47-caf7-49f4-81c2-ccd9c46beedb" targetNamespace="http://www.signavio.com/bpmn20" 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">
<categoryValue id="sid-afd7e63e-916e-4bd0-a9f0-98cbff749193" value="group with label"/>
<process id="sid-d21bd22a-e617-4562-9cbd-2546073c1cf1" isExecutable="false" processType="None">
<extensionElements>
<signavio:signavioDiagramMetaData metaKey="revisionid" metaValue="a97a57cd8c4145d09f902344a2f6eec7"/>
</extensionElements>
<group categoryValueRef="sid-afd7e63e-916e-4bd0-a9f0-98cbff749193" id="sid-1FB8E9C5-D54C-4FCA-A2B2-256090EC79DF">
<extensionElements>
<signavio:signavioMetaData metaKey="userstory" metaValue=""/>
</extensionElements>
</group>
</process>
<bpmndi:BPMNDiagram id="sid-73344385-3bbb-419c-ad69-a9db64e271c7">
<bpmndi:BPMNPlane bpmnElement="sid-d21bd22a-e617-4562-9cbd-2546073c1cf1" id="sid-def820ae-1226-4abe-9eb0-7b5543824627">
<bpmndi:BPMNShape bpmnElement="sid-1FB8E9C5-D54C-4FCA-A2B2-256090EC79DF" id="sid-1FB8E9C5-D54C-4FCA-A2B2-256090EC79DF_gui">
<omgdc:Bounds height="234.0" width="346.0" x="180.0" y="135.0"/>
<bpmndi:BPMNLabel labelStyle="sid-41bec41f-8420-426c-bf18-f704a8dd71d2">
<omgdc:Bounds height="12.0" width="96.0" x="184.0" y="137.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="sid-41bec41f-8420-426c-bf18-f704a8dd71d2">
<omgdc:Font isBold="false" isItalic="false" isStrikeThrough="false" isUnderline="false" name="Arial" size="11.0"/>
</bpmndi:BPMNLabelStyle>
</bpmndi:BPMNDiagram>
</definitions>

View File

@ -119,13 +119,37 @@ describe('Viewer', function() {
describe('error handling', function() {
function expectMessage(e, expectedMessage) {
expect(e).toBeDefined();
if (expectedMessage instanceof RegExp) {
expect(e.message).toMatch(expectedMessage);
} else {
expect(e.message).toEqual(expectedMessage);
}
}
function expectWarnings(warnings, expected) {
expect(warnings.length).toBe(expected.length);
warnings.forEach(function(w, idx) {
expectMessage(w, expected[idx]);
});
}
it('should handle non-bpmn input', function(done) {
var xml = 'invalid stuff';
createViewer(xml, function(err) {
expect(err).toBeDefined();
expect(err).toBeTruthy();
expectMessage(err, /Text data outside of root node./);
done();
});
@ -136,13 +160,39 @@ describe('Viewer', function() {
var xml = fs.readFileSync('test/fixtures/bpmn/error/di-plane-no-bpmn-element.bpmn', 'utf8');
// when
createViewer(xml, function(err, warnings) {
expect(err).not.toBeDefined();
expect(warnings.length).toBe(2);
// then
expect(err).toBeFalsy();
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" />');
expectWarnings(warnings, [
'unresolved reference <Collaboration_2>',
'no bpmnElement referenced in <bpmndi:BPMNPlane id="BPMNPlane_1" />',
'correcting missing bpmnElement ' +
'on <bpmndi:BPMNPlane id="BPMNPlane_1" /> ' +
'to <bpmn:Process id="Process_1" />'
]);
done();
});
});
it('should handle invalid namespaced element', function(done) {
var xml = fs.readFileSync('test/fixtures/bpmn/error/categoryValue.bpmn', 'utf8');
// when
createViewer(xml, function(err, warnings) {
// then
expect(err).toBeFalsy();
expectWarnings(warnings, [
/unparsable content <categoryValue> detected/,
'unresolved reference <sid-afd7e63e-916e-4bd0-a9f0-98cbff749193>'
]);
done();
});
@ -153,13 +203,19 @@ describe('Viewer', function() {
var xml = fs.readFileSync('test/fixtures/bpmn/error/missing-namespace.bpmn', 'utf8');
createViewer(xml, function(err) {
expect(err).toBeDefined();
expect(err.message).toEqual(
'unparsable content <collaboration> detected; this may indicate an invalid BPMN 2.0 diagram file\n' +
'\tline: 2\n' +
'\tcolumn: 29\n' +
'\tnested error: unrecognized element <collaboration>');
// when
createViewer(xml, function(err, warnings) {
// then
expect(err).toBeFalsy();
expectWarnings(warnings, [
/unparsable content <collaboration> detected/,
'unresolved reference <Participant_1>',
'no bpmnElement referenced in <bpmndi:BPMNPlane id="BPMNPlane_1" />',
'no bpmnElement referenced in <bpmndi:BPMNShape id="BPMNShape_Participant_1" />',
'no process or collaboration present to display'
]);
done();
});

View File

@ -15,11 +15,6 @@ describe('import - importer', function() {
var moddle = new BpmnModdle();
function read(xml, opts, callback) {
return moddle.fromXML(xml, 'bpmn:Definitions', opts, callback);
}
var container;
beforeEach(function() {
@ -287,8 +282,11 @@ describe('import - importer', function() {
// when
runImport(diagram, xml, function(err, warnings) {
var expectedMessage =
'multiple DI elements defined for <bpmn:InclusiveGateway id="InclusiveGateway_1" />';
expect(warnings.length).toBe(1);
expect(warnings[0].message).toBe('multiple DI elements defined for <bpmn:InclusiveGateway id="InclusiveGateway_1" />');
expect(warnings[0].message).toBe(expectedMessage);
done(err);
});
@ -353,10 +351,10 @@ describe('import - importer', function() {
});
});
describe('position', function() {
var xml1 = fs.readFileSync('test/fixtures/bpmn/import/position/position-testcase.bpmn', 'utf8');
var xml2 = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf8');
it('should round shape\'s x and y coordinates', function(done) {
@ -383,6 +381,7 @@ describe('import - importer', function() {
});
});
it('should round shape\'s height and width', function(done) {
// given
@ -405,4 +404,5 @@ describe('import - importer', function() {
});
});
});