feat: add additional (default!) moddle descriptor to viewer

Closes #471
This commit is contained in:
davcs86 2016-02-17 18:16:10 -06:00 committed by Vladimirs Katusenoks
parent b89b9be65a
commit 0fb1bf616e
4 changed files with 164 additions and 20 deletions

View File

@ -9,7 +9,8 @@
var assign = require('lodash/object/assign'), var assign = require('lodash/object/assign'),
omit = require('lodash/object/omit'), omit = require('lodash/object/omit'),
isString = require('lodash/lang/isString'), isString = require('lodash/lang/isString'),
isNumber = require('lodash/lang/isNumber'); isNumber = require('lodash/lang/isNumber'),
merge = require('lodash/object/merge');
var domify = require('min-dom/lib/domify'), var domify = require('min-dom/lib/domify'),
domQuery = require('min-dom/lib/query'), domQuery = require('min-dom/lib/query'),
@ -146,10 +147,10 @@ module.exports = Viewer;
/** /**
* Import and render a BPMN 2.0 diagram. * Import and render a BPMN 2.0 diagram.
* *
* Once finished the viewer reports back the result to the * Once finished the viewer reports back the result to the
* provided callback function with (err, warnings). * provided callback function with (err, warnings).
* *
* @param {String} xml the BPMN 2.0 xml * @param {String} xml the BPMN 2.0 xml
* @param {Function} done invoked with (err, warnings=[]) * @param {Function} done invoked with (err, warnings=[])
*/ */
@ -179,11 +180,11 @@ Viewer.prototype.importXML = function(xml, done) {
/** /**
* Export the currently displayed BPMN 2.0 diagram as * Export the currently displayed BPMN 2.0 diagram as
* a BPMN 2.0 XML document. * a BPMN 2.0 XML document.
* *
* @param {Object} [options] export options * @param {Object} [options] export options
* @param {Boolean} [options.format=false] output formated XML * @param {Boolean} [options.format=false] output formated XML
* @param {Boolean} [options.preamble=true] output preamble * @param {Boolean} [options.preamble=true] output preamble
* *
* @param {Function} done invoked with (err, xml) * @param {Function} done invoked with (err, xml)
*/ */
Viewer.prototype.saveXML = function(options, done) { Viewer.prototype.saveXML = function(options, done) {
@ -203,13 +204,13 @@ Viewer.prototype.saveXML = function(options, done) {
}; };
Viewer.prototype.createModdle = function() { Viewer.prototype.createModdle = function() {
return new BpmnModdle(this.options.moddleExtensions); return new BpmnModdle(merge(this.options.moddleExtensions, this._moddleExtensions));
}; };
/** /**
* Export the currently displayed BPMN 2.0 diagram as * Export the currently displayed BPMN 2.0 diagram as
* an SVG image. * an SVG image.
* *
* @param {Object} [options] * @param {Object} [options]
* @param {Function} done invoked with (err, svgStr) * @param {Function} done invoked with (err, svgStr)
*/ */
@ -245,14 +246,14 @@ Viewer.prototype.saveSVG = function(options, done) {
/** /**
* Get a named diagram service. * Get a named diagram service.
* *
* @example * @example
* *
* var elementRegistry = viewer.get('elementRegistry'); * var elementRegistry = viewer.get('elementRegistry');
* var startEventShape = elementRegistry.get('StartEvent_1'); * var startEventShape = elementRegistry.get('StartEvent_1');
* *
* @param {String} name * @param {String} name
* *
* @return {Object} diagram service instance * @return {Object} diagram service instance
*/ */
Viewer.prototype.get = function(name) { Viewer.prototype.get = function(name) {
@ -266,15 +267,15 @@ Viewer.prototype.get = function(name) {
/** /**
* Invoke a function in the context of this viewer. * Invoke a function in the context of this viewer.
* *
* @example * @example
* *
* viewer.invoke(function(elementRegistry) { * viewer.invoke(function(elementRegistry) {
* var startEventShape = elementRegistry.get('StartEvent_1'); * var startEventShape = elementRegistry.get('StartEvent_1');
* }); * });
* *
* @param {Function} fn to be invoked * @param {Function} fn to be invoked
* *
* @return {Object} the functions return value * @return {Object} the functions return value
*/ */
Viewer.prototype.invoke = function(fn) { Viewer.prototype.invoke = function(fn) {
@ -366,7 +367,7 @@ Viewer.prototype.destroy = function() {
* Register an event listener on the viewer * Register an event listener on the viewer
* *
* Remove a previously added listener via {@link #off(event, callback)}. * Remove a previously added listener via {@link #off(event, callback)}.
* *
* @param {String} event * @param {String} event
* @param {Number} [priority] * @param {Number} [priority]
* @param {Function} callback * @param {Function} callback
@ -381,7 +382,7 @@ Viewer.prototype.on = function(event, priority, callback, that) {
callback = priority; callback = priority;
priority = 1000; priority = 1000;
} }
listeners.push({ event: event, priority: priority, callback: callback, that: that }); listeners.push({ event: event, priority: priority, callback: callback, that: that });
if (diagram) { if (diagram) {
@ -398,7 +399,7 @@ Viewer.prototype.on = function(event, priority, callback, that) {
Viewer.prototype.off = function(event, callback) { Viewer.prototype.off = function(event, callback) {
var filter, var filter,
diagram = this.diagram; diagram = this.diagram;
if (callback) { if (callback) {
filter = function(l) { filter = function(l) {
return !(l.event === event && l.callback === callback); return !(l.event === event && l.callback === callback);
@ -408,9 +409,9 @@ Viewer.prototype.off = function(event, callback) {
return l.event !== event; return l.event !== event;
}; };
} }
this.__listeners = (this.__listeners || []).filter(filter); this.__listeners = (this.__listeners || []).filter(filter);
if (diagram) { if (diagram) {
diagram.get('eventBus').off(event, callback); diagram.get('eventBus').off(event, callback);
} }
@ -423,6 +424,8 @@ Viewer.prototype._modules = [
require('diagram-js/lib/features/overlays') require('diagram-js/lib/features/overlays')
]; ];
// default moddle extensions the viewer is composed of
Viewer.prototype._moddleExtensions = {};
/* <project-logo> */ /* <project-logo> */

View File

@ -0,0 +1,54 @@
<?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:camunda="http://activiti.org/bpmn" xmlns:custom="http://customdescriptor.com/bpmn2" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="_FVEpwO_VEeOtYvXzz5ksgw" exporter="camunda modeler" exporterVersion="2.5.0" targetNamespace="http://activiti.org/bpmn">
<bpmn2:process id="testProcess" isExecutable="true">
<bpmn2:startEvent id="StartEvent_1">
<bpmn2:outgoing>SequenceFlow_1</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:sendTask id="send" name="send">
<bpmn2:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="var1">
<camunda:map>
<camunda:entry key="a">
<camunda:list>
<camunda:value>stringInListNestedInMap</camunda:value>
<camunda:value>${ 'b' }</camunda:value>
</camunda:list>
</camunda:entry>
</camunda:map>
</camunda:inputParameter>
<camunda:inputParameter name="var2">stringConstantValue</camunda:inputParameter>
</camunda:inputOutput>
<custom:customSendElement name="custom" value="1" />
</bpmn2:extensionElements>
<bpmn2:incoming>SequenceFlow_1</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_2</bpmn2:outgoing>
</bpmn2:sendTask>
<bpmn2:sequenceFlow id="SequenceFlow_1" name="" sourceRef="StartEvent_1" targetRef="send"/>
<bpmn2:endEvent id="EndEvent_1">
<bpmn2:incoming>SequenceFlow_2</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="SequenceFlow_2" name="" sourceRef="send" targetRef="EndEvent_1"/>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="testProcess">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds height="36.0" width="36.0" x="128.0" y="178.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_UserTask_2" bpmnElement="send">
<dc:Bounds height="80.0" width="100.0" x="214.0" y="156.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_1" sourceElement="_BPMNShape_StartEvent_2" targetElement="_BPMNShape_UserTask_2">
<di:waypoint xsi:type="dc:Point" x="164.0" y="196.0"/>
<di:waypoint xsi:type="dc:Point" x="214.0" y="196.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_EndEvent_2" bpmnElement="EndEvent_1">
<dc:Bounds height="36.0" width="36.0" x="364.0" y="178.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_2" bpmnElement="SequenceFlow_2" sourceElement="_BPMNShape_UserTask_2" targetElement="_BPMNShape_EndEvent_2">
<di:waypoint xsi:type="dc:Point" x="314.0" y="196.0"/>
<di:waypoint xsi:type="dc:Point" x="364.0" y="196.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

39
test/fixtures/json/model/custom.json vendored Normal file
View File

@ -0,0 +1,39 @@
{
"name": "Custom descriptor",
"uri": "http://customdescriptor.com/bpmn2",
"prefix": "custom",
"xml": {
"tagAlias": "lowerCase"
},
"associations": [],
"types": [
{
"name": "CustomSendElement",
"superClass": [
"Element"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "value",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "ServiceTaskGroup",
"extends": [
"bpmn:ServiceTask",
"bpmn:BusinessRuleTask",
"bpmn:SendTask",
"bpmn:MessageEventDefinition"
]
}
],
"emumerations": [ ]
}

View File

@ -545,6 +545,54 @@ describe('Viewer', function() {
}); });
it.only('should allow to add default custom moddle extensions', function(done) {
var xml = require('../fixtures/bpmn/extension/custom.bpmn'),
additionalModdleDescriptors = {
custom: require('../fixtures/json/model/custom')
};
Viewer.prototype._moddleExtensions = additionalModdleDescriptors;
// given
viewer = new Viewer({
container: container,
moddleExtensions: {
camunda: camundaPackage
}
});
// when
viewer.importXML(xml, function(err, warnings) {
var elementRegistry = viewer.get('elementRegistry');
var taskShape = elementRegistry.get('send'),
sendTask = taskShape.businessObject;
// then
expect(sendTask).to.exist;
var extensionElements = sendTask.extensionElements;
// receive task should be moddle extended
expect(sendTask.$instanceOf('camunda:ServiceTaskLike')).to.exist;
expect(sendTask.$instanceOf('custom:ServiceTaskGroup')).to.exist;
// extension elements should provide typed element
expect(extensionElements).to.exist;
expect(extensionElements.values.length).to.equal(2);
expect(extensionElements.values[0].$instanceOf('camunda:InputOutput')).to.exist;
expect(extensionElements.values[1].$instanceOf('custom:CustomSendElement')).to.exist;
done(err);
});
});
it('should throw error due to missing diagram', function(done) { it('should throw error due to missing diagram', function(done) {
var xml = require('../fixtures/bpmn/empty-definitions.bpmn'); var xml = require('../fixtures/bpmn/empty-definitions.bpmn');