bpmn-js/lib/util/model/ModelCloneHelper.js

126 lines
3.5 KiB
JavaScript

'use strict';
var forEach = require('lodash/collection/forEach'),
filter = require('lodash/collection/filter'),
isArray = require('lodash/lang/isArray'),
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;
}
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;
}
/**
* A bpmn properties cloning interface
*
* @param {Moddle} moddle
*/
function ModelCloneHelper(moddle) {
this._moddle = moddle;
}
module.exports = ModelCloneHelper;
ModelCloneHelper.prototype.clone = function(oldElement, newElement, properties) {
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];
if (extProp.meta.allowedIn && isAllowedIn(extProp, newElement.$type)) {
var newProp = this._deepClone(extElement);
newProp.$parent = newElement.extensionElements;
newElement.extensionElements.values.push(newProp);
}
}, this);
} else if (propName === 'bpmn:documentation') {
newElement.documentation = [];
forEach(oldElementProp, function(extElement) {
var newProp = this._deepClone(extElement);
newProp.$parent = newElement;
newElement.documentation.push(newProp);
}, this);
}
}, this);
return newElement;
};
ModelCloneHelper.prototype._deepClone = function _deepClone(extElement) {
var newProp = extElement.$model.create(extElement.$type),
properties = filter(Object.keys(extElement), function(prop) { return prop !== '$type'; });
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) {
var newDeepProp = this._deepClone(property);
newDeepProp.$parent = newProp;
newProp[propName].push(newDeepProp);
}, this);
} else if (extElement[propName].$type) {
newProp[propName] = this._deepClone(extElement[propName]);
newProp[propName].$parent = newProp;
}
} else {
// just assign directly if it's a value
newProp[propName] = extElement[propName];
}
}, this);
return newProp;
};