2017-01-11 07:12:34 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var forEach = require('lodash/collection/forEach'),
|
|
|
|
filter = require('lodash/collection/filter'),
|
|
|
|
isArray = require('lodash/lang/isArray'),
|
2017-01-11 14:22:32 +00:00
|
|
|
contains = require('lodash/collection/contains');
|
|
|
|
|
|
|
|
|
|
|
|
function isAllowedIn(extProp, type) {
|
|
|
|
var allowedIn = extProp.meta.allowedIn;
|
|
|
|
|
|
|
|
// '*' is a wildcard, which means any element is allowed to use this property
|
|
|
|
if (allowedIn.length === 1 && allowedIn[0] === '*') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return allowedIn.indexOf(type) !== -1;
|
|
|
|
}
|
2017-01-11 07:12:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A bpmn properties cloning interface
|
|
|
|
*
|
|
|
|
* @param {Moddle} moddle
|
|
|
|
*/
|
2017-01-11 14:22:32 +00:00
|
|
|
function ModelCloneHelper(moddle) {
|
2017-01-11 07:12:34 +00:00
|
|
|
this._moddle = moddle;
|
|
|
|
}
|
|
|
|
|
2017-01-11 14:22:32 +00:00
|
|
|
module.exports = ModelCloneHelper;
|
2017-01-11 07:12:34 +00:00
|
|
|
|
|
|
|
|
2017-01-11 14:22:32 +00:00
|
|
|
ModelCloneHelper.prototype.clone = function(oldElement, newElement, properties) {
|
2017-01-11 07:12:34 +00:00
|
|
|
var moddle = this._moddle;
|
|
|
|
|
|
|
|
forEach(properties, function(propName) {
|
|
|
|
var oldElementProp = oldElement.$model.properties.get(oldElement, propName),
|
|
|
|
newElementProp = newElement.$model.properties.get(newElement, propName);
|
|
|
|
|
|
|
|
if (newElementProp === oldElementProp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if it's not an 'extensionElement' or 'documentation' just set the property
|
|
|
|
if (!(contains([ 'bpmn:extensionElements', 'bpmn:documentation' ], propName))) {
|
|
|
|
newElement.$model.properties.set(newElement, propName, oldElementProp);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (propName === 'bpmn:extensionElements') {
|
|
|
|
newElement.$model.properties.set(newElement, propName, moddle.create('bpmn:ExtensionElements', { values: [] }));
|
|
|
|
|
|
|
|
forEach(oldElementProp.values, function(extElement) {
|
|
|
|
|
|
|
|
var extProp = moddle.registry.typeMap[extElement.$type];
|
|
|
|
|
2017-01-11 14:22:32 +00:00
|
|
|
if (extProp.meta.allowedIn && isAllowedIn(extProp, newElement.$type)) {
|
2017-01-11 07:12:34 +00:00
|
|
|
|
|
|
|
var newProp = this._deepClone(extElement);
|
|
|
|
|
2017-01-11 14:22:32 +00:00
|
|
|
newProp.$parent = newElement.extensionElements;
|
|
|
|
|
2017-01-11 07:12:34 +00:00
|
|
|
newElement.extensionElements.values.push(newProp);
|
|
|
|
}
|
|
|
|
}, this);
|
|
|
|
} else if (propName === 'bpmn:documentation') {
|
|
|
|
newElement.documentation = [];
|
|
|
|
|
|
|
|
forEach(oldElementProp, function(extElement) {
|
|
|
|
var newProp = this._deepClone(extElement);
|
|
|
|
|
2017-01-11 14:22:32 +00:00
|
|
|
newProp.$parent = newElement;
|
|
|
|
|
2017-01-11 07:12:34 +00:00
|
|
|
newElement.documentation.push(newProp);
|
|
|
|
}, this);
|
|
|
|
}
|
|
|
|
}, this);
|
|
|
|
|
|
|
|
return newElement;
|
|
|
|
};
|
|
|
|
|
2017-01-11 14:22:32 +00:00
|
|
|
ModelCloneHelper.prototype._deepClone = function _deepClone(extElement) {
|
2017-01-11 07:12:34 +00:00
|
|
|
var newProp = extElement.$model.create(extElement.$type),
|
2017-01-11 14:22:32 +00:00
|
|
|
properties = filter(Object.keys(extElement), function(prop) { return prop !== '$type'; });
|
2017-01-11 07:12:34 +00:00
|
|
|
|
|
|
|
forEach(properties, function(propName) {
|
|
|
|
// check if the extElement has this property defined
|
|
|
|
if (extElement[propName] !== undefined && (extElement[propName].$type || isArray(extElement[propName]))) {
|
|
|
|
|
|
|
|
if (isArray(extElement[propName])) {
|
|
|
|
newProp[propName] = [];
|
|
|
|
|
|
|
|
forEach(extElement[propName], function(property) {
|
2017-01-11 14:22:32 +00:00
|
|
|
var newDeepProp = this._deepClone(property);
|
|
|
|
|
|
|
|
newDeepProp.$parent = newProp;
|
|
|
|
|
|
|
|
newProp[propName].push(newDeepProp);
|
2017-01-11 07:12:34 +00:00
|
|
|
}, this);
|
|
|
|
|
|
|
|
} else if (extElement[propName].$type) {
|
|
|
|
newProp[propName] = this._deepClone(extElement[propName]);
|
2017-01-11 14:22:32 +00:00
|
|
|
|
|
|
|
newProp[propName].$parent = newProp;
|
2017-01-11 07:12:34 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// just assign directly if it's a value
|
|
|
|
newProp[propName] = extElement[propName];
|
|
|
|
}
|
|
|
|
}, this);
|
|
|
|
|
|
|
|
return newProp;
|
|
|
|
};
|