/*!
* bpmn-js - bpmn-navigated-viewer v0.14.1
* Copyright 2014, 2015 camunda Services GmbH and other contributors
*
* Released under the bpmn.io license
* http://bpmn.io/license
*
* Source Code: https://github.com/bpmn-io/bpmn-js
*
* Date: 2016-03-23
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.BpmnJS = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o area
* must not be changed.
*
* @see http://bpmn.io/license for more information.
*/
'use strict';
var assign = _dereq_(206),
omit = _dereq_(210),
isString = _dereq_(203),
isNumber = _dereq_(200);
var domify = _dereq_(220),
domQuery = _dereq_(222),
domRemove = _dereq_(223);
var Diagram = _dereq_(37),
BpmnModdle = _dereq_(16);
var inherits = _dereq_(86);
var Importer = _dereq_(9);
function checkValidationError(err) {
// check if we can help the user by indicating wrong BPMN 2.0 xml
// (in case he or the exporting tool did not get that right)
var pattern = /unparsable content <([^>]+)> detected([\s\S]*)$/;
var match = pattern.exec(err.message);
if (match) {
err.message =
'unparsable content <' + match[1] + '> detected; ' +
'this may indicate an invalid BPMN 2.0 diagram file' + match[2];
}
return err;
}
var DEFAULT_OPTIONS = {
width: '100%',
height: '100%',
position: 'relative',
container: 'body'
};
/**
* Ensure the passed argument is a proper unit (defaulting to px)
*/
function ensureUnit(val) {
return val + (isNumber(val) ? 'px' : '');
}
/**
* A viewer for BPMN 2.0 diagrams.
*
* Have a look at {@link NavigatedViewer} or {@link Modeler} for bundles that include
* additional features.
*
*
* ## Extending the Viewer
*
* In order to extend the viewer pass extension modules to bootstrap via the
* `additionalModules` option. An extension module is an object that exposes
* named services.
*
* The following example depicts the integration of a simple
* logging component that integrates with interaction events:
*
*
* ```javascript
*
* // logging component
* function InteractionLogger(eventBus) {
* eventBus.on('element.hover', function(event) {
* console.log()
* })
* }
*
* InteractionLogger.$inject = [ 'eventBus' ]; // minification save
*
* // extension module
* var extensionModule = {
* __init__: [ 'interactionLogger' ],
* interactionLogger: [ 'type', InteractionLogger ]
* };
*
* // extend the viewer
* var bpmnViewer = new Viewer({ additionalModules: [ extensionModule ] });
* bpmnViewer.importXML(...);
* ```
*
* @param {Object} [options] configuration options to pass to the viewer
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
* @param {String|Number} [options.width] the width of the viewer
* @param {String|Number} [options.height] the height of the viewer
* @param {Object} [options.moddleExtensions] extension packages to provide
* @param {Array} [options.modules] a list of modules to override the default modules
* @param {Array} [options.additionalModules] a list of modules to use with the default modules
*/
function Viewer(options) {
options = assign({}, DEFAULT_OPTIONS, options);
this.moddle = this._createModdle(options);
this.container = this._createContainer(options);
/* */
addProjectLogo(this.container);
/* */
this._init(this.container, this.moddle, options);
}
inherits(Viewer, Diagram);
module.exports = Viewer;
/**
* Parse and render a BPMN 2.0 diagram.
*
* Once finished the viewer reports back the result to the
* provided callback function with (err, warnings).
*
* ## Life-Cycle Events
*
* During import the viewer will fire life-cycle events:
*
* * import.parse.start (about to read model from xml)
* * import.parse.complete (model read; may have worked or not)
* * import.render.start (graphical import start)
* * import.render.complete (graphical import finished)
* * import.done (everything done)
*
* You can use these events to hook into the life-cycle.
*
* @param {String} xml the BPMN 2.0 xml
* @param {Function} [done] invoked with (err, warnings=[])
*/
Viewer.prototype.importXML = function(xml, done) {
// done is optional
done = done || function() {};
var self = this;
// hook in pre-parse listeners +
// allow xml manipulation
xml = this._emit('import.parse.start', { xml: xml }) || xml;
this.moddle.fromXML(xml, 'bpmn:Definitions', function(err, definitions, context) {
// hook in post parse listeners +
// allow definitions manipulation
definitions = self._emit('import.parse.complete', {
error: err,
definitions: definitions,
context: context
}) || definitions;
if (err) {
err = checkValidationError(err);
self._emit('import.done', { error: err });
return done(err);
}
var parseWarnings = context.warnings;
self.importDefinitions(definitions, function(err, importWarnings) {
var allWarnings = [].concat(parseWarnings, importWarnings || []);
self._emit('import.done', { error: err, warnings: allWarnings });
done(err, allWarnings);
});
});
};
/**
* Export the currently displayed BPMN 2.0 diagram as
* a BPMN 2.0 XML document.
*
* @param {Object} [options] export options
* @param {Boolean} [options.format=false] output formated XML
* @param {Boolean} [options.preamble=true] output preamble
*
* @param {Function} done invoked with (err, xml)
*/
Viewer.prototype.saveXML = function(options, done) {
if (!done) {
done = options;
options = {};
}
var definitions = this.definitions;
if (!definitions) {
return done(new Error('no definitions loaded'));
}
this.moddle.toXML(definitions, options, done);
};
/**
* Export the currently displayed BPMN 2.0 diagram as
* an SVG image.
*
* @param {Object} [options]
* @param {Function} done invoked with (err, svgStr)
*/
Viewer.prototype.saveSVG = function(options, done) {
if (!done) {
done = options;
options = {};
}
var canvas = this.get('canvas');
var contentNode = canvas.getDefaultLayer(),
defsNode = canvas._svg.select('defs');
var contents = contentNode.innerSVG(),
defs = (defsNode && defsNode.outerSVG()) || '';
var bbox = contentNode.getBBox();
var svg =
'\n' +
'\n' +
'\n' +
'' +
defs + contents +
' ';
done(null, svg);
};
/**
* Get a named diagram service.
*
* @example
*
* var elementRegistry = viewer.get('elementRegistry');
* var startEventShape = elementRegistry.get('StartEvent_1');
*
* @param {String} name
*
* @return {Object} diagram service instance
*
* @method Viewer#get
*/
/**
* Invoke a function in the context of this viewer.
*
* @example
*
* viewer.invoke(function(elementRegistry) {
* var startEventShape = elementRegistry.get('StartEvent_1');
* });
*
* @param {Function} fn to be invoked
*
* @return {Object} the functions return value
*
* @method Viewer#invoke
*/
/**
* Remove all drawn elements from the viewer.
*
* After calling this method the viewer can still
* be reused for opening another diagram.
*
* @method Viewer#clear
*/
Viewer.prototype.importDefinitions = function(definitions, done) {
// use try/catch to not swallow synchronous exceptions
// that may be raised during model parsing
try {
if (this.definitions) {
// clear existing rendered diagram
this.clear();
}
// update definitions
this.definitions = definitions;
// perform graphical import
Importer.importBpmnDiagram(this, definitions, done);
} catch (e) {
// handle synchronous errors
done(e);
}
};
Viewer.prototype.getModules = function() {
return this._modules;
};
/**
* Destroy the viewer instance and remove all its
* remainders from the document tree.
*/
Viewer.prototype.destroy = function() {
// diagram destroy
Diagram.prototype.destroy.call(this);
// dom detach
domRemove(this.container);
};
/**
* Register an event listener
*
* Remove a previously added listener via {@link #off(event, callback)}.
*
* @param {String} event
* @param {Number} [priority]
* @param {Function} callback
* @param {Object} [that]
*/
Viewer.prototype.on = function(event, priority, callback, target) {
return this.get('eventBus').on(event, priority, callback, target);
};
/**
* De-register an event listener
*
* @param {String} event
* @param {Function} callback
*/
Viewer.prototype.off = function(event, callback) {
this.get('eventBus').off(event, callback);
};
Viewer.prototype._init = function(container, moddle, options) {
var baseModules = options.modules || this.getModules(),
additionalModules = options.additionalModules || [],
staticModules = [
{
bpmnjs: [ 'value', this ],
moddle: [ 'value', moddle ]
}
];
var diagramModules = [].concat(staticModules, baseModules, additionalModules);
var diagramOptions = assign(omit(options, 'additionalModules'), {
canvas: assign({}, options.canvas, { container: container }),
modules: diagramModules
});
// invoke diagram constructor
Diagram.call(this, diagramOptions);
};
/**
* Emit an event on the underlying {@link EventBus}
*
* @param {String} type
* @param {Object} event
*
* @return {Object} event processing result (if any)
*/
Viewer.prototype._emit = function(type, event) {
return this.get('eventBus').fire(type, event);
};
Viewer.prototype._createContainer = function(options) {
var parent = options.container,
container;
// support jquery element
// unwrap it if passed
if (parent.get) {
parent = parent.get(0);
}
// support selector
if (isString(parent)) {
parent = domQuery(parent);
}
container = domify('
');
assign(container.style, {
width: ensureUnit(options.width),
height: ensureUnit(options.height),
position: options.position
});
parent.appendChild(container);
return container;
};
Viewer.prototype._createModdle = function(options) {
var moddleOptions = assign({}, this._moddleExtensions, options.moddleExtensions);
return new BpmnModdle(moddleOptions);
};
// modules the viewer is composed of
Viewer.prototype._modules = [
_dereq_(3),
_dereq_(59),
_dereq_(58),
_dereq_(54)
];
// default moddle extensions the viewer is composed of
Viewer.prototype._moddleExtensions = {};
/* */
var PoweredBy = _dereq_(15),
domEvent = _dereq_(221);
/**
* Adds the project logo to the diagram container as
* required by the bpmn.io license.
*
* @see http://bpmn.io/license
*
* @param {Element} container
*/
function addProjectLogo(container) {
var logoData = PoweredBy.BPMNIO_LOGO;
var linkMarkup =
'' +
' ' +
' ';
var linkElement = domify(linkMarkup);
container.appendChild(linkElement);
domEvent.bind(linkElement, 'click', function(event) {
PoweredBy.open();
event.preventDefault();
});
}
/* */
},{"15":15,"16":16,"200":200,"203":203,"206":206,"210":210,"220":220,"221":221,"222":222,"223":223,"3":3,"37":37,"54":54,"58":58,"59":59,"86":86,"9":9}],3:[function(_dereq_,module,exports){
module.exports = {
__depends__: [
_dereq_(6),
_dereq_(11)
]
};
},{"11":11,"6":6}],4:[function(_dereq_,module,exports){
'use strict';
var inherits = _dereq_(86),
isObject = _dereq_(201),
assign = _dereq_(206),
forEach = _dereq_(92),
every = _dereq_(89),
includes = _dereq_(94),
some = _dereq_(97);
var BaseRenderer = _dereq_(45),
TextUtil = _dereq_(78),
DiUtil = _dereq_(12);
var is = _dereq_(14).is;
var RenderUtil = _dereq_(77);
var componentsToPath = RenderUtil.componentsToPath,
createLine = RenderUtil.createLine;
var TASK_BORDER_RADIUS = 10;
var INNER_OUTER_DIST = 3;
var LABEL_STYLE = {
fontFamily: 'Arial, sans-serif',
fontSize: '12px'
};
function BpmnRenderer(eventBus, styles, pathMap, priority) {
BaseRenderer.call(this, eventBus, priority);
var textUtil = new TextUtil({
style: LABEL_STYLE,
size: { width: 100 }
});
var markers = {};
var computeStyle = styles.computeStyle;
function addMarker(id, element) {
markers[id] = element;
}
function marker(id) {
return markers[id];
}
function initMarkers(svg) {
function createMarker(id, options) {
var attrs = assign({
fill: 'black',
strokeWidth: 1,
strokeLinecap: 'round',
strokeDasharray: 'none'
}, options.attrs);
var ref = options.ref || { x: 0, y: 0 };
var scale = options.scale || 1;
// fix for safari / chrome / firefox bug not correctly
// resetting stroke dash array
if (attrs.strokeDasharray === 'none') {
attrs.strokeDasharray = [10000, 1];
}
var marker = options.element
.attr(attrs)
.marker(0, 0, 20, 20, ref.x, ref.y)
.attr({
markerWidth: 20 * scale,
markerHeight: 20 * scale
});
return addMarker(id, marker);
}
createMarker('sequenceflow-end', {
element: svg.path('M 1 5 L 11 10 L 1 15 Z'),
ref: { x: 11, y: 10 },
scale: 0.5
});
createMarker('messageflow-start', {
element: svg.circle(6, 6, 3.5),
attrs: {
fill: 'white',
stroke: 'black'
},
ref: { x: 6, y: 6 }
});
createMarker('messageflow-end', {
element: svg.path('m 1 5 l 0 -3 l 7 3 l -7 3 z'),
attrs: {
fill: 'white',
stroke: 'black',
strokeLinecap: 'butt'
},
ref: { x: 8.5, y: 5 }
});
createMarker('association-start', {
element: svg.path('M 11 5 L 1 10 L 11 15'),
attrs: {
fill: 'none',
stroke: 'black',
strokeWidth: 1.5
},
ref: { x: 1, y: 10 },
scale: 0.5
});
createMarker('association-end', {
element: svg.path('M 1 5 L 11 10 L 1 15'),
attrs: {
fill: 'none',
stroke: 'black',
strokeWidth: 1.5
},
ref: { x: 12, y: 10 },
scale: 0.5
});
createMarker('conditional-flow-marker', {
element: svg.path('M 0 10 L 8 6 L 16 10 L 8 14 Z'),
attrs: {
fill: 'white',
stroke: 'black'
},
ref: { x: -1, y: 10 },
scale: 0.5
});
createMarker('conditional-default-flow-marker', {
element: svg.path('M 1 4 L 5 16'),
attrs: {
stroke: 'black'
},
ref: { x: -5, y: 10 },
scale: 0.5
});
}
function drawCircle(p, width, height, offset, attrs) {
if (isObject(offset)) {
attrs = offset;
offset = 0;
}
offset = offset || 0;
attrs = computeStyle(attrs, {
stroke: 'black',
strokeWidth: 2,
fill: 'white'
});
var cx = width / 2,
cy = height / 2;
return p.circle(cx, cy, Math.round((width + height) / 4 - offset)).attr(attrs);
}
function drawRect(p, width, height, r, offset, attrs) {
if (isObject(offset)) {
attrs = offset;
offset = 0;
}
offset = offset || 0;
attrs = computeStyle(attrs, {
stroke: 'black',
strokeWidth: 2,
fill: 'white'
});
return p.rect(offset, offset, width - offset * 2, height - offset * 2, r).attr(attrs);
}
function drawDiamond(p, width, height, attrs) {
var x_2 = width / 2;
var y_2 = height / 2;
var points = [x_2, 0, width, y_2, x_2, height, 0, y_2 ];
attrs = computeStyle(attrs, {
stroke: 'black',
strokeWidth: 2,
fill: 'white'
});
return p.polygon(points).attr(attrs);
}
function drawLine(p, waypoints, attrs) {
attrs = computeStyle(attrs, [ 'no-fill' ], {
stroke: 'black',
strokeWidth: 2,
fill: 'none'
});
return createLine(waypoints, attrs).appendTo(p);
}
function drawPath(p, d, attrs) {
attrs = computeStyle(attrs, [ 'no-fill' ], {
strokeWidth: 2,
stroke: 'black'
});
return p.path(d).attr(attrs);
}
function drawMarker(type, p, path, attrs) {
return drawPath(p, path, assign({ 'data-marker': type }, attrs));
}
function as(type) {
return function(p, element) {
return handlers[type](p, element);
};
}
function renderer(type) {
return handlers[type];
}
function renderEventContent(element, p) {
var event = getSemantic(element);
var isThrowing = isThrowEvent(event);
if (isTypedEvent(event, 'bpmn:MessageEventDefinition')) {
return renderer('bpmn:MessageEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:TimerEventDefinition')) {
return renderer('bpmn:TimerEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:ConditionalEventDefinition')) {
return renderer('bpmn:ConditionalEventDefinition')(p, element);
}
if (isTypedEvent(event, 'bpmn:SignalEventDefinition')) {
return renderer('bpmn:SignalEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: false })) {
return renderer('bpmn:MultipleEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: true })) {
return renderer('bpmn:ParallelMultipleEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:EscalationEventDefinition')) {
return renderer('bpmn:EscalationEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:LinkEventDefinition')) {
return renderer('bpmn:LinkEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:ErrorEventDefinition')) {
return renderer('bpmn:ErrorEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:CancelEventDefinition')) {
return renderer('bpmn:CancelEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:CompensateEventDefinition')) {
return renderer('bpmn:CompensateEventDefinition')(p, element, isThrowing);
}
if (isTypedEvent(event, 'bpmn:TerminateEventDefinition')) {
return renderer('bpmn:TerminateEventDefinition')(p, element, isThrowing);
}
return null;
}
function renderLabel(p, label, options) {
return textUtil.createText(p, label || '', options).addClass('djs-label');
}
function renderEmbeddedLabel(p, element, align) {
var semantic = getSemantic(element);
return renderLabel(p, semantic.name, { box: element, align: align, padding: 5 });
}
function renderExternalLabel(p, element, align) {
var semantic = getSemantic(element);
return renderLabel(p, semantic.name, { box: element, align: align, style: { fontSize: '11px' } });
}
function renderLaneLabel(p, text, element) {
var textBox = renderLabel(p, text, {
box: { height: 30, width: element.height },
align: 'center-middle'
});
var top = -1 * element.height;
textBox.transform(
'rotate(270) ' +
'translate(' + top + ',' + 0 + ')'
);
}
function createPathFromConnection(connection) {
var waypoints = connection.waypoints;
var pathData = 'm ' + waypoints[0].x + ',' + waypoints[0].y;
for (var i = 1; i < waypoints.length; i++) {
pathData += 'L' + waypoints[i].x + ',' + waypoints[i].y + ' ';
}
return pathData;
}
var handlers = this.handlers = {
'bpmn:Event': function(p, element, attrs) {
return drawCircle(p, element.width, element.height, attrs);
},
'bpmn:StartEvent': function(p, element) {
var attrs = {};
var semantic = getSemantic(element);
if (!semantic.isInterrupting) {
attrs = {
strokeDasharray: '6',
strokeLinecap: 'round'
};
}
var circle = renderer('bpmn:Event')(p, element, attrs);
renderEventContent(element, p);
return circle;
},
'bpmn:MessageEventDefinition': function(p, element, isThrowing) {
var pathData = pathMap.getScaledPath('EVENT_MESSAGE', {
xScaleFactor: 0.9,
yScaleFactor: 0.9,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.235,
my: 0.315
}
});
var fill = isThrowing ? 'black' : 'white';
var stroke = isThrowing ? 'white' : 'black';
var messagePath = drawPath(p, pathData, {
strokeWidth: 1,
fill: fill,
stroke: stroke
});
return messagePath;
},
'bpmn:TimerEventDefinition': function(p, element) {
var circle = drawCircle(p, element.width, element.height, 0.2 * element.height, {
strokeWidth: 2
});
var pathData = pathMap.getScaledPath('EVENT_TIMER_WH', {
xScaleFactor: 0.75,
yScaleFactor: 0.75,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.5,
my: 0.5
}
});
drawPath(p, pathData, {
strokeWidth: 2,
strokeLinecap: 'square'
});
for(var i = 0;i < 12;i++) {
var linePathData = pathMap.getScaledPath('EVENT_TIMER_LINE', {
xScaleFactor: 0.75,
yScaleFactor: 0.75,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.5,
my: 0.5
}
});
var width = element.width / 2;
var height = element.height / 2;
drawPath(p, linePathData, {
strokeWidth: 1,
strokeLinecap: 'square',
transform: 'rotate(' + (i * 30) + ',' + height + ',' + width + ')'
});
}
return circle;
},
'bpmn:EscalationEventDefinition': function(p, event, isThrowing) {
var pathData = pathMap.getScaledPath('EVENT_ESCALATION', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: event.width,
containerHeight: event.height,
position: {
mx: 0.5,
my: 0.555
}
});
var fill = isThrowing ? 'black' : 'none';
return drawPath(p, pathData, {
strokeWidth: 1,
fill: fill
});
},
'bpmn:ConditionalEventDefinition': function(p, event) {
var pathData = pathMap.getScaledPath('EVENT_CONDITIONAL', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: event.width,
containerHeight: event.height,
position: {
mx: 0.5,
my: 0.222
}
});
return drawPath(p, pathData, {
strokeWidth: 1
});
},
'bpmn:LinkEventDefinition': function(p, event, isThrowing) {
var pathData = pathMap.getScaledPath('EVENT_LINK', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: event.width,
containerHeight: event.height,
position: {
mx: 0.57,
my: 0.263
}
});
var fill = isThrowing ? 'black' : 'none';
return drawPath(p, pathData, {
strokeWidth: 1,
fill: fill
});
},
'bpmn:ErrorEventDefinition': function(p, event, isThrowing) {
var pathData = pathMap.getScaledPath('EVENT_ERROR', {
xScaleFactor: 1.1,
yScaleFactor: 1.1,
containerWidth: event.width,
containerHeight: event.height,
position: {
mx: 0.2,
my: 0.722
}
});
var fill = isThrowing ? 'black' : 'none';
return drawPath(p, pathData, {
strokeWidth: 1,
fill: fill
});
},
'bpmn:CancelEventDefinition': function(p, event, isThrowing) {
var pathData = pathMap.getScaledPath('EVENT_CANCEL_45', {
xScaleFactor: 1.0,
yScaleFactor: 1.0,
containerWidth: event.width,
containerHeight: event.height,
position: {
mx: 0.638,
my: -0.055
}
});
var fill = isThrowing ? 'black' : 'none';
return drawPath(p, pathData, {
strokeWidth: 1,
fill: fill
}).transform('rotate(45)');
},
'bpmn:CompensateEventDefinition': function(p, event, isThrowing) {
var pathData = pathMap.getScaledPath('EVENT_COMPENSATION', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: event.width,
containerHeight: event.height,
position: {
mx: 0.22,
my: 0.5
}
});
var fill = isThrowing ? 'black' : 'none';
return drawPath(p, pathData, {
strokeWidth: 1,
fill: fill
});
},
'bpmn:SignalEventDefinition': function(p, event, isThrowing) {
var pathData = pathMap.getScaledPath('EVENT_SIGNAL', {
xScaleFactor: 0.9,
yScaleFactor: 0.9,
containerWidth: event.width,
containerHeight: event.height,
position: {
mx: 0.5,
my: 0.2
}
});
var fill = isThrowing ? 'black' : 'none';
return drawPath(p, pathData, {
strokeWidth: 1,
fill: fill
});
},
'bpmn:MultipleEventDefinition': function(p, event, isThrowing) {
var pathData = pathMap.getScaledPath('EVENT_MULTIPLE', {
xScaleFactor: 1.1,
yScaleFactor: 1.1,
containerWidth: event.width,
containerHeight: event.height,
position: {
mx: 0.222,
my: 0.36
}
});
var fill = isThrowing ? 'black' : 'none';
return drawPath(p, pathData, {
strokeWidth: 1,
fill: fill
});
},
'bpmn:ParallelMultipleEventDefinition': function(p, event) {
var pathData = pathMap.getScaledPath('EVENT_PARALLEL_MULTIPLE', {
xScaleFactor: 1.2,
yScaleFactor: 1.2,
containerWidth: event.width,
containerHeight: event.height,
position: {
mx: 0.458,
my: 0.194
}
});
return drawPath(p, pathData, {
strokeWidth: 1
});
},
'bpmn:EndEvent': function(p, element) {
var circle = renderer('bpmn:Event')(p, element, {
strokeWidth: 4
});
renderEventContent(element, p, true);
return circle;
},
'bpmn:TerminateEventDefinition': function(p, element) {
var circle = drawCircle(p, element.width, element.height, 8, {
strokeWidth: 4,
fill: 'black'
});
return circle;
},
'bpmn:IntermediateEvent': function(p, element) {
var outer = renderer('bpmn:Event')(p, element, { strokeWidth: 1 });
/* inner */ drawCircle(p, element.width, element.height, INNER_OUTER_DIST, { strokeWidth: 1, fill: 'none' });
renderEventContent(element, p);
return outer;
},
'bpmn:IntermediateCatchEvent': as('bpmn:IntermediateEvent'),
'bpmn:IntermediateThrowEvent': as('bpmn:IntermediateEvent'),
'bpmn:Activity': function(p, element, attrs) {
return drawRect(p, element.width, element.height, TASK_BORDER_RADIUS, attrs);
},
'bpmn:Task': function(p, element, attrs) {
var rect = renderer('bpmn:Activity')(p, element, attrs);
renderEmbeddedLabel(p, element, 'center-middle');
attachTaskMarkers(p, element);
return rect;
},
'bpmn:ServiceTask': function(p, element) {
var task = renderer('bpmn:Task')(p, element);
var pathDataBG = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
abspos: {
x: 12,
y: 18
}
});
/* service bg */ drawPath(p, pathDataBG, {
strokeWidth: 1,
fill: 'none'
});
var fillPathData = pathMap.getScaledPath('TASK_TYPE_SERVICE_FILL', {
abspos: {
x: 17.2,
y: 18
}
});
/* service fill */ drawPath(p, fillPathData, {
strokeWidth: 0,
stroke: 'none',
fill: 'white'
});
var pathData = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
abspos: {
x: 17,
y: 22
}
});
/* service */ drawPath(p, pathData, {
strokeWidth: 1,
fill: 'white'
});
return task;
},
'bpmn:UserTask': function(p, element) {
var task = renderer('bpmn:Task')(p, element);
var x = 15;
var y = 12;
var pathData = pathMap.getScaledPath('TASK_TYPE_USER_1', {
abspos: {
x: x,
y: y
}
});
/* user path */ drawPath(p, pathData, {
strokeWidth: 0.5,
fill: 'none'
});
var pathData2 = pathMap.getScaledPath('TASK_TYPE_USER_2', {
abspos: {
x: x,
y: y
}
});
/* user2 path */ drawPath(p, pathData2, {
strokeWidth: 0.5,
fill: 'none'
});
var pathData3 = pathMap.getScaledPath('TASK_TYPE_USER_3', {
abspos: {
x: x,
y: y
}
});
/* user3 path */ drawPath(p, pathData3, {
strokeWidth: 0.5,
fill: 'black'
});
return task;
},
'bpmn:ManualTask': function(p, element) {
var task = renderer('bpmn:Task')(p, element);
var pathData = pathMap.getScaledPath('TASK_TYPE_MANUAL', {
abspos: {
x: 17,
y: 15
}
});
/* manual path */ drawPath(p, pathData, {
strokeWidth: 0.25,
fill: 'white',
stroke: 'black'
});
return task;
},
'bpmn:SendTask': function(p, element) {
var task = renderer('bpmn:Task')(p, element);
var pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: 21,
containerHeight: 14,
position: {
mx: 0.285,
my: 0.357
}
});
/* send path */ drawPath(p, pathData, {
strokeWidth: 1,
fill: 'black',
stroke: 'white'
});
return task;
},
'bpmn:ReceiveTask' : function(p, element) {
var semantic = getSemantic(element);
var task = renderer('bpmn:Task')(p, element);
var pathData;
if (semantic.instantiate) {
drawCircle(p, 28, 28, 20 * 0.22, { strokeWidth: 1 });
pathData = pathMap.getScaledPath('TASK_TYPE_INSTANTIATING_SEND', {
abspos: {
x: 7.77,
y: 9.52
}
});
} else {
pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
xScaleFactor: 0.9,
yScaleFactor: 0.9,
containerWidth: 21,
containerHeight: 14,
position: {
mx: 0.3,
my: 0.4
}
});
}
/* receive path */ drawPath(p, pathData, {
strokeWidth: 1
});
return task;
},
'bpmn:ScriptTask': function(p, element) {
var task = renderer('bpmn:Task')(p, element);
var pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', {
abspos: {
x: 15,
y: 20
}
});
/* script path */ drawPath(p, pathData, {
strokeWidth: 1
});
return task;
},
'bpmn:BusinessRuleTask': function(p, element) {
var task = renderer('bpmn:Task')(p, element);
var headerPathData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_HEADER', {
abspos: {
x: 8,
y: 8
}
});
var businessHeaderPath = drawPath(p, headerPathData);
businessHeaderPath.attr({
strokeWidth: 1,
fill: 'AAA'
});
var headerData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_MAIN', {
abspos: {
x: 8,
y: 8
}
});
var businessPath = drawPath(p, headerData);
businessPath.attr({
strokeWidth: 1
});
return task;
},
'bpmn:SubProcess': function(p, element, attrs) {
attrs = assign({ fillOpacity: 0.95 }, attrs);
var rect = renderer('bpmn:Activity')(p, element, attrs);
var expanded = DiUtil.isExpanded(element);
var isEventSubProcess = DiUtil.isEventSubProcess(element);
if (isEventSubProcess) {
rect.attr({
strokeDasharray: '1,2'
});
}
renderEmbeddedLabel(p, element, expanded ? 'center-top' : 'center-middle');
if (expanded) {
attachTaskMarkers(p, element);
} else {
attachTaskMarkers(p, element, ['SubProcessMarker']);
}
return rect;
},
'bpmn:AdHocSubProcess': function(p, element) {
return renderer('bpmn:SubProcess')(p, element);
},
'bpmn:Transaction': function(p, element) {
var outer = renderer('bpmn:SubProcess')(p, element);
var innerAttrs = styles.style([ 'no-fill', 'no-events' ]);
/* inner path */ drawRect(p, element.width, element.height, TASK_BORDER_RADIUS - 2, INNER_OUTER_DIST, innerAttrs);
return outer;
},
'bpmn:CallActivity': function(p, element) {
return renderer('bpmn:SubProcess')(p, element, {
strokeWidth: 5
});
},
'bpmn:Participant': function(p, element) {
var lane = renderer('bpmn:Lane')(p, element, {
fillOpacity: 0.95,
fill: 'White'
});
var expandedPool = DiUtil.isExpanded(element);
if (expandedPool) {
drawLine(p, [
{ x: 30, y: 0 },
{ x: 30, y: element.height }
]);
var text = getSemantic(element).name;
renderLaneLabel(p, text, element);
} else {
// Collapsed pool draw text inline
var text2 = getSemantic(element).name;
renderLabel(p, text2, { box: element, align: 'center-middle' });
}
var participantMultiplicity = !!(getSemantic(element).participantMultiplicity);
if (participantMultiplicity) {
renderer('ParticipantMultiplicityMarker')(p, element);
}
return lane;
},
'bpmn:Lane': function(p, element, attrs) {
var rect = drawRect(p, element.width, element.height, 0, attrs || {
fill: 'none'
});
var semantic = getSemantic(element);
if (semantic.$type === 'bpmn:Lane') {
var text = semantic.name;
renderLaneLabel(p, text, element);
}
return rect;
},
'bpmn:InclusiveGateway': function(p, element) {
var diamond = drawDiamond(p, element.width, element.height);
/* circle path */
drawCircle(p, element.width, element.height, element.height * 0.24, {
strokeWidth: 2.5,
fill: 'none'
});
return diamond;
},
'bpmn:ExclusiveGateway': function(p, element) {
var diamond = drawDiamond(p, element.width, element.height);
var pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', {
xScaleFactor: 0.4,
yScaleFactor: 0.4,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.32,
my: 0.3
}
});
if (!!(getDi(element).isMarkerVisible)) {
drawPath(p, pathData, {
strokeWidth: 1,
fill: 'black'
});
}
return diamond;
},
'bpmn:ComplexGateway': function(p, element) {
var diamond = drawDiamond(p, element.width, element.height);
var pathData = pathMap.getScaledPath('GATEWAY_COMPLEX', {
xScaleFactor: 0.5,
yScaleFactor:0.5,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.46,
my: 0.26
}
});
/* complex path */ drawPath(p, pathData, {
strokeWidth: 1,
fill: 'black'
});
return diamond;
},
'bpmn:ParallelGateway': function(p, element) {
var diamond = drawDiamond(p, element.width, element.height);
var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
xScaleFactor: 0.6,
yScaleFactor:0.6,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.46,
my: 0.2
}
});
/* parallel path */ drawPath(p, pathData, {
strokeWidth: 1,
fill: 'black'
});
return diamond;
},
'bpmn:EventBasedGateway': function(p, element) {
var semantic = getSemantic(element);
var diamond = drawDiamond(p, element.width, element.height);
/* outer circle path */ drawCircle(p, element.width, element.height, element.height * 0.20, {
strokeWidth: 1,
fill: 'none'
});
var type = semantic.eventGatewayType;
var instantiate = !!semantic.instantiate;
function drawEvent() {
var pathData = pathMap.getScaledPath('GATEWAY_EVENT_BASED', {
xScaleFactor: 0.18,
yScaleFactor: 0.18,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.36,
my: 0.44
}
});
/* event path */ drawPath(p, pathData, {
strokeWidth: 2,
fill: 'none'
});
}
if (type === 'Parallel') {
var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
xScaleFactor: 0.4,
yScaleFactor:0.4,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.474,
my: 0.296
}
});
var parallelPath = drawPath(p, pathData);
parallelPath.attr({
strokeWidth: 1,
fill: 'none'
});
} else if (type === 'Exclusive') {
if (!instantiate) {
var innerCircle = drawCircle(p, element.width, element.height, element.height * 0.26);
innerCircle.attr({
strokeWidth: 1,
fill: 'none'
});
}
drawEvent();
}
return diamond;
},
'bpmn:Gateway': function(p, element) {
return drawDiamond(p, element.width, element.height);
},
'bpmn:SequenceFlow': function(p, element) {
var pathData = createPathFromConnection(element);
var path = drawPath(p, pathData, {
strokeLinejoin: 'round',
markerEnd: marker('sequenceflow-end')
});
var sequenceFlow = getSemantic(element);
var source = element.source.businessObject;
// conditional flow marker
if (sequenceFlow.conditionExpression && source.$instanceOf('bpmn:Activity')) {
path.attr({
markerStart: marker('conditional-flow-marker')
});
}
// default marker
if (source.default && (source.$instanceOf('bpmn:Gateway') || source.$instanceOf('bpmn:Activity')) &&
source.default === sequenceFlow) {
path.attr({
markerStart: marker('conditional-default-flow-marker')
});
}
return path;
},
'bpmn:Association': function(p, element, attrs) {
var semantic = getSemantic(element);
attrs = assign({
strokeDasharray: '0.5, 5',
strokeLinecap: 'round',
strokeLinejoin: 'round'
}, attrs || {});
if (semantic.associationDirection === 'One' ||
semantic.associationDirection === 'Both') {
attrs.markerEnd = marker('association-end');
}
if (semantic.associationDirection === 'Both') {
attrs.markerStart = marker('association-start');
}
return drawLine(p, element.waypoints, attrs);
},
'bpmn:DataInputAssociation': function(p, element) {
return renderer('bpmn:Association')(p, element, {
markerEnd: marker('association-end')
});
},
'bpmn:DataOutputAssociation': function(p, element) {
return renderer('bpmn:Association')(p, element, {
markerEnd: marker('association-end')
});
},
'bpmn:MessageFlow': function(p, element) {
var semantic = getSemantic(element),
di = getDi(element);
var pathData = createPathFromConnection(element);
var path = drawPath(p, pathData, {
markerEnd: marker('messageflow-end'),
markerStart: marker('messageflow-start'),
strokeDasharray: '10, 12',
strokeLinecap: 'round',
strokeLinejoin: 'round',
strokeWidth: '1.5px'
});
if (semantic.messageRef) {
var midPoint = path.getPointAtLength(path.getTotalLength() / 2);
var markerPathData = pathMap.getScaledPath('MESSAGE_FLOW_MARKER', {
abspos: {
x: midPoint.x,
y: midPoint.y
}
});
var messageAttrs = { strokeWidth: 1 };
if (di.messageVisibleKind === 'initiating') {
messageAttrs.fill = 'white';
messageAttrs.stroke = 'black';
} else {
messageAttrs.fill = '#888';
messageAttrs.stroke = 'white';
}
drawPath(p, markerPathData, messageAttrs);
}
return path;
},
'bpmn:DataObject': function(p, element) {
var pathData = pathMap.getScaledPath('DATA_OBJECT_PATH', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.474,
my: 0.296
}
});
var elementObject = drawPath(p, pathData, { fill: 'white' });
var semantic = getSemantic(element);
if (isCollection(semantic)) {
renderDataItemCollection(p, element);
}
return elementObject;
},
'bpmn:DataObjectReference': as('bpmn:DataObject'),
'bpmn:DataInput': function(p, element) {
var arrowPathData = pathMap.getRawPath('DATA_ARROW');
// page
var elementObject = renderer('bpmn:DataObject')(p, element);
/* input arrow path */ drawPath(p, arrowPathData, { strokeWidth: 1 });
return elementObject;
},
'bpmn:DataOutput': function(p, element) {
var arrowPathData = pathMap.getRawPath('DATA_ARROW');
// page
var elementObject = renderer('bpmn:DataObject')(p, element);
/* output arrow path */ drawPath(p, arrowPathData, {
strokeWidth: 1,
fill: 'black'
});
return elementObject;
},
'bpmn:DataStoreReference': function(p, element) {
var DATA_STORE_PATH = pathMap.getScaledPath('DATA_STORE', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0,
my: 0.133
}
});
var elementStore = drawPath(p, DATA_STORE_PATH, {
strokeWidth: 2,
fill: 'white'
});
return elementStore;
},
'bpmn:BoundaryEvent': function(p, element) {
var semantic = getSemantic(element),
cancel = semantic.cancelActivity;
var attrs = {
strokeWidth: 1
};
if (!cancel) {
attrs.strokeDasharray = '6';
attrs.strokeLinecap = 'round';
}
var outer = renderer('bpmn:Event')(p, element, attrs);
/* inner path */ drawCircle(p, element.width, element.height, INNER_OUTER_DIST, assign(attrs, { fill: 'none' }));
renderEventContent(element, p);
return outer;
},
'bpmn:Group': function(p, element) {
return drawRect(p, element.width, element.height, TASK_BORDER_RADIUS, {
strokeWidth: 1,
strokeDasharray: '8,3,1,3',
fill: 'none',
pointerEvents: 'none'
});
},
'label': function(p, element) {
return renderExternalLabel(p, element, '');
},
'bpmn:TextAnnotation': function(p, element) {
var style = {
'fill': 'none',
'stroke': 'none'
};
var textElement = drawRect(p, element.width, element.height, 0, 0, style);
var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.0,
my: 0.0
}
});
drawPath(p, textPathData);
var text = getSemantic(element).text || '';
renderLabel(p, text, { box: element, align: 'left-middle', padding: 5 });
return textElement;
},
'ParticipantMultiplicityMarker': function(p, element) {
var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: ((element.width / 2) / element.width),
my: (element.height - 15) / element.height
}
});
drawMarker('participant-multiplicity', p, markerPath);
},
'SubProcessMarker': function(p, element) {
var markerRect = drawRect(p, 14, 14, 0, {
strokeWidth: 1
});
// Process marker is placed in the middle of the box
// therefore fixed values can be used here
markerRect.transform('translate(' + (element.width / 2 - 7.5) + ',' + (element.height - 20) + ')');
var markerPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', {
xScaleFactor: 1.5,
yScaleFactor: 1.5,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: (element.width / 2 - 7.5) / element.width,
my: (element.height - 20) / element.height
}
});
drawMarker('sub-process', p, markerPath);
},
'ParallelMarker': function(p, element, position) {
var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: ((element.width / 2 + position.parallel) / element.width),
my: (element.height - 20) / element.height
}
});
drawMarker('parallel', p, markerPath);
},
'SequentialMarker': function(p, element, position) {
var markerPath = pathMap.getScaledPath('MARKER_SEQUENTIAL', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: ((element.width / 2 + position.seq) / element.width),
my: (element.height - 19) / element.height
}
});
drawMarker('sequential', p, markerPath);
},
'CompensationMarker': function(p, element, position) {
var markerMath = pathMap.getScaledPath('MARKER_COMPENSATION', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: ((element.width / 2 + position.compensation) / element.width),
my: (element.height - 13) / element.height
}
});
drawMarker('compensation', p, markerMath, { strokeWidth: 1 });
},
'LoopMarker': function(p, element, position) {
var markerPath = pathMap.getScaledPath('MARKER_LOOP', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: ((element.width / 2 + position.loop) / element.width),
my: (element.height - 7) / element.height
}
});
drawMarker('loop', p, markerPath, {
strokeWidth: 1,
fill: 'none',
strokeLinecap: 'round',
strokeMiterlimit: 0.5
});
},
'AdhocMarker': function(p, element, position) {
var markerPath = pathMap.getScaledPath('MARKER_ADHOC', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: ((element.width / 2 + position.adhoc) / element.width),
my: (element.height - 15) / element.height
}
});
drawMarker('adhoc', p, markerPath, {
strokeWidth: 1,
fill: 'black'
});
}
};
function attachTaskMarkers(p, element, taskMarkers) {
var obj = getSemantic(element);
var subprocess = includes(taskMarkers, 'SubProcessMarker');
var position;
if (subprocess) {
position = {
seq: -21,
parallel: -22,
compensation: -42,
loop: -18,
adhoc: 10
};
} else {
position = {
seq: -3,
parallel: -6,
compensation: -27,
loop: 0,
adhoc: 10
};
}
forEach(taskMarkers, function(marker) {
renderer(marker)(p, element, position);
});
if (obj.isForCompensation) {
renderer('CompensationMarker')(p, element, position);
}
if (obj.$type === 'bpmn:AdHocSubProcess') {
renderer('AdhocMarker')(p, element, position);
}
var loopCharacteristics = obj.loopCharacteristics,
isSequential = loopCharacteristics && loopCharacteristics.isSequential;
if (loopCharacteristics) {
if (isSequential === undefined) {
renderer('LoopMarker')(p, element, position);
}
if (isSequential === false) {
renderer('ParallelMarker')(p, element, position);
}
if (isSequential === true) {
renderer('SequentialMarker')(p, element, position);
}
}
}
function renderDataItemCollection(p, element) {
var yPosition = (element.height - 16) / element.height;
var pathData = pathMap.getScaledPath('DATA_OBJECT_COLLECTION_PATH', {
xScaleFactor: 1,
yScaleFactor: 1,
containerWidth: element.width,
containerHeight: element.height,
position: {
mx: 0.451,
my: yPosition
}
});
/* collection path */ drawPath(p, pathData, {
strokeWidth: 2
});
}
// hook onto canvas init event to initialize
// connection start/end markers on svg
eventBus.on('canvas.init', function(event) {
initMarkers(event.svg);
});
}
inherits(BpmnRenderer, BaseRenderer);
BpmnRenderer.$inject = [ 'eventBus', 'styles', 'pathMap' ];
module.exports = BpmnRenderer;
BpmnRenderer.prototype.canRender = function(element) {
return is(element, 'bpmn:BaseElement');
};
BpmnRenderer.prototype.drawShape = function(visuals, element) {
var type = element.type;
var h = this.handlers[type];
/* jshint -W040 */
return h(visuals, element);
};
BpmnRenderer.prototype.drawConnection = function(visuals, element) {
var type = element.type;
var h = this.handlers[type];
/* jshint -W040 */
return h(visuals, element);
};
BpmnRenderer.prototype.getShapePath = function(element) {
if (is(element, 'bpmn:Event')) {
return getCirclePath(element);
}
if (is(element, 'bpmn:Activity')) {
return getRoundRectPath(element, TASK_BORDER_RADIUS);
}
if (is(element, 'bpmn:Gateway')) {
return getDiamondPath(element);
}
return getRectPath(element);
};
///////// helper functions /////////////////////////////
/**
* Checks if eventDefinition of the given element matches with semantic type.
*
* @return {boolean} true if element is of the given semantic type
*/
function isTypedEvent(event, eventDefinitionType, filter) {
function matches(definition, filter) {
return every(filter, function(val, key) {
// we want a == conversion here, to be able to catch
// undefined == false and friends
/* jshint -W116 */
return definition[key] == val;
});
}
return some(event.eventDefinitions, function(definition) {
return definition.$type === eventDefinitionType && matches(event, filter);
});
}
function isThrowEvent(event) {
return (event.$type === 'bpmn:IntermediateThrowEvent') || (event.$type === 'bpmn:EndEvent');
}
function isCollection(element) {
return element.isCollection ||
(element.elementObjectRef && element.elementObjectRef.isCollection);
}
function getDi(element) {
return element.businessObject.di;
}
function getSemantic(element) {
return element.businessObject;
}
/////// cropping path customizations /////////////////////////
function getCirclePath(shape) {
var cx = shape.x + shape.width / 2,
cy = shape.y + shape.height / 2,
radius = shape.width / 2;
var circlePath = [
['M', cx, cy],
['m', 0, -radius],
['a', radius, radius, 0, 1, 1, 0, 2 * radius],
['a', radius, radius, 0, 1, 1, 0, -2 * radius],
['z']
];
return componentsToPath(circlePath);
}
function getRoundRectPath(shape, borderRadius) {
var x = shape.x,
y = shape.y,
width = shape.width,
height = shape.height;
var roundRectPath = [
['M', x + borderRadius, y],
['l', width - borderRadius * 2, 0],
['a', borderRadius, borderRadius, 0, 0, 1, borderRadius, borderRadius],
['l', 0, height - borderRadius * 2],
['a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, borderRadius],
['l', borderRadius * 2 - width, 0],
['a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, -borderRadius],
['l', 0, borderRadius * 2 - height],
['a', borderRadius, borderRadius, 0, 0, 1, borderRadius, -borderRadius],
['z']
];
return componentsToPath(roundRectPath);
}
function getDiamondPath(shape) {
var width = shape.width,
height = shape.height,
x = shape.x,
y = shape.y,
halfWidth = width / 2,
halfHeight = height / 2;
var diamondPath = [
['M', x + halfWidth, y],
['l', halfWidth, halfHeight],
['l', -halfWidth, halfHeight],
['l', -halfWidth, -halfHeight],
['z']
];
return componentsToPath(diamondPath);
}
function getRectPath(shape) {
var x = shape.x,
y = shape.y,
width = shape.width,
height = shape.height;
var rectPath = [
['M', x, y],
['l', width, 0],
['l', 0, height],
['l', -width, 0],
['z']
];
return componentsToPath(rectPath);
}
},{"12":12,"14":14,"201":201,"206":206,"45":45,"77":77,"78":78,"86":86,"89":89,"92":92,"94":94,"97":97}],5:[function(_dereq_,module,exports){
'use strict';
var Snap = _dereq_(85);
/**
* Map containing SVG paths needed by BpmnRenderer.
*/
function PathMap() {
/**
* Contains a map of path elements
*
* Path definition
* A parameterized path is defined like this:
*
* 'GATEWAY_PARALLEL': {
* d: 'm {mx},{my} {e.x0},0 0,{e.x1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
'-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
* height: 17.5,
* width: 17.5,
* heightElements: [2.5, 7.5],
* widthElements: [2.5, 7.5]
* }
*
* It's important to specify a correct height and width for the path as the scaling
* is based on the ratio between the specified height and width in this object and the
* height and width that is set as scale target (Note x,y coordinates will be scaled with
* individual ratios).
* The 'heightElements ' and 'widthElements ' array must contain the values that will be scaled.
* The scaling is based on the computed ratios.
* Coordinates on the y axis should be in the heightElement 's array, they will be scaled using
* the computed ratio coefficient.
* In the parameterized path the scaled values can be accessed through the 'e' object in {} brackets.
*
* The values for the y axis can be accessed in the path string using {e.y0}, {e.y1}, ....
* The values for the x axis can be accessed in the path string using {e.x0}, {e.x1}, ....
*
* The numbers x0, x1 respectively y0, y1, ... map to the corresponding array index.
*
*/
this.pathMap = {
'EVENT_MESSAGE': {
d: 'm {mx},{my} l 0,{e.y1} l {e.x1},0 l 0,-{e.y1} z l {e.x0},{e.y0} l {e.x0},-{e.y0}',
height: 36,
width: 36,
heightElements: [6, 14],
widthElements: [10.5, 21]
},
'EVENT_SIGNAL': {
d: 'M {mx},{my} l {e.x0},{e.y0} l -{e.x1},0 Z',
height: 36,
width: 36,
heightElements: [18],
widthElements: [10, 20]
},
'EVENT_ESCALATION': {
d: 'm {mx},{my} c -{e.x1},{e.y0} -{e.x3},{e.y1} -{e.x5},{e.y4} {e.x1},-{e.y3} {e.x3},-{e.y5} {e.x5},-{e.y6} ' +
'{e.x0},{e.y3} {e.x2},{e.y5} {e.x4},{e.y6} -{e.x0},-{e.y0} -{e.x2},-{e.y1} -{e.x4},-{e.y4} z',
height: 36,
width: 36,
heightElements: [2.382, 4.764, 4.926, 6.589333, 7.146, 13.178667, 19.768],
widthElements: [2.463, 2.808, 4.926, 5.616, 7.389, 8.424]
},
'EVENT_CONDITIONAL': {
d: 'M {e.x0},{e.y0} l {e.x1},0 l 0,{e.y2} l -{e.x1},0 Z ' +
'M {e.x2},{e.y3} l {e.x0},0 ' +
'M {e.x2},{e.y4} l {e.x0},0 ' +
'M {e.x2},{e.y5} l {e.x0},0 ' +
'M {e.x2},{e.y6} l {e.x0},0 ' +
'M {e.x2},{e.y7} l {e.x0},0 ' +
'M {e.x2},{e.y8} l {e.x0},0 ',
height: 36,
width: 36,
heightElements: [8.5, 14.5, 18, 11.5, 14.5, 17.5, 20.5, 23.5, 26.5],
widthElements: [10.5, 14.5, 12.5]
},
'EVENT_LINK': {
d: 'm {mx},{my} 0,{e.y0} -{e.x1},0 0,{e.y1} {e.x1},0 0,{e.y0} {e.x0},-{e.y2} -{e.x0},-{e.y2} z',
height: 36,
width: 36,
heightElements: [4.4375, 6.75, 7.8125],
widthElements: [9.84375, 13.5]
},
'EVENT_ERROR': {
d: 'm {mx},{my} {e.x0},-{e.y0} {e.x1},-{e.y1} {e.x2},{e.y2} {e.x3},-{e.y3} -{e.x4},{e.y4} -{e.x5},-{e.y5} z',
height: 36,
width: 36,
heightElements: [0.023, 8.737, 8.151, 16.564, 10.591, 8.714],
widthElements: [0.085, 6.672, 6.97, 4.273, 5.337, 6.636]
},
'EVENT_CANCEL_45': {
d: 'm {mx},{my} -{e.x1},0 0,{e.x0} {e.x1},0 0,{e.y1} {e.x0},0 ' +
'0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z',
height: 36,
width: 36,
heightElements: [4.75, 8.5],
widthElements: [4.75, 8.5]
},
'EVENT_COMPENSATION': {
d: 'm {mx},{my} {e.x0},-{e.y0} 0,{e.y1} z m {e.x1},-{e.y2} {e.x2},-{e.y3} 0,{e.y1} -{e.x2},-{e.y3} z',
height: 36,
width: 36,
heightElements: [6.5, 13, 0.4, 6.1],
widthElements: [9, 9.3, 8.7]
},
'EVENT_TIMER_WH': {
d: 'M {mx},{my} l {e.x0},-{e.y0} m -{e.x0},{e.y0} l {e.x1},{e.y1} ',
height: 36,
width: 36,
heightElements: [10, 2],
widthElements: [3, 7]
},
'EVENT_TIMER_LINE': {
d: 'M {mx},{my} ' +
'm {e.x0},{e.y0} l -{e.x1},{e.y1} ',
height: 36,
width: 36,
heightElements: [10, 3],
widthElements: [0, 0]
},
'EVENT_MULTIPLE': {
d:'m {mx},{my} {e.x1},-{e.y0} {e.x1},{e.y0} -{e.x0},{e.y1} -{e.x2},0 z',
height: 36,
width: 36,
heightElements: [6.28099, 12.56199],
widthElements: [3.1405, 9.42149, 12.56198]
},
'EVENT_PARALLEL_MULTIPLE': {
d:'m {mx},{my} {e.x0},0 0,{e.y1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
'-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
height: 36,
width: 36,
heightElements: [2.56228, 7.68683],
widthElements: [2.56228, 7.68683]
},
'GATEWAY_EXCLUSIVE': {
d:'m {mx},{my} {e.x0},{e.y0} {e.x1},{e.y0} {e.x2},0 {e.x4},{e.y2} ' +
'{e.x4},{e.y1} {e.x2},0 {e.x1},{e.y3} {e.x0},{e.y3} ' +
'{e.x3},0 {e.x5},{e.y1} {e.x5},{e.y2} {e.x3},0 z',
height: 17.5,
width: 17.5,
heightElements: [8.5, 6.5312, -6.5312, -8.5],
widthElements: [6.5, -6.5, 3, -3, 5, -5]
},
'GATEWAY_PARALLEL': {
d:'m {mx},{my} 0,{e.y1} -{e.x1},0 0,{e.y0} {e.x1},0 0,{e.y1} {e.x0},0 ' +
'0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z',
height: 30,
width: 30,
heightElements: [5, 12.5],
widthElements: [5, 12.5]
},
'GATEWAY_EVENT_BASED': {
d:'m {mx},{my} {e.x0},{e.y0} {e.x0},{e.y1} {e.x1},{e.y2} {e.x2},0 z',
height: 11,
width: 11,
heightElements: [-6, 6, 12, -12],
widthElements: [9, -3, -12]
},
'GATEWAY_COMPLEX': {
d:'m {mx},{my} 0,{e.y0} -{e.x0},-{e.y1} -{e.x1},{e.y2} {e.x0},{e.y1} -{e.x2},0 0,{e.y3} ' +
'{e.x2},0 -{e.x0},{e.y1} l {e.x1},{e.y2} {e.x0},-{e.y1} 0,{e.y0} {e.x3},0 0,-{e.y0} {e.x0},{e.y1} ' +
'{e.x1},-{e.y2} -{e.x0},-{e.y1} {e.x2},0 0,-{e.y3} -{e.x2},0 {e.x0},-{e.y1} -{e.x1},-{e.y2} ' +
'-{e.x0},{e.y1} 0,-{e.y0} -{e.x3},0 z',
height: 17.125,
width: 17.125,
heightElements: [4.875, 3.4375, 2.125, 3],
widthElements: [3.4375, 2.125, 4.875, 3]
},
'DATA_OBJECT_PATH': {
d:'m 0,0 {e.x1},0 {e.x0},{e.y0} 0,{e.y1} -{e.x2},0 0,-{e.y2} {e.x1},0 0,{e.y0} {e.x0},0',
height: 61,
width: 51,
heightElements: [10, 50, 60],
widthElements: [10, 40, 50, 60]
},
'DATA_OBJECT_COLLECTION_PATH': {
d:'m {mx}, {my} ' +
'm 0 15 l 0 -15 ' +
'm 4 15 l 0 -15 ' +
'm 4 15 l 0 -15 ',
height: 61,
width: 51,
heightElements: [12],
widthElements: [1, 6, 12, 15]
},
'DATA_ARROW': {
d:'m 5,9 9,0 0,-3 5,5 -5,5 0,-3 -9,0 z',
height: 61,
width: 51,
heightElements: [],
widthElements: []
},
'DATA_STORE': {
d:'m {mx},{my} ' +
'l 0,{e.y2} ' +
'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0 ' +
'l 0,-{e.y2} ' +
'c -{e.x0},-{e.y1} -{e.x1},-{e.y1} -{e.x2},0' +
'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0 ' +
'm -{e.x2},{e.y0}' +
'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0' +
'm -{e.x2},{e.y0}' +
'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0',
height: 61,
width: 61,
heightElements: [7, 10, 45],
widthElements: [2, 58, 60]
},
'TEXT_ANNOTATION': {
d: 'm {mx}, {my} m 10,0 l -10,0 l 0,{e.y0} l 10,0',
height: 30,
width: 10,
heightElements: [30],
widthElements: [10]
},
'MARKER_SUB_PROCESS': {
d: 'm{mx},{my} m 7,2 l 0,10 m -5,-5 l 10,0',
height: 10,
width: 10,
heightElements: [],
widthElements: []
},
'MARKER_PARALLEL': {
d: 'm{mx},{my} m 3,2 l 0,10 m 3,-10 l 0,10 m 3,-10 l 0,10',
height: 10,
width: 10,
heightElements: [],
widthElements: []
},
'MARKER_SEQUENTIAL': {
d: 'm{mx},{my} m 0,3 l 10,0 m -10,3 l 10,0 m -10,3 l 10,0',
height: 10,
width: 10,
heightElements: [],
widthElements: []
},
'MARKER_COMPENSATION': {
d: 'm {mx},{my} 7,-5 0,10 z m 7.1,-0.3 6.9,-4.7 0,10 -6.9,-4.7 z',
height: 10,
width: 21,
heightElements: [],
widthElements: []
},
'MARKER_LOOP': {
d: 'm {mx},{my} c 3.526979,0 6.386161,-2.829858 6.386161,-6.320661 0,-3.490806 -2.859182,-6.320661 ' +
'-6.386161,-6.320661 -3.526978,0 -6.38616,2.829855 -6.38616,6.320661 0,1.745402 ' +
'0.714797,3.325567 1.870463,4.469381 0.577834,0.571908 1.265885,1.034728 2.029916,1.35457 ' +
'l -0.718163,-3.909793 m 0.718163,3.909793 -3.885211,0.802902',
height: 13.9,
width: 13.7,
heightElements: [],
widthElements: []
},
'MARKER_ADHOC': {
d: 'm {mx},{my} m 0.84461,2.64411 c 1.05533,-1.23780996 2.64337,-2.07882 4.29653,-1.97997996 2.05163,0.0805 ' +
'3.85579,1.15803 5.76082,1.79107 1.06385,0.34139996 2.24454,0.1438 3.18759,-0.43767 0.61743,-0.33642 ' +
'1.2775,-0.64078 1.7542,-1.17511 0,0.56023 0,1.12046 0,1.6807 -0.98706,0.96237996 -2.29792,1.62393996 ' +
'-3.6918,1.66181996 -1.24459,0.0927 -2.46671,-0.2491 -3.59505,-0.74812 -1.35789,-0.55965 ' +
'-2.75133,-1.33436996 -4.27027,-1.18121996 -1.37741,0.14601 -2.41842,1.13685996 -3.44288,1.96782996 z',
height: 4,
width: 15,
heightElements: [],
widthElements: []
},
'TASK_TYPE_SEND': {
d: 'm {mx},{my} l 0,{e.y1} l {e.x1},0 l 0,-{e.y1} z l {e.x0},{e.y0} l {e.x0},-{e.y0}',
height: 14,
width: 21,
heightElements: [6, 14],
widthElements: [10.5, 21]
},
'TASK_TYPE_SCRIPT': {
d: 'm {mx},{my} c 9.966553,-6.27276 -8.000926,-7.91932 2.968968,-14.938 l -8.802728,0 ' +
'c -10.969894,7.01868 6.997585,8.66524 -2.968967,14.938 z ' +
'm -7,-12 l 5,0 ' +
'm -4.5,3 l 4.5,0 ' +
'm -3,3 l 5,0' +
'm -4,3 l 5,0',
height: 15,
width: 12.6,
heightElements: [6, 14],
widthElements: [10.5, 21]
},
'TASK_TYPE_USER_1': {
d: 'm {mx},{my} c 0.909,-0.845 1.594,-2.049 1.594,-3.385 0,-2.554 -1.805,-4.62199999 ' +
'-4.357,-4.62199999 -2.55199998,0 -4.28799998,2.06799999 -4.28799998,4.62199999 0,1.348 ' +
'0.974,2.562 1.89599998,3.405 -0.52899998,0.187 -5.669,2.097 -5.794,4.7560005 v 6.718 ' +
'h 17 v -6.718 c 0,-2.2980005 -5.5279996,-4.5950005 -6.0509996,-4.7760005 z' +
'm -8,6 l 0,5.5 m 11,0 l 0,-5'
},
'TASK_TYPE_USER_2': {
d: 'm {mx},{my} m 2.162,1.009 c 0,2.4470005 -2.158,4.4310005 -4.821,4.4310005 ' +
'-2.66499998,0 -4.822,-1.981 -4.822,-4.4310005 '
},
'TASK_TYPE_USER_3': {
d: 'm {mx},{my} m -6.9,-3.80 c 0,0 2.25099998,-2.358 4.27399998,-1.177 2.024,1.181 4.221,1.537 ' +
'4.124,0.965 -0.098,-0.57 -0.117,-3.79099999 -4.191,-4.13599999 -3.57499998,0.001 ' +
'-4.20799998,3.36699999 -4.20699998,4.34799999 z'
},
'TASK_TYPE_MANUAL': {
d: 'm {mx},{my} c 0.234,-0.01 5.604,0.008 8.029,0.004 0.808,0 1.271,-0.172 1.417,-0.752 0.227,-0.898 ' +
'-0.334,-1.314 -1.338,-1.316 -2.467,-0.01 -7.886,-0.004 -8.108,-0.004 -0.014,-0.079 0.016,-0.533 0,-0.61 ' +
'0.195,-0.042 8.507,0.006 9.616,0.002 0.877,-0.007 1.35,-0.438 1.353,-1.208 0.003,-0.768 -0.479,-1.09 ' +
'-1.35,-1.091 -2.968,-0.002 -9.619,-0.013 -9.619,-0.013 v -0.591 c 0,0 5.052,-0.016 7.225,-0.016 ' +
'0.888,-0.002 1.354,-0.416 1.351,-1.193 -0.006,-0.761 -0.492,-1.196 -1.361,-1.196 -3.473,-0.005 ' +
'-10.86,-0.003 -11.0829995,-0.003 -0.022,-0.047 -0.045,-0.094 -0.069,-0.139 0.3939995,-0.319 ' +
'2.0409995,-1.626 2.4149995,-2.017 0.469,-0.4870005 0.519,-1.1650005 0.162,-1.6040005 -0.414,-0.511 ' +
'-0.973,-0.5 -1.48,-0.236 -1.4609995,0.764 -6.5999995,3.6430005 -7.7329995,4.2710005 -0.9,0.499 ' +
'-1.516,1.253 -1.882,2.19 -0.37000002,0.95 -0.17,2.01 -0.166,2.979 0.004,0.718 -0.27300002,1.345 ' +
'-0.055,2.063 0.629,2.087 2.425,3.312 4.859,3.318 4.6179995,0.014 9.2379995,-0.139 13.8569995,-0.158 ' +
'0.755,-0.004 1.171,-0.301 1.182,-1.033 0.012,-0.754 -0.423,-0.969 -1.183,-0.973 -1.778,-0.01 ' +
'-5.824,-0.004 -6.04,-0.004 10e-4,-0.084 0.003,-0.586 10e-4,-0.67 z'
},
'TASK_TYPE_INSTANTIATING_SEND': {
d: 'm {mx},{my} l 0,8.4 l 12.6,0 l 0,-8.4 z l 6.3,3.6 l 6.3,-3.6'
},
'TASK_TYPE_SERVICE': {
d: 'm {mx},{my} v -1.71335 c 0.352326,-0.0705 0.703932,-0.17838 1.047628,-0.32133 ' +
'0.344416,-0.14465 0.665822,-0.32133 0.966377,-0.52145 l 1.19431,1.18005 1.567487,-1.57688 ' +
'-1.195028,-1.18014 c 0.403376,-0.61394 0.683079,-1.29908 0.825447,-2.01824 l 1.622133,-0.01 ' +
'v -2.2196 l -1.636514,0.01 c -0.07333,-0.35153 -0.178319,-0.70024 -0.323564,-1.04372 ' +
'-0.145244,-0.34406 -0.321407,-0.6644 -0.522735,-0.96217 l 1.131035,-1.13631 -1.583305,-1.56293 ' +
'-1.129598,1.13589 c -0.614052,-0.40108 -1.302883,-0.68093 -2.022633,-0.82247 l 0.0093,-1.61852 ' +
'h -2.241173 l 0.0042,1.63124 c -0.353763,0.0736 -0.705369,0.17977 -1.049785,0.32371 -0.344415,0.14437 ' +
'-0.665102,0.32092 -0.9635006,0.52046 l -1.1698628,-1.15823 -1.5667691,1.5792 1.1684265,1.15669 ' +
'c -0.4026573,0.61283 -0.68308,1.29797 -0.8247287,2.01713 l -1.6588041,0.003 v 2.22174 ' +
'l 1.6724648,-0.006 c 0.073327,0.35077 0.1797598,0.70243 0.3242851,1.04472 0.1452428,0.34448 ' +
'0.3214064,0.6644 0.5227339,0.96066 l -1.1993431,1.19723 1.5840256,1.56011 1.1964668,-1.19348 ' +
'c 0.6140517,0.40346 1.3028827,0.68232 2.0233517,0.82331 l 7.19e-4,1.69892 h 2.226848 z ' +
'm 0.221462,-3.9957 c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' +
'0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' +
'0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z'
},
'TASK_TYPE_SERVICE_FILL': {
d: 'm {mx},{my} c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' +
'0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' +
'0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z'
},
'TASK_TYPE_BUSINESS_RULE_HEADER': {
d: 'm {mx},{my} 0,4 20,0 0,-4 z'
},
'TASK_TYPE_BUSINESS_RULE_MAIN': {
d: 'm {mx},{my} 0,12 20,0 0,-12 z' +
'm 0,8 l 20,0 ' +
'm -13,-4 l 0,8'
},
'MESSAGE_FLOW_MARKER': {
d: 'm {mx},{my} m -10.5 ,-7 l 0,14 l 21,0 l 0,-14 z l 10.5,6 l 10.5,-6'
}
};
this.getRawPath = function getRawPath(pathId) {
return this.pathMap[pathId].d;
};
/**
* Scales the path to the given height and width.
* Use case
* Use case is to scale the content of elements (event, gateways) based
* on the element bounding box's size.
*
* Why not transform
* Scaling a path with transform() will also scale the stroke and IE does not support
* the option 'non-scaling-stroke' to prevent this.
* Also there are use cases where only some parts of a path should be
* scaled.
*
* @param {String} pathId The ID of the path.
* @param {Object} param
* Example param object scales the path to 60% size of the container (data.width, data.height).
*
* {
* xScaleFactor: 0.6,
* yScaleFactor:0.6,
* containerWidth: data.width,
* containerHeight: data.height,
* position: {
* mx: 0.46,
* my: 0.2,
* }
* }
*
*
* targetpathwidth = xScaleFactor * containerWidth
* targetpathheight = yScaleFactor * containerHeight
* Position is used to set the starting coordinate of the path. M is computed:
*
* position.x * containerWidth
* position.y * containerHeight
*
* Center of the container position: {
* mx: 0.5,
* my: 0.5,
* }
* Upper left corner of the container
* position: {
* mx: 0.0,
* my: 0.0,
* }
*
*
*
*
*/
this.getScaledPath = function getScaledPath(pathId, param) {
var rawPath = this.pathMap[pathId];
// positioning
// compute the start point of the path
var mx, my;
if(!!param.abspos) {
mx = param.abspos.x;
my = param.abspos.y;
} else {
mx = param.containerWidth * param.position.mx;
my = param.containerHeight * param.position.my;
}
var coordinates = {}; //map for the scaled coordinates
if(param.position) {
// path
var heightRatio = (param.containerHeight / rawPath.height) * param.yScaleFactor;
var widthRatio = (param.containerWidth / rawPath.width) * param.xScaleFactor;
//Apply height ratio
for (var heightIndex = 0; heightIndex < rawPath.heightElements.length; heightIndex++) {
coordinates['y' + heightIndex] = rawPath.heightElements[heightIndex] * heightRatio;
}
//Apply width ratio
for (var widthIndex = 0; widthIndex < rawPath.widthElements.length; widthIndex++) {
coordinates['x' + widthIndex] = rawPath.widthElements[widthIndex] * widthRatio;
}
}
//Apply value to raw path
var path = Snap.format(
rawPath.d, {
mx: mx,
my: my,
e: coordinates
}
);
return path;
};
}
module.exports = PathMap;
},{"85":85}],6:[function(_dereq_,module,exports){
module.exports = {
__init__: [ 'bpmnRenderer' ],
bpmnRenderer: [ 'type', _dereq_(4) ],
pathMap: [ 'type', _dereq_(5) ]
};
},{"4":4,"5":5}],7:[function(_dereq_,module,exports){
'use strict';
var assign = _dereq_(206),
map = _dereq_(95);
var LabelUtil = _dereq_(13);
var is = _dereq_(14).is;
var hasExternalLabel = LabelUtil.hasExternalLabel,
getExternalLabelBounds = LabelUtil.getExternalLabelBounds,
isExpanded = _dereq_(12).isExpanded,
elementToString = _dereq_(10).elementToString;
function elementData(semantic, attrs) {
return assign({
id: semantic.id,
type: semantic.$type,
businessObject: semantic
}, attrs);
}
function collectWaypoints(waypoints) {
return map(waypoints, function(p) {
return { x: p.x, y: p.y };
});
}
function notYetDrawn(translate, semantic, refSemantic, property) {
return new Error(translate('element {element} referenced by {referenced}#{property} not yet drawn', {
element: elementToString(refSemantic),
referenced: elementToString(semantic),
property: property
}));
}
/**
* An importer that adds bpmn elements to the canvas
*
* @param {EventBus} eventBus
* @param {Canvas} canvas
* @param {ElementFactory} elementFactory
* @param {ElementRegistry} elementRegistry
*/
function BpmnImporter(eventBus, canvas, elementFactory, elementRegistry, translate) {
this._eventBus = eventBus;
this._canvas = canvas;
this._elementFactory = elementFactory;
this._elementRegistry = elementRegistry;
this._translate = translate;
}
BpmnImporter.$inject = [ 'eventBus', 'canvas', 'elementFactory', 'elementRegistry', 'translate' ];
module.exports = BpmnImporter;
/**
* Add bpmn element (semantic) to the canvas onto the
* specified parent shape.
*/
BpmnImporter.prototype.add = function(semantic, parentElement) {
var di = semantic.di,
element,
translate = this._translate;
// ROOT ELEMENT
// handle the special case that we deal with a
// invisible root element (process or collaboration)
if (is(di, 'bpmndi:BPMNPlane')) {
// add a virtual element (not being drawn)
element = this._elementFactory.createRoot(elementData(semantic));
this._canvas.setRootElement(element);
}
// SHAPE
else if (is(di, 'bpmndi:BPMNShape')) {
var collapsed = !isExpanded(semantic);
var hidden = parentElement && (parentElement.hidden || parentElement.collapsed);
var bounds = semantic.di.bounds;
element = this._elementFactory.createShape(elementData(semantic, {
collapsed: collapsed,
hidden: hidden,
x: Math.round(bounds.x),
y: Math.round(bounds.y),
width: Math.round(bounds.width),
height: Math.round(bounds.height)
}));
if (is(semantic, 'bpmn:BoundaryEvent')) {
this._attachBoundary(semantic, element);
}
this._canvas.addShape(element, parentElement);
}
// CONNECTION
else if (is(di, 'bpmndi:BPMNEdge')) {
var source = this._getSource(semantic),
target = this._getTarget(semantic);
element = this._elementFactory.createConnection(elementData(semantic, {
source: source,
target: target,
waypoints: collectWaypoints(semantic.di.waypoint)
}));
this._canvas.addConnection(element, parentElement);
} else {
throw new Error(translate('unknown di {di} for element {semantic}', {
di: elementToString(di),
semantic: elementToString(semantic)
}));
}
// (optional) LABEL
if (hasExternalLabel(semantic)) {
this.addLabel(semantic, element);
}
this._eventBus.fire('bpmnElement.added', { element: element });
return element;
};
/**
* Attach the boundary element to the given host
*
* @param {ModdleElement} boundarySemantic
* @param {djs.model.Base} boundaryElement
*/
BpmnImporter.prototype._attachBoundary = function(boundarySemantic, boundaryElement) {
var translate = this._translate;
var hostSemantic = boundarySemantic.attachedToRef;
if (!hostSemantic) {
throw new Error(translate('missing {semantic}#attachedToRef', {
semantic: elementToString(boundarySemantic)
}));
}
var host = this._elementRegistry.get(hostSemantic.id),
attachers = host && host.attachers;
if (!host) {
throw notYetDrawn(translate, boundarySemantic, hostSemantic, 'attachedToRef');
}
// wire element.host <> host.attachers
boundaryElement.host = host;
if (!attachers) {
host.attachers = attachers = [];
}
if (attachers.indexOf(boundaryElement) === -1) {
attachers.push(boundaryElement);
}
};
/**
* add label for an element
*/
BpmnImporter.prototype.addLabel = function(semantic, element) {
var bounds = getExternalLabelBounds(semantic, element);
var label = this._elementFactory.createLabel(elementData(semantic, {
id: semantic.id + '_label',
labelTarget: element,
type: 'label',
hidden: element.hidden || !semantic.name,
x: Math.round(bounds.x),
y: Math.round(bounds.y),
width: Math.round(bounds.width),
height: Math.round(bounds.height)
}));
return this._canvas.addShape(label, element.parent);
};
/**
* Return the drawn connection end based on the given side.
*
* @throws {Error} if the end is not yet drawn
*/
BpmnImporter.prototype._getEnd = function(semantic, side) {
var element,
refSemantic,
type = semantic.$type,
translate = this._translate;
refSemantic = semantic[side + 'Ref'];
// handle mysterious isMany DataAssociation#sourceRef
if (side === 'source' && type === 'bpmn:DataInputAssociation') {
refSemantic = refSemantic && refSemantic[0];
}
// fix source / target for DataInputAssociation / DataOutputAssociation
if (side === 'source' && type === 'bpmn:DataOutputAssociation' ||
side === 'target' && type === 'bpmn:DataInputAssociation') {
refSemantic = semantic.$parent;
}
element = refSemantic && this._getElement(refSemantic);
if (element) {
return element;
}
if (refSemantic) {
throw notYetDrawn(translate, semantic, refSemantic, side + 'Ref');
} else {
throw new Error(translate('{semantic}#{side} Ref not specified', {
semantic: elementToString(semantic),
side: side
}));
}
};
BpmnImporter.prototype._getSource = function(semantic) {
return this._getEnd(semantic, 'source');
};
BpmnImporter.prototype._getTarget = function(semantic) {
return this._getEnd(semantic, 'target');
};
BpmnImporter.prototype._getElement = function(semantic) {
return this._elementRegistry.get(semantic.id);
};
},{"10":10,"12":12,"13":13,"14":14,"206":206,"95":95}],8:[function(_dereq_,module,exports){
'use strict';
var filter = _dereq_(90),
find = _dereq_(91),
forEach = _dereq_(92);
var Refs = _dereq_(232);
var elementToString = _dereq_(10).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
* correctly specify one.
*/
function findDisplayCandidate(definitions) {
return find(definitions.rootElements, function(e) {
return is(e, 'bpmn:Process') || is(e, 'bpmn:Collaboration');
});
}
function BpmnTreeWalker(handler, translate) {
// list of containers already walked
var handledElements = {};
// list of elements to handle deferred to ensure
// prerequisites are drawn
var deferred = [];
///// Helpers /////////////////////////////////
function contextual(fn, ctx) {
return function(e) {
fn(e, ctx);
};
}
function handled(element) {
handledElements[element.id] = element;
}
function isHandled(element) {
return handledElements[element.id];
}
function visit(element, ctx) {
var gfx = element.gfx;
// avoid multiple rendering of elements
if (gfx) {
throw new Error(
translate('already rendered {element}', { element: elementToString(element) })
);
}
// call handler
return handler.element(element, ctx);
}
function visitRoot(element, diagram) {
return handler.root(element, diagram);
}
function visitIfDi(element, ctx) {
try {
var gfx = element.di && visit(element, ctx);
handled(element);
return gfx;
} catch (e) {
logError(e.message, { element: element, error: e });
console.error(translate('failed to import {element}', { element: elementToString(element) }));
console.error(e);
}
}
function logError(message, context) {
handler.error(message, context);
}
////// DI handling ////////////////////////////
function registerDi(di) {
var bpmnElement = di.bpmnElement;
if (bpmnElement) {
if (bpmnElement.di) {
logError(
translate('multiple DI elements defined for {element}', {
element: elementToString(bpmnElement)
}),
{ element: bpmnElement }
);
} else {
diRefs.bind(bpmnElement, 'di');
bpmnElement.di = di;
}
} else {
logError(
translate('no bpmnElement referenced in {element}', {
element: elementToString(di)
}),
{ element: di }
);
}
}
function handleDiagram(diagram) {
handlePlane(diagram.plane);
}
function handlePlane(plane) {
registerDi(plane);
forEach(plane.planeElement, handlePlaneElement);
}
function handlePlaneElement(planeElement) {
registerDi(planeElement);
}
////// Semantic handling //////////////////////
/**
* Handle definitions and return the rendered diagram (if any)
*
* @param {ModdleElement} definitions to walk and import
* @param {ModdleElement} [diagram] specific diagram to import and display
*
* @throws {Error} if no diagram to display could be found
*/
function handleDefinitions(definitions, diagram) {
// make sure we walk the correct bpmnElement
var diagrams = definitions.diagrams;
if (diagram && diagrams.indexOf(diagram) === -1) {
throw new Error(translate('diagram not part of bpmn:Definitions'));
}
if (!diagram && diagrams && diagrams.length) {
diagram = diagrams[0];
}
// no diagram -> nothing to import
if (!diagram) {
throw new Error(translate('no diagram to display'));
}
// load DI from selected diagram only
handleDiagram(diagram);
var plane = diagram.plane;
if (!plane) {
throw new Error(translate(
'no plane for {element}',
{ element: 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) {
rootElement = findDisplayCandidate(definitions);
if (!rootElement) {
throw new Error(translate('no process or collaboration to display'));
} else {
logError(
translate('correcting missing bpmnElement on {plane} to {rootElement}', {
plane: elementToString(plane),
rootElement: elementToString(rootElement)
})
);
// correct DI on the fly
plane.bpmnElement = rootElement;
registerDi(plane);
}
}
var ctx = visitRoot(rootElement, plane);
if (is(rootElement, 'bpmn:Process')) {
handleProcess(rootElement, ctx);
} else if (is(rootElement, 'bpmn:Collaboration')) {
handleCollaboration(rootElement, ctx);
// force drawing of everything not yet drawn that is part of the target DI
handleUnhandledProcesses(definitions.rootElements, ctx);
} else {
throw new Error(
translate('unsupported bpmnElement for {plane}: {rootElement}', {
plane: elementToString(plane),
rootElement: elementToString(rootElement)
})
);
}
// handle all deferred elements
handleDeferred(deferred);
}
function handleDeferred(deferred) {
forEach(deferred, function(d) { d(); });
}
function handleProcess(process, context) {
handleFlowElementsContainer(process, context);
handleIoSpecification(process.ioSpecification, context);
handleArtifacts(process.artifacts, context);
// log process handled
handled(process);
}
function handleUnhandledProcesses(rootElements) {
// walk through all processes that have not yet been drawn and draw them
// 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) {
return !isHandled(e) && is(e, 'bpmn:Process') && e.laneSets;
});
processes.forEach(contextual(handleProcess));
}
function handleMessageFlow(messageFlow, context) {
visitIfDi(messageFlow, context);
}
function handleMessageFlows(messageFlows, context) {
forEach(messageFlows, contextual(handleMessageFlow, context));
}
function handleDataAssociation(association, context) {
visitIfDi(association, context);
}
function handleDataInput(dataInput, context) {
visitIfDi(dataInput, context);
}
function handleDataOutput(dataOutput, context) {
visitIfDi(dataOutput, context);
}
function handleArtifact(artifact, context) {
// bpmn:TextAnnotation
// bpmn:Group
// bpmn:Association
visitIfDi(artifact, context);
}
function handleArtifacts(artifacts, context) {
forEach(artifacts, function(e) {
if (is(e, 'bpmn:Association')) {
deferred.push(function() {
handleArtifact(e, context);
});
} else {
handleArtifact(e, context);
}
});
}
function handleIoSpecification(ioSpecification, context) {
if (!ioSpecification) {
return;
}
forEach(ioSpecification.dataInputs, contextual(handleDataInput, context));
forEach(ioSpecification.dataOutputs, contextual(handleDataOutput, context));
}
function handleSubProcess(subProcess, context) {
handleFlowElementsContainer(subProcess, context);
handleArtifacts(subProcess.artifacts, context);
}
function handleFlowNode(flowNode, context) {
var childCtx = visitIfDi(flowNode, context);
if (is(flowNode, 'bpmn:SubProcess')) {
handleSubProcess(flowNode, childCtx || context);
}
if (is(flowNode, 'bpmn:Activity')) {
handleIoSpecification(flowNode.ioSpecification, context);
}
// defer handling of associations
// affected types:
//
// * bpmn:Activity
// * bpmn:ThrowEvent
// * bpmn:CatchEvent
//
deferred.push(function() {
forEach(flowNode.dataInputAssociations, contextual(handleDataAssociation, context));
forEach(flowNode.dataOutputAssociations, contextual(handleDataAssociation, context));
});
}
function handleSequenceFlow(sequenceFlow, context) {
visitIfDi(sequenceFlow, context);
}
function handleDataElement(dataObject, context) {
visitIfDi(dataObject, context);
}
function handleBoundaryEvent(dataObject, context) {
visitIfDi(dataObject, context);
}
function handleLane(lane, context) {
var newContext = visitIfDi(lane, context);
if (lane.childLaneSet) {
handleLaneSet(lane.childLaneSet, newContext || context);
}
wireFlowNodeRefs(lane);
}
function handleLaneSet(laneSet, context) {
forEach(laneSet.lanes, contextual(handleLane, context));
}
function handleLaneSets(laneSets, context) {
forEach(laneSets, contextual(handleLaneSet, context));
}
function handleFlowElementsContainer(container, context) {
if (container.laneSets) {
handleLaneSets(container.laneSets, context);
}
handleFlowElements(container.flowElements, context);
}
function handleFlowElements(flowElements, context) {
forEach(flowElements, function(e) {
if (is(e, 'bpmn:SequenceFlow')) {
deferred.push(function() {
handleSequenceFlow(e, context);
});
} else if (is(e, 'bpmn:BoundaryEvent')) {
deferred.unshift(function() {
handleBoundaryEvent(e, context);
});
} else if (is(e, 'bpmn:FlowNode')) {
handleFlowNode(e, context);
} else if (is(e, 'bpmn:DataObject')) {
// SKIP (assume correct referencing via DataObjectReference)
} else if (is(e, 'bpmn:DataStoreReference')) {
handleDataElement(e, context);
} else if (is(e, 'bpmn:DataObjectReference')) {
handleDataElement(e, context);
} else {
logError(
translate('unrecognized flowElement {element} in context {context}', {
element: elementToString(e),
context: (context ? elementToString(context.businessObject) : 'null')
}),
{ element: e, context: context }
);
}
});
}
function handleParticipant(participant, context) {
var newCtx = visitIfDi(participant, context);
var process = participant.processRef;
if (process) {
handleProcess(process, newCtx || context);
}
}
function handleCollaboration(collaboration) {
forEach(collaboration.participants, contextual(handleParticipant));
handleArtifacts(collaboration.artifacts);
// handle message flows latest in the process
deferred.push(function() {
handleMessageFlows(collaboration.messageFlows);
});
}
function wireFlowNodeRefs(lane) {
// wire the virtual flowNodeRefs <-> relationship
forEach(lane.flowNodeRef, function(flowNode) {
var lanes = flowNode.get('lanes');
if (lanes) {
lanes.push(lane);
}
});
}
///// API ////////////////////////////////
return {
handleDefinitions: handleDefinitions
};
}
module.exports = BpmnTreeWalker;
},{"10":10,"232":232,"90":90,"91":91,"92":92}],9:[function(_dereq_,module,exports){
'use strict';
var BpmnTreeWalker = _dereq_(8);
/**
* Import the definitions into a diagram.
*
* Errors and warnings are reported through the specified callback.
*
* @param {Diagram} diagram
* @param {ModdleElement} definitions
* @param {Function} done the callback, invoked with (err, [ warning ]) once the import is done
*/
function importBpmnDiagram(diagram, definitions, done) {
var importer = diagram.get('bpmnImporter'),
eventBus = diagram.get('eventBus'),
translate = diagram.get('translate');
var error,
warnings = [];
/**
* Walk the diagram semantically, importing (=drawing)
* all elements you encounter.
*
* @param {ModdleElement} definitions
*/
function render(definitions) {
var visitor = {
root: function(element) {
return importer.add(element);
},
element: function(element, parentShape) {
return importer.add(element, parentShape);
},
error: function(message, context) {
warnings.push({ message: message, context: context });
}
};
var walker = new BpmnTreeWalker(visitor, translate);
// traverse BPMN 2.0 document model,
// starting at definitions
walker.handleDefinitions(definitions);
}
eventBus.fire('import.render.start', { definitions: definitions });
try {
render(definitions);
} catch (e) {
error = e;
}
eventBus.fire('import.render.complete', {
error: error,
warnings: warnings
});
done(error, warnings);
}
module.exports.importBpmnDiagram = importBpmnDiagram;
},{"8":8}],10:[function(_dereq_,module,exports){
'use strict';
module.exports.elementToString = function(e) {
if (!e) {
return '';
}
return '<' + e.$type + (e.id ? ' id="' + e.id : '') + '" />';
};
},{}],11:[function(_dereq_,module,exports){
module.exports = {
__depends__: [
_dereq_(59)
],
bpmnImporter: [ 'type', _dereq_(7) ]
};
},{"59":59,"7":7}],12:[function(_dereq_,module,exports){
'use strict';
var is = _dereq_(14).is,
getBusinessObject = _dereq_(14).getBusinessObject;
module.exports.isExpanded = function(element) {
if (is(element, 'bpmn:CallActivity')) {
return false;
}
if (is(element, 'bpmn:SubProcess')) {
return !!getBusinessObject(element).di.isExpanded;
}
if (is(element, 'bpmn:Participant')) {
return !!getBusinessObject(element).processRef;
}
return true;
};
module.exports.isInterrupting = function(element) {
return element && getBusinessObject(element).isInterrupting !== false;
};
module.exports.isEventSubProcess = function(element) {
return element && !!getBusinessObject(element).triggeredByEvent;
};
},{"14":14}],13:[function(_dereq_,module,exports){
'use strict';
var assign = _dereq_(206);
var is = _dereq_(14).is;
var DEFAULT_LABEL_SIZE = module.exports.DEFAULT_LABEL_SIZE = {
width: 90,
height: 20
};
/**
* Returns true if the given semantic has an external label
*
* @param {BpmnElement} semantic
* @return {Boolean} true if has label
*/
module.exports.hasExternalLabel = function(semantic) {
return is(semantic, 'bpmn:Event') ||
is(semantic, 'bpmn:Gateway') ||
is(semantic, 'bpmn:DataStoreReference') ||
is(semantic, 'bpmn:DataObjectReference') ||
is(semantic, 'bpmn:SequenceFlow') ||
is(semantic, 'bpmn:MessageFlow');
};
/**
* Get the middle of a number of waypoints
*
* @param {Array} waypoints
* @return {Point} the mid point
*/
function getWaypointsMid(waypoints) {
var mid = waypoints.length / 2 - 1;
var first = waypoints[Math.floor(mid)];
var second = waypoints[Math.ceil(mid + 0.01)];
return {
x: first.x + (second.x - first.x) / 2,
y: first.y + (second.y - first.y) / 2
};
}
module.exports.getWaypointsMid = getWaypointsMid;
function getExternalLabelMid(element) {
if (element.waypoints) {
return getWaypointsMid(element.waypoints);
} else {
return {
x: element.x + element.width / 2,
y: element.y + element.height + DEFAULT_LABEL_SIZE.height / 2
};
}
}
module.exports.getExternalLabelMid = getExternalLabelMid;
/**
* Returns the bounds of an elements label, parsed from the elements DI or
* generated from its bounds.
*
* @param {BpmnElement} semantic
* @param {djs.model.Base} element
*/
module.exports.getExternalLabelBounds = function(semantic, element) {
var mid,
size,
bounds,
di = semantic.di,
label = di.label;
if (label && label.bounds) {
bounds = label.bounds;
size = {
width: Math.max(DEFAULT_LABEL_SIZE.width, bounds.width),
height: bounds.height
};
mid = {
x: bounds.x + bounds.width / 2,
y: bounds.y + bounds.height / 2
};
} else {
mid = getExternalLabelMid(element);
size = DEFAULT_LABEL_SIZE;
}
return assign({
x: mid.x - size.width / 2,
y: mid.y - size.height / 2
}, size);
};
},{"14":14,"206":206}],14:[function(_dereq_,module,exports){
'use strict';
/**
* Is an element of the given BPMN type?
*
* @param {djs.model.Base|ModdleElement} element
* @param {String} type
*
* @return {Boolean}
*/
function is(element, type) {
var bo = getBusinessObject(element);
return bo && (typeof bo.$instanceOf === 'function') && bo.$instanceOf(type);
}
module.exports.is = is;
/**
* Return the business object for a given element.
*
* @param {djs.model.Base|ModdleElement} element
*
* @return {ModdleElement}
*/
function getBusinessObject(element) {
return (element && element.businessObject) || element;
}
module.exports.getBusinessObject = getBusinessObject;
},{}],15:[function(_dereq_,module,exports){
/**
* This file must not be changed or exchanged.
*
* @see http://bpmn.io/license for more information.
*/
'use strict';
var domify = _dereq_(220);
var domDelegate = _dereq_(219);
/* jshint -W101 */
// inlined ../resources/bpmnjs.png
var logoData = module.exports.BPMNIO_LOGO = 'iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAMAAADypuvZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADBQTFRFiMte9PrwldFwfcZPqtqN0+zEyOe1XLgjvuKncsJAZ70y6fXh3vDT////UrQV////G2zN+AAAABB0Uk5T////////////////////AOAjXRkAAAHDSURBVHjavJZJkoUgDEBJmAX8979tM8u3E6x20VlYJfFFMoL4vBDxATxZcakIOJTWSmxvKWVIkJ8jHvlRv1F2LFrVISCZI+tCtQx+XfewgVTfyY3plPiQEAzI3zWy+kR6NBhFBYeBuscJLOUuA2WVLpCjVIaFzrNQZArxAZKUQm6gsj37L9Cb7dnIBUKxENaaMJQqMpDXvSL+ktxdGRm2IsKgJGGPg7atwUG5CcFUEuSv+CwQqizTrvDTNXdMU2bMiDWZd8d7QIySWVRsb2vBBioxOFt4OinPBapL+neAb5KL5IJ8szOza2/DYoipUCx+CjO0Bpsv0V6mktNZ+k8rlABlWG0FrOpKYVo8DT3dBeLEjUBAj7moDogVii7nSS9QzZnFcOVBp1g2PyBQ3Vr5aIapN91VJy33HTJLC1iX2FY6F8gRdaAeIEfVONgtFCzZTmoLEdOjBDfsIOA6128gw3eu1shAajdZNAORxuQDJN5A5PbEG6gNIu24QJD5iNyRMZIr6bsHbCtCU/OaOaSvgkUyDMdDa1BXGf5HJ1To+/Ym6mCKT02Y+/Sa126ZKyd3jxhzpc1r8zVL6YM1Qy/kR4ABAFJ6iQUnivhAAAAAAElFTkSuQmCC';
/* jshint +W101 */
function css(attrs) {
return attrs.join(';');
}
var LIGHTBOX_STYLES = css([
'z-index: 1001',
'position: fixed',
'top: 0',
'left: 0',
'right: 0',
'bottom: 0'
]);
var BACKDROP_STYLES = css([
'width: 100%',
'height: 100%',
'background: rgba(0,0,0,0.2)'
]);
var NOTICE_STYLES = css([
'position: absolute',
'left: 50%',
'top: 40%',
'margin: 0 -130px',
'width: 260px',
'padding: 10px',
'background: white',
'border: solid 1px #AAA',
'border-radius: 3px',
'font-family: Helvetica, Arial, sans-serif',
'font-size: 14px',
'line-height: 1.2em'
]);
var LIGHTBOX_MARKUP =
'' +
'
' +
'
' +
'
' +
' ' +
' ' +
'Web-based tooling for BPMN, DMN and CMMN diagrams ' +
'powered by
bpmn.io .' +
'
' +
'
';
var lightbox;
function open() {
if (!lightbox) {
lightbox = domify(LIGHTBOX_MARKUP);
domDelegate.bind(lightbox, '.backdrop', 'click', function(event) {
document.body.removeChild(lightbox);
});
}
document.body.appendChild(lightbox);
}
module.exports.open = open;
},{"219":219,"220":220}],16:[function(_dereq_,module,exports){
module.exports = _dereq_(18);
},{"18":18}],17:[function(_dereq_,module,exports){
'use strict';
var isString = _dereq_(203),
isFunction = _dereq_(198),
assign = _dereq_(206);
var Moddle = _dereq_(24),
XmlReader = _dereq_(20),
XmlWriter = _dereq_(21);
/**
* A sub class of {@link Moddle} with support for import and export of BPMN 2.0 xml files.
*
* @class BpmnModdle
* @extends Moddle
*
* @param {Object|Array} packages to use for instantiating the model
* @param {Object} [options] additional options to pass over
*/
function BpmnModdle(packages, options) {
Moddle.call(this, packages, options);
}
BpmnModdle.prototype = Object.create(Moddle.prototype);
module.exports = BpmnModdle;
/**
* Instantiates a BPMN model tree from a given xml string.
*
* @param {String} xmlStr
* @param {String} [typeName='bpmn:Definitions'] name of the root element
* @param {Object} [options] options to pass to the underlying reader
* @param {Function} done callback that is invoked with (err, result, parseContext)
* once the import completes
*/
BpmnModdle.prototype.fromXML = function(xmlStr, typeName, options, done) {
if (!isString(typeName)) {
done = options;
options = typeName;
typeName = 'bpmn:Definitions';
}
if (isFunction(options)) {
done = options;
options = {};
}
var reader = new XmlReader(assign({ model: this, lax: true }, options));
var rootHandler = reader.handler(typeName);
reader.fromXML(xmlStr, rootHandler, done);
};
/**
* Serializes a BPMN 2.0 object tree to XML.
*
* @param {String} element the root element, typically an instance of `bpmn:Definitions`
* @param {Object} [options] to pass to the underlying writer
* @param {Function} done callback invoked with (err, xmlStr) once the import completes
*/
BpmnModdle.prototype.toXML = function(element, options, done) {
if (isFunction(options)) {
done = options;
options = {};
}
var writer = new XmlWriter(options);
try {
var result = writer.toXML(element);
done(null, result);
} catch (e) {
done(e);
}
};
},{"198":198,"20":20,"203":203,"206":206,"21":21,"24":24}],18:[function(_dereq_,module,exports){
'use strict';
var assign = _dereq_(206);
var BpmnModdle = _dereq_(17);
var packages = {
bpmn: _dereq_(33),
bpmndi: _dereq_(34),
dc: _dereq_(35),
di: _dereq_(36)
};
module.exports = function(additionalPackages, options) {
return new BpmnModdle(assign({}, packages, additionalPackages), options);
};
},{"17":17,"206":206,"33":33,"34":34,"35":35,"36":36}],19:[function(_dereq_,module,exports){
'use strict';
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function lower(string) {
return string.charAt(0).toLowerCase() + string.slice(1);
}
function hasLowerCaseAlias(pkg) {
return pkg.xml && pkg.xml.tagAlias === 'lowerCase';
}
module.exports.aliasToName = function(alias, pkg) {
if (hasLowerCaseAlias(pkg)) {
return capitalize(alias);
} else {
return alias;
}
};
module.exports.nameToAlias = function(name, pkg) {
if (hasLowerCaseAlias(pkg)) {
return lower(name);
} else {
return name;
}
};
module.exports.DEFAULT_NS_MAP = {
'xsi': 'http://www.w3.org/2001/XMLSchema-instance'
};
var XSI_TYPE = module.exports.XSI_TYPE = 'xsi:type';
function serializeFormat(element) {
return element.xml && element.xml.serialize;
}
module.exports.serializeAsType = function(element) {
return serializeFormat(element) === XSI_TYPE;
};
module.exports.serializeAsProperty = function(element) {
return serializeFormat(element) === 'property';
};
},{}],20:[function(_dereq_,module,exports){
'use strict';
var reduce = _dereq_(96),
forEach = _dereq_(92),
find = _dereq_(91),
assign = _dereq_(206),
defer = _dereq_(101);
var Stack = _dereq_(23),
SaxParser = _dereq_(22).parser,
Moddle = _dereq_(24),
parseNameNs = _dereq_(29).parseName,
Types = _dereq_(32),
coerceType = Types.coerceType,
isSimpleType = Types.isSimple,
common = _dereq_(19),
XSI_TYPE = common.XSI_TYPE,
XSI_URI = common.DEFAULT_NS_MAP.xsi,
serializeAsType = common.serializeAsType,
aliasToName = common.aliasToName;
function parseNodeAttributes(node) {
var nodeAttrs = node.attributes;
return reduce(nodeAttrs, function(result, v, k) {
var name, ns;
if (!v.local) {
name = v.prefix;
} else {
ns = parseNameNs(v.name, v.prefix);
name = ns.name;
}
result[name] = v.value;
return result;
}, {});
}
function normalizeType(node, attr, model) {
var nameNs = parseNameNs(attr.value);
var uri = node.ns[nameNs.prefix || ''],
localName = nameNs.localName,
pkg = uri && model.getPackage(uri),
typePrefix;
if (pkg) {
typePrefix = pkg.xml && pkg.xml.typePrefix;
if (typePrefix && localName.indexOf(typePrefix) === 0) {
localName = localName.slice(typePrefix.length);
}
attr.value = pkg.prefix + ':' + localName;
}
}
/**
* Normalizes namespaces for a node given an optional default namespace and a
* number of mappings from uris to default prefixes.
*
* @param {XmlNode} node
* @param {Model} model the model containing all registered namespaces
* @param {Uri} defaultNsUri
*/
function normalizeNamespaces(node, model, defaultNsUri) {
var uri, prefix;
uri = node.uri || defaultNsUri;
if (uri) {
var pkg = model.getPackage(uri);
if (pkg) {
prefix = pkg.prefix;
} else {
prefix = node.prefix;
}
node.prefix = prefix;
node.uri = uri;
}
forEach(node.attributes, function(attr) {
// normalize xsi:type attributes because the
// assigned type may or may not be namespace prefixed
if (attr.uri === XSI_URI && attr.local === 'type') {
normalizeType(node, attr, model);
}
normalizeNamespaces(attr, model, null);
});
}
function error(message) {
return new Error(message);
}
/**
* Get the moddle descriptor for a given instance or type.
*
* @param {ModdleElement|Function} element
*
* @return {Object} the moddle descriptor
*/
function getModdleDescriptor(element) {
return element.$descriptor;
}
/**
* A parse context.
*
* @class
*
* @param {Object} options
* @param {ElementHandler} options.rootHandler the root handler for parsing a document
* @param {boolean} [options.lax=false] whether or not to ignore invalid elements
*/
function Context(options) {
/**
* @property {ElementHandler} rootHandler
*/
/**
* @property {Boolean} lax
*/
assign(this, options);
this.elementsById = {};
this.references = [];
this.warnings = [];
/**
* Add an unresolved reference.
*
* @param {Object} reference
*/
this.addReference = function(reference) {
this.references.push(reference);
};
/**
* Add a processed element.
*
* @param {ModdleElement} element
*/
this.addElement = function(element) {
if (!element) {
throw error('expected element');
}
var descriptor = getModdleDescriptor(element);
var idProperty = descriptor.idProperty,
id;
if (idProperty) {
id = element.get(idProperty.name);
if (id) {
this.elementsById[id] = element;
}
}
};
/**
* Add an import warning.
*
* @param {Object} warning
* @param {String} warning.message
* @param {Error} [warning.error]
*/
this.addWarning = function(warning) {
this.warnings.push(warning);
};
}
function BaseHandler() {}
BaseHandler.prototype.handleEnd = function() {};
BaseHandler.prototype.handleText = function() {};
BaseHandler.prototype.handleNode = function() {};
/**
* A simple pass through handler that does nothing except for
* ignoring all input it receives.
*
* This is used to ignore unknown elements and
* attributes.
*/
function NoopHandler() { }
NoopHandler.prototype = new BaseHandler();
NoopHandler.prototype.handleNode = function() {
return this;
};
function BodyHandler() {}
BodyHandler.prototype = new BaseHandler();
BodyHandler.prototype.handleText = function(text) {
this.body = (this.body || '') + text;
};
function ReferenceHandler(property, context) {
this.property = property;
this.context = context;
}
ReferenceHandler.prototype = new BodyHandler();
ReferenceHandler.prototype.handleNode = function(node) {
if (this.element) {
throw error('expected no sub nodes');
} else {
this.element = this.createReference(node);
}
return this;
};
ReferenceHandler.prototype.handleEnd = function() {
this.element.id = this.body;
};
ReferenceHandler.prototype.createReference = function(node) {
return {
property: this.property.ns.name,
id: ''
};
};
function ValueHandler(propertyDesc, element) {
this.element = element;
this.propertyDesc = propertyDesc;
}
ValueHandler.prototype = new BodyHandler();
ValueHandler.prototype.handleEnd = function() {
var value = this.body,
element = this.element,
propertyDesc = this.propertyDesc;
value = coerceType(propertyDesc.type, value);
if (propertyDesc.isMany) {
element.get(propertyDesc.name).push(value);
} else {
element.set(propertyDesc.name, value);
}
};
function BaseElementHandler() {}
BaseElementHandler.prototype = Object.create(BodyHandler.prototype);
BaseElementHandler.prototype.handleNode = function(node) {
var parser = this,
element = this.element;
if (!element) {
element = this.element = this.createElement(node);
this.context.addElement(element);
} else {
parser = this.handleChild(node);
}
return parser;
};
/**
* @class XMLReader.ElementHandler
*
*/
function ElementHandler(model, type, context) {
this.model = model;
this.type = model.getType(type);
this.context = context;
}
ElementHandler.prototype = new BaseElementHandler();
ElementHandler.prototype.addReference = function(reference) {
this.context.addReference(reference);
};
ElementHandler.prototype.handleEnd = function() {
var value = this.body,
element = this.element,
descriptor = getModdleDescriptor(element),
bodyProperty = descriptor.bodyProperty;
if (bodyProperty && value !== undefined) {
value = coerceType(bodyProperty.type, value);
element.set(bodyProperty.name, value);
}
};
/**
* Create an instance of the model from the given node.
*
* @param {Element} node the xml node
*/
ElementHandler.prototype.createElement = function(node) {
var attributes = parseNodeAttributes(node),
Type = this.type,
descriptor = getModdleDescriptor(Type),
context = this.context,
instance = new Type({});
forEach(attributes, function(value, name) {
var prop = descriptor.propertiesByName[name],
values;
if (prop && prop.isReference) {
if (!prop.isMany) {
context.addReference({
element: instance,
property: prop.ns.name,
id: value
});
} else {
// IDREFS: parse references as whitespace-separated list
values = value.split(' ');
forEach(values, function(v) {
context.addReference({
element: instance,
property: prop.ns.name,
id: v
});
});
}
} else {
if (prop) {
value = coerceType(prop.type, value);
}
instance.set(name, value);
}
});
return instance;
};
ElementHandler.prototype.getPropertyForNode = function(node) {
var nameNs = parseNameNs(node.local, node.prefix);
var type = this.type,
model = this.model,
descriptor = getModdleDescriptor(type);
var propertyName = nameNs.name,
property = descriptor.propertiesByName[propertyName],
elementTypeName,
elementType,
typeAnnotation;
// search for properties by name first
if (property) {
if (serializeAsType(property)) {
typeAnnotation = node.attributes[XSI_TYPE];
// xsi type is optional, if it does not exists the
// default type is assumed
if (typeAnnotation) {
elementTypeName = typeAnnotation.value;
// TODO: extract real name from attribute
elementType = model.getType(elementTypeName);
return assign({}, property, { effectiveType: getModdleDescriptor(elementType).name });
}
}
// search for properties by name first
return property;
}
var pkg = model.getPackage(nameNs.prefix);
if (pkg) {
elementTypeName = nameNs.prefix + ':' + aliasToName(nameNs.localName, descriptor.$pkg);
elementType = model.getType(elementTypeName);
// search for collection members later
property = find(descriptor.properties, function(p) {
return !p.isVirtual && !p.isReference && !p.isAttribute && elementType.hasType(p.type);
});
if (property) {
return assign({}, property, { effectiveType: getModdleDescriptor(elementType).name });
}
} else {
// parse unknown element (maybe extension)
property = find(descriptor.properties, function(p) {
return !p.isReference && !p.isAttribute && p.type === 'Element';
});
if (property) {
return property;
}
}
throw error('unrecognized element <' + nameNs.name + '>');
};
ElementHandler.prototype.toString = function() {
return 'ElementDescriptor[' + getModdleDescriptor(this.type).name + ']';
};
ElementHandler.prototype.valueHandler = function(propertyDesc, element) {
return new ValueHandler(propertyDesc, element);
};
ElementHandler.prototype.referenceHandler = function(propertyDesc) {
return new ReferenceHandler(propertyDesc, this.context);
};
ElementHandler.prototype.handler = function(type) {
if (type === 'Element') {
return new GenericElementHandler(this.model, type, this.context);
} else {
return new ElementHandler(this.model, type, this.context);
}
};
/**
* Handle the child element parsing
*
* @param {Element} node the xml node
*/
ElementHandler.prototype.handleChild = function(node) {
var propertyDesc, type, element, childHandler;
propertyDesc = this.getPropertyForNode(node);
element = this.element;
type = propertyDesc.effectiveType || propertyDesc.type;
if (isSimpleType(type)) {
return this.valueHandler(propertyDesc, element);
}
if (propertyDesc.isReference) {
childHandler = this.referenceHandler(propertyDesc).handleNode(node);
} else {
childHandler = this.handler(type).handleNode(node);
}
var newElement = childHandler.element;
// child handles may decide to skip elements
// by not returning anything
if (newElement !== undefined) {
if (propertyDesc.isMany) {
element.get(propertyDesc.name).push(newElement);
} else {
element.set(propertyDesc.name, newElement);
}
if (propertyDesc.isReference) {
assign(newElement, {
element: element
});
this.context.addReference(newElement);
} else {
// establish child -> parent relationship
newElement.$parent = element;
}
}
return childHandler;
};
function GenericElementHandler(model, type, context) {
this.model = model;
this.context = context;
}
GenericElementHandler.prototype = Object.create(BaseElementHandler.prototype);
GenericElementHandler.prototype.createElement = function(node) {
var name = node.name,
prefix = node.prefix,
uri = node.ns[prefix],
attributes = node.attributes;
return this.model.createAny(name, uri, attributes);
};
GenericElementHandler.prototype.handleChild = function(node) {
var handler = new GenericElementHandler(this.model, 'Element', this.context).handleNode(node),
element = this.element;
var newElement = handler.element,
children;
if (newElement !== undefined) {
children = element.$children = element.$children || [];
children.push(newElement);
// establish child -> parent relationship
newElement.$parent = element;
}
return handler;
};
GenericElementHandler.prototype.handleText = function(text) {
this.body = this.body || '' + text;
};
GenericElementHandler.prototype.handleEnd = function() {
if (this.body) {
this.element.$body = this.body;
}
};
/**
* A reader for a meta-model
*
* @param {Object} options
* @param {Model} options.model used to read xml files
* @param {Boolean} options.lax whether to make parse errors warnings
*/
function XMLReader(options) {
if (options instanceof Moddle) {
options = {
model: options
};
}
assign(this, { lax: false }, options);
}
/**
* Parse the given XML into a moddle document tree.
*
* @param {String} xml
* @param {ElementHandler|Object} options or rootHandler
* @param {Function} done
*/
XMLReader.prototype.fromXML = function(xml, options, done) {
var rootHandler = options.rootHandler;
if (options instanceof ElementHandler) {
// root handler passed via (xml, { rootHandler: ElementHandler }, ...)
rootHandler = options;
options = {};
} else {
if (typeof options === 'string') {
// rootHandler passed via (xml, 'someString', ...)
rootHandler = this.handler(options);
options = {};
} else if (typeof rootHandler === 'string') {
// rootHandler passed via (xml, { rootHandler: 'someString' }, ...)
rootHandler = this.handler(rootHandler);
}
}
var model = this.model,
lax = this.lax;
var context = new Context(assign({}, options, { rootHandler: rootHandler })),
parser = new SaxParser(true, { xmlns: true, trim: true }),
stack = new Stack();
rootHandler.context = context;
// push root handler
stack.push(rootHandler);
function resolveReferences() {
var elementsById = context.elementsById;
var references = context.references;
var i, r;
for (i = 0; !!(r = references[i]); i++) {
var element = r.element;
var reference = elementsById[r.id];
var property = getModdleDescriptor(element).propertiesByName[r.property];
if (!reference) {
context.addWarning({
message: 'unresolved reference <' + r.id + '>',
element: r.element,
property: r.property,
value: r.id
});
}
if (property.isMany) {
var collection = element.get(property.name),
idx = collection.indexOf(r);
// we replace an existing place holder (idx != -1) or
// append to the collection instead
if (idx === -1) {
idx = collection.length;
}
if (!reference) {
// remove unresolvable reference
collection.splice(idx, 1);
} else {
// add or update reference in collection
collection[idx] = reference;
}
} else {
element.set(property.name, reference);
}
}
}
function handleClose(tagName) {
stack.pop().handleEnd();
}
function handleOpen(node) {
var handler = stack.peek();
normalizeNamespaces(node, model);
try {
stack.push(handler.handleNode(node));
} catch (e) {
var line = this.line,
column = this.column;
var message =
'unparsable content <' + node.name + '> detected\n\t' +
'line: ' + line + '\n\t' +
'column: ' + column + '\n\t' +
'nested error: ' + e.message;
if (lax) {
context.addWarning({
message: message,
error: e
});
console.warn('could not parse node');
console.warn(e);
stack.push(new NoopHandler());
} else {
console.error('could not parse document');
console.error(e);
throw error(message);
}
}
}
function handleText(text) {
stack.peek().handleText(text);
}
parser.onopentag = handleOpen;
parser.oncdata = parser.ontext = handleText;
parser.onclosetag = handleClose;
parser.onend = resolveReferences;
// deferred parse XML to make loading really ascnchronous
// this ensures the execution environment (node or browser)
// is kept responsive and that certain optimization strategies
// can kick in
defer(function() {
var error;
try {
parser.write(xml).close();
} catch (e) {
error = e;
}
done(error, error ? undefined : rootHandler.element, context);
});
};
XMLReader.prototype.handler = function(name) {
return new ElementHandler(this.model, name);
};
module.exports = XMLReader;
module.exports.ElementHandler = ElementHandler;
},{"101":101,"19":19,"206":206,"22":22,"23":23,"24":24,"29":29,"32":32,"91":91,"92":92,"96":96}],21:[function(_dereq_,module,exports){
'use strict';
var map = _dereq_(95),
forEach = _dereq_(92),
isString = _dereq_(203),
filter = _dereq_(90),
assign = _dereq_(206);
var Types = _dereq_(32),
parseNameNs = _dereq_(29).parseName,
common = _dereq_(19),
nameToAlias = common.nameToAlias,
serializeAsType = common.serializeAsType,
serializeAsProperty = common.serializeAsProperty;
var XML_PREAMBLE = '\n',
ESCAPE_CHARS = /(<|>|'|"|&|\n\r|\n)/g,
DEFAULT_NS_MAP = common.DEFAULT_NS_MAP,
XSI_TYPE = common.XSI_TYPE;
function nsName(ns) {
if (isString(ns)) {
return ns;
} else {
return (ns.prefix ? ns.prefix + ':' : '') + ns.localName;
}
}
function getNsAttrs(namespaces) {
function isUsed(ns) {
return namespaces.used[ns.uri];
}
function toAttr(ns) {
var name = 'xmlns' + (ns.prefix ? ':' + ns.prefix : '');
return { name: name, value: ns.uri };
}
var allNs = [].concat(namespaces.wellknown, namespaces.custom);
return map(filter(allNs, isUsed), toAttr);
}
function getElementNs(ns, descriptor) {
if (descriptor.isGeneric) {
return descriptor.name;
} else {
return assign({ localName: nameToAlias(descriptor.ns.localName, descriptor.$pkg) }, ns);
}
}
function getPropertyNs(ns, descriptor) {
return assign({ localName: descriptor.ns.localName }, ns);
}
function getSerializableProperties(element) {
var descriptor = element.$descriptor;
return filter(descriptor.properties, function(p) {
var name = p.name;
if (p.isVirtual) {
return false;
}
// do not serialize defaults
if (!element.hasOwnProperty(name)) {
return false;
}
var value = element[name];
// do not serialize default equals
if (value === p.default) {
return false;
}
return p.isMany ? value.length : true;
});
}
var ESCAPE_MAP = {
'\n': '10',
'\n\r': '10',
'"': '34',
'\'': '39',
'<': '60',
'>': '62',
'&': '38'
};
/**
* Escape a string attribute to not contain any bad values (line breaks, '"', ...)
*
* @param {String} str the string to escape
* @return {String} the escaped string
*/
function escapeAttr(str) {
// ensure we are handling strings here
str = isString(str) ? str : '' + str;
return str.replace(ESCAPE_CHARS, function(str) {
return '' + ESCAPE_MAP[str] + ';';
});
}
function filterAttributes(props) {
return filter(props, function(p) { return p.isAttr; });
}
function filterContained(props) {
return filter(props, function(p) { return !p.isAttr; });
}
function ReferenceSerializer(parent, ns) {
this.ns = ns;
}
ReferenceSerializer.prototype.build = function(element) {
this.element = element;
return this;
};
ReferenceSerializer.prototype.serializeTo = function(writer) {
writer
.appendIndent()
.append('<' + nsName(this.ns) + '>' + this.element.id + '' + nsName(this.ns) + '>')
.appendNewLine();
};
function BodySerializer() {}
BodySerializer.prototype.serializeValue = BodySerializer.prototype.serializeTo = function(writer) {
var escape = this.escape;
if (escape) {
writer.append('');
}
};
BodySerializer.prototype.build = function(prop, value) {
this.value = value;
if (prop.type === 'String' && value.search(ESCAPE_CHARS) !== -1) {
this.escape = true;
}
return this;
};
function ValueSerializer(ns) {
this.ns = ns;
}
ValueSerializer.prototype = new BodySerializer();
ValueSerializer.prototype.serializeTo = function(writer) {
writer
.appendIndent()
.append('<' + nsName(this.ns) + '>');
this.serializeValue(writer);
writer
.append( '' + nsName(this.ns) + '>')
.appendNewLine();
};
function ElementSerializer(parent, ns) {
this.body = [];
this.attrs = [];
this.parent = parent;
this.ns = ns;
}
ElementSerializer.prototype.build = function(element) {
this.element = element;
var otherAttrs = this.parseNsAttributes(element);
if (!this.ns) {
this.ns = this.nsTagName(element.$descriptor);
}
if (element.$descriptor.isGeneric) {
this.parseGeneric(element);
} else {
var properties = getSerializableProperties(element);
this.parseAttributes(filterAttributes(properties));
this.parseContainments(filterContained(properties));
this.parseGenericAttributes(element, otherAttrs);
}
return this;
};
ElementSerializer.prototype.nsTagName = function(descriptor) {
var effectiveNs = this.logNamespaceUsed(descriptor.ns);
return getElementNs(effectiveNs, descriptor);
};
ElementSerializer.prototype.nsPropertyTagName = function(descriptor) {
var effectiveNs = this.logNamespaceUsed(descriptor.ns);
return getPropertyNs(effectiveNs, descriptor);
};
ElementSerializer.prototype.isLocalNs = function(ns) {
return ns.uri === this.ns.uri;
};
/**
* Get the actual ns attribute name for the given element.
*
* @param {Object} element
* @param {Boolean} [inherited=false]
*
* @return {Object} nsName
*/
ElementSerializer.prototype.nsAttributeName = function(element) {
var ns;
if (isString(element)) {
ns = parseNameNs(element);
} else {
ns = element.ns;
}
// return just local name for inherited attributes
if (element.inherited) {
return { localName: ns.localName };
}
// parse + log effective ns
var effectiveNs = this.logNamespaceUsed(ns);
// strip prefix if same namespace like parent
if (this.isLocalNs(effectiveNs)) {
return { localName: ns.localName };
} else {
return assign({ localName: ns.localName }, effectiveNs);
}
};
ElementSerializer.prototype.parseGeneric = function(element) {
var self = this,
body = this.body,
attrs = this.attrs;
forEach(element, function(val, key) {
if (key === '$body') {
body.push(new BodySerializer().build({ type: 'String' }, val));
} else
if (key === '$children') {
forEach(val, function(child) {
body.push(new ElementSerializer(self).build(child));
});
} else
if (key.indexOf('$') !== 0) {
attrs.push({ name: key, value: escapeAttr(val) });
}
});
};
/**
* Parse namespaces and return a list of left over generic attributes
*
* @param {Object} element
* @return {Array}
*/
ElementSerializer.prototype.parseNsAttributes = function(element) {
var self = this;
var genericAttrs = element.$attrs;
var model = element.$model;
var attributes = [];
// parse namespace attributes first
// and log them. push non namespace attributes to a list
// and process them later
forEach(genericAttrs, function(value, name) {
var nameNs = parseNameNs(name);
var ns;
// parse xmlns:foo="http://foo.bar"
if (nameNs.prefix === 'xmlns') {
ns = { prefix: nameNs.localName, uri: value };
}
// parse xmlns="http://foo.bar"
if (!nameNs.prefix && nameNs.localName === 'xmlns') {
ns = { uri: value };
}
if (ns) {
if (model.getPackage(value)) {
// register well known namespace
self.logNamespace(ns, true);
} else {
// log custom namespace directly as used
self.logNamespaceUsed(ns);
}
} else {
attributes.push({ name: name, value: value });
}
});
return attributes;
};
ElementSerializer.prototype.parseGenericAttributes = function(element, attributes) {
var self = this;
forEach(attributes, function(attr) {
// do not serialize xsi:type attribute
// it is set manually based on the actual implementation type
if (attr.name === XSI_TYPE) {
return;
}
try {
self.addAttribute(self.nsAttributeName(attr.name), attr.value);
} catch (e) {
console.warn(
'missing namespace information for ',
attr.name, '=', attr.value, 'on', element,
e);
}
});
};
ElementSerializer.prototype.parseContainments = function(properties) {
var self = this,
body = this.body,
element = this.element;
forEach(properties, function(p) {
var value = element.get(p.name),
isReference = p.isReference,
isMany = p.isMany;
var ns = self.nsPropertyTagName(p);
if (!isMany) {
value = [ value ];
}
if (p.isBody) {
body.push(new BodySerializer().build(p, value[0]));
} else
if (Types.isSimple(p.type)) {
forEach(value, function(v) {
body.push(new ValueSerializer(ns).build(p, v));
});
} else
if (isReference) {
forEach(value, function(v) {
body.push(new ReferenceSerializer(self, ns).build(v));
});
} else {
// allow serialization via type
// rather than element name
var asType = serializeAsType(p),
asProperty = serializeAsProperty(p);
forEach(value, function(v) {
var serializer;
if (asType) {
serializer = new TypeSerializer(self, ns);
} else
if (asProperty) {
serializer = new ElementSerializer(self, ns);
} else {
serializer = new ElementSerializer(self);
}
body.push(serializer.build(v));
});
}
});
};
ElementSerializer.prototype.getNamespaces = function() {
var namespaces = this.namespaces,
parent = this.parent;
if (!namespaces) {
namespaces = this.namespaces = parent ? parent.getNamespaces() : {
prefixMap: {},
uriMap: {},
used: {},
wellknown: [],
custom: []
};
}
return namespaces;
};
ElementSerializer.prototype.logNamespace = function(ns, wellknown) {
var namespaces = this.getNamespaces();
var nsUri = ns.uri;
var existing = namespaces.uriMap[nsUri];
if (!existing) {
namespaces.uriMap[nsUri] = ns;
if (wellknown) {
namespaces.wellknown.push(ns);
} else {
namespaces.custom.push(ns);
}
}
namespaces.prefixMap[ns.prefix] = nsUri;
return ns;
};
ElementSerializer.prototype.logNamespaceUsed = function(ns) {
var element = this.element,
model = element.$model,
namespaces = this.getNamespaces();
// ns may be
//
// * prefix only
// * prefix:uri
var prefix = ns.prefix;
var wellknownUri = DEFAULT_NS_MAP[prefix] || model && (model.getPackage(prefix) || {}).uri;
var uri = ns.uri || namespaces.prefixMap[prefix] || wellknownUri;
if (!uri) {
throw new Error('no namespace uri given for prefix <' + ns.prefix + '>');
}
ns = namespaces.uriMap[uri];
if (!ns) {
ns = this.logNamespace({ prefix: prefix, uri: uri }, wellknownUri);
}
if (!namespaces.used[ns.uri]) {
namespaces.used[ns.uri] = ns;
}
return ns;
};
ElementSerializer.prototype.parseAttributes = function(properties) {
var self = this,
element = this.element;
forEach(properties, function(p) {
var value = element.get(p.name);
if (p.isReference) {
if (!p.isMany) {
value = value.id;
}
else {
var values = [];
forEach(value, function(v) {
values.push(v.id);
});
// IDREFS is a whitespace-separated list of references.
value = values.join(' ');
}
}
self.addAttribute(self.nsAttributeName(p), value);
});
};
ElementSerializer.prototype.addAttribute = function(name, value) {
var attrs = this.attrs;
if (isString(value)) {
value = escapeAttr(value);
}
attrs.push({ name: name, value: value });
};
ElementSerializer.prototype.serializeAttributes = function(writer) {
var attrs = this.attrs,
root = !this.parent;
if (root) {
attrs = getNsAttrs(this.namespaces).concat(attrs);
}
forEach(attrs, function(a) {
writer
.append(' ')
.append(nsName(a.name)).append('="').append(a.value).append('"');
});
};
ElementSerializer.prototype.serializeTo = function(writer) {
var hasBody = this.body.length,
indent = !(this.body.length === 1 && this.body[0] instanceof BodySerializer);
writer
.appendIndent()
.append('<' + nsName(this.ns));
this.serializeAttributes(writer);
writer.append(hasBody ? '>' : ' />');
if (hasBody) {
if (indent) {
writer
.appendNewLine()
.indent();
}
forEach(this.body, function(b) {
b.serializeTo(writer);
});
if (indent) {
writer
.unindent()
.appendIndent();
}
writer.append('' + nsName(this.ns) + '>');
}
writer.appendNewLine();
};
/**
* A serializer for types that handles serialization of data types
*/
function TypeSerializer(parent, ns) {
ElementSerializer.call(this, parent, ns);
}
TypeSerializer.prototype = new ElementSerializer();
TypeSerializer.prototype.build = function(element) {
var descriptor = element.$descriptor;
this.element = element;
this.typeNs = this.nsTagName(descriptor);
// add xsi:type attribute to represent the elements
// actual type
var typeNs = this.typeNs,
pkg = element.$model.getPackage(typeNs.uri),
typePrefix = (pkg.xml && pkg.xml.typePrefix) || '';
this.addAttribute(this.nsAttributeName(XSI_TYPE),
(typeNs.prefix ? typeNs.prefix + ':' : '') +
typePrefix + descriptor.ns.localName);
// do the usual stuff
return ElementSerializer.prototype.build.call(this, element);
};
TypeSerializer.prototype.isLocalNs = function(ns) {
return ns.uri === this.typeNs.uri;
};
function SavingWriter() {
this.value = '';
this.write = function(str) {
this.value += str;
};
}
function FormatingWriter(out, format) {
var indent = [''];
this.append = function(str) {
out.write(str);
return this;
};
this.appendNewLine = function() {
if (format) {
out.write('\n');
}
return this;
};
this.appendIndent = function() {
if (format) {
out.write(indent.join(' '));
}
return this;
};
this.indent = function() {
indent.push('');
return this;
};
this.unindent = function() {
indent.pop();
return this;
};
}
/**
* A writer for meta-model backed document trees
*
* @param {Object} options output options to pass into the writer
*/
function XMLWriter(options) {
options = assign({ format: false, preamble: true }, options || {});
function toXML(tree, writer) {
var internalWriter = writer || new SavingWriter();
var formatingWriter = new FormatingWriter(internalWriter, options.format);
if (options.preamble) {
formatingWriter.append(XML_PREAMBLE);
}
new ElementSerializer().build(tree).serializeTo(formatingWriter);
if (!writer) {
return internalWriter.value;
}
}
return {
toXML: toXML
};
}
module.exports = XMLWriter;
},{"19":19,"203":203,"206":206,"29":29,"32":32,"90":90,"92":92,"95":95}],22:[function(_dereq_,module,exports){
(function (Buffer){
// wrapper for non-node envs
;(function (sax) {
sax.parser = function (strict, opt) { return new SAXParser(strict, opt) }
sax.SAXParser = SAXParser
sax.SAXStream = SAXStream
sax.createStream = createStream
// When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
// When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
// since that's the earliest that a buffer overrun could occur. This way, checks are
// as rare as required, but as often as necessary to ensure never crossing this bound.
// Furthermore, buffers are only tested at most once per write(), so passing a very
// large string into write() might have undesirable effects, but this is manageable by
// the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme
// edge case, result in creating at most one complete copy of the string passed in.
// Set to Infinity to have unlimited buffers.
sax.MAX_BUFFER_LENGTH = 64 * 1024
var buffers = [
"comment", "sgmlDecl", "textNode", "tagName", "doctype",
"procInstName", "procInstBody", "entity", "attribName",
"attribValue", "cdata", "script"
]
sax.EVENTS = // for discoverability.
[ "text"
, "processinginstruction"
, "sgmldeclaration"
, "doctype"
, "comment"
, "attribute"
, "opentag"
, "closetag"
, "opencdata"
, "cdata"
, "closecdata"
, "error"
, "end"
, "ready"
, "script"
, "opennamespace"
, "closenamespace"
]
function SAXParser (strict, opt) {
if (!(this instanceof SAXParser)) return new SAXParser(strict, opt)
var parser = this
clearBuffers(parser)
parser.q = parser.c = ""
parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH
parser.opt = opt || {}
parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags
parser.looseCase = parser.opt.lowercase ? "toLowerCase" : "toUpperCase"
parser.tags = []
parser.closed = parser.closedRoot = parser.sawRoot = false
parser.tag = parser.error = null
parser.strict = !!strict
parser.noscript = !!(strict || parser.opt.noscript)
parser.state = S.BEGIN
parser.ENTITIES = Object.create(sax.ENTITIES)
parser.attribList = []
// namespaces form a prototype chain.
// it always points at the current tag,
// which protos to its parent tag.
if (parser.opt.xmlns) parser.ns = Object.create(rootNS)
// mostly just for error reporting
parser.trackPosition = parser.opt.position !== false
if (parser.trackPosition) {
parser.position = parser.line = parser.column = 0
}
emit(parser, "onready")
}
if (!Object.create) Object.create = function (o) {
function f () { this.__proto__ = o }
f.prototype = o
return new f
}
if (!Object.getPrototypeOf) Object.getPrototypeOf = function (o) {
return o.__proto__
}
if (!Object.keys) Object.keys = function (o) {
var a = []
for (var i in o) if (o.hasOwnProperty(i)) a.push(i)
return a
}
function checkBufferLength (parser) {
var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10)
, maxActual = 0
for (var i = 0, l = buffers.length; i < l; i ++) {
var len = parser[buffers[i]].length
if (len > maxAllowed) {
// Text/cdata nodes can get big, and since they're buffered,
// we can get here under normal conditions.
// Avoid issues by emitting the text node now,
// so at least it won't get any bigger.
switch (buffers[i]) {
case "textNode":
closeText(parser)
break
case "cdata":
emitNode(parser, "oncdata", parser.cdata)
parser.cdata = ""
break
case "script":
emitNode(parser, "onscript", parser.script)
parser.script = ""
break
default:
error(parser, "Max buffer length exceeded: "+buffers[i])
}
}
maxActual = Math.max(maxActual, len)
}
// schedule the next check for the earliest possible buffer overrun.
parser.bufferCheckPosition = (sax.MAX_BUFFER_LENGTH - maxActual)
+ parser.position
}
function clearBuffers (parser) {
for (var i = 0, l = buffers.length; i < l; i ++) {
parser[buffers[i]] = ""
}
}
function flushBuffers (parser) {
closeText(parser)
if (parser.cdata !== "") {
emitNode(parser, "oncdata", parser.cdata)
parser.cdata = ""
}
if (parser.script !== "") {
emitNode(parser, "onscript", parser.script)
parser.script = ""
}
}
SAXParser.prototype =
{ end: function () { end(this) }
, write: write
, resume: function () { this.error = null; return this }
, close: function () { return this.write(null) }
, flush: function () { flushBuffers(this) }
}
try {
var Stream = _dereq_("stream").Stream
} catch (ex) {
var Stream = function () {}
}
var streamWraps = sax.EVENTS.filter(function (ev) {
return ev !== "error" && ev !== "end"
})
function createStream (strict, opt) {
return new SAXStream(strict, opt)
}
function SAXStream (strict, opt) {
if (!(this instanceof SAXStream)) return new SAXStream(strict, opt)
Stream.apply(this)
this._parser = new SAXParser(strict, opt)
this.writable = true
this.readable = true
var me = this
this._parser.onend = function () {
me.emit("end")
}
this._parser.onerror = function (er) {
me.emit("error", er)
// if didn't throw, then means error was handled.
// go ahead and clear error, so we can write again.
me._parser.error = null
}
this._decoder = null;
streamWraps.forEach(function (ev) {
Object.defineProperty(me, "on" + ev, {
get: function () { return me._parser["on" + ev] },
set: function (h) {
if (!h) {
me.removeAllListeners(ev)
return me._parser["on"+ev] = h
}
me.on(ev, h)
},
enumerable: true,
configurable: false
})
})
}
SAXStream.prototype = Object.create(Stream.prototype,
{ constructor: { value: SAXStream } })
SAXStream.prototype.write = function (data) {
if (typeof Buffer === 'function' &&
typeof Buffer.isBuffer === 'function' &&
Buffer.isBuffer(data)) {
if (!this._decoder) {
var SD = _dereq_('string_decoder').StringDecoder
this._decoder = new SD('utf8')
}
data = this._decoder.write(data);
}
this._parser.write(data.toString())
this.emit("data", data)
return true
}
SAXStream.prototype.end = function (chunk) {
if (chunk && chunk.length) this.write(chunk)
this._parser.end()
return true
}
SAXStream.prototype.on = function (ev, handler) {
var me = this
if (!me._parser["on"+ev] && streamWraps.indexOf(ev) !== -1) {
me._parser["on"+ev] = function () {
var args = arguments.length === 1 ? [arguments[0]]
: Array.apply(null, arguments)
args.splice(0, 0, ev)
me.emit.apply(me, args)
}
}
return Stream.prototype.on.call(me, ev, handler)
}
// character classes and tokens
var whitespace = "\r\n\t "
// this really needs to be replaced with character classes.
// XML allows all manner of ridiculous numbers and digits.
, number = "0124356789"
, letter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// (Letter | "_" | ":")
, quote = "'\""
, entity = number+letter+"#"
, attribEnd = whitespace + ">"
, CDATA = "[CDATA["
, DOCTYPE = "DOCTYPE"
, XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace"
, XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/"
, rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE }
// turn all the string character sets into character class objects.
whitespace = charClass(whitespace)
number = charClass(number)
letter = charClass(letter)
// http://www.w3.org/TR/REC-xml/#NT-NameStartChar
// This implementation works on strings, a single character at a time
// as such, it cannot ever support astral-plane characters (10000-EFFFF)
// without a significant breaking change to either this parser, or the
// JavaScript language. Implementation of an emoji-capable xml parser
// is left as an exercise for the reader.
var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040\.\d-]/
quote = charClass(quote)
entity = charClass(entity)
attribEnd = charClass(attribEnd)
function charClass (str) {
return str.split("").reduce(function (s, c) {
s[c] = true
return s
}, {})
}
function isRegExp (c) {
return Object.prototype.toString.call(c) === '[object RegExp]'
}
function is (charclass, c) {
return isRegExp(charclass) ? !!c.match(charclass) : charclass[c]
}
function not (charclass, c) {
return !is(charclass, c)
}
var S = 0
sax.STATE =
{ BEGIN : S++
, TEXT : S++ // general stuff
, TEXT_ENTITY : S++ // & and such.
, OPEN_WAKA : S++ // <
, SGML_DECL : S++ //
, SCRIPT : S++ //