feat(util/model): avoid persisting empty property element containers

Closes camunda/camunda-modeler#512
This commit is contained in:
Ricardo Matias 2017-02-01 10:42:49 +01:00 committed by Philipp Fromme
parent c1c62823f6
commit 86c0a0aa75
2 changed files with 42 additions and 10 deletions

View File

@ -39,6 +39,10 @@ module.exports = ModelCloneHelper;
ModelCloneHelper.prototype.clone = function(oldElement, newElement, properties) {
this._newElement = newElement;
// this property allows us to avoid ending up with empty (xml) tags
// f.ex: if extensionElements.values is empty, don't set it
this._hasNestedProperty = false;
// we want the extensionElements to be cloned last
// so that they can check certain properties
properties = sort(properties, function(prop) {
@ -49,7 +53,7 @@ ModelCloneHelper.prototype.clone = function(oldElement, newElement, properties)
var oldElementProp = oldElement.get(propName),
newElementProp = newElement.get(propName),
propDescriptor = newElement.$model.getPropertyDescriptor(newElement, propName),
name;
newProperty, name;
// we're not interested in cloning:
// - same values from simple types
@ -72,14 +76,25 @@ ModelCloneHelper.prototype.clone = function(oldElement, newElement, properties)
forEach(oldElementProp, function(extElement) {
var newProp = this._deepClone(extElement);
newProp.$parent = newElement;
if (this._hasNestedProperty) {
newProp.$parent = newElement;
newElementProp.push(newProp);
newElementProp.push(newProp);
}
this._hasNestedProperty = false;
}, this);
} else {
name = propName.replace(/bpmn:/, '');
newElement[name] = this._deepClone(oldElementProp);
newProperty = this._deepClone(oldElementProp);
if (this._hasNestedProperty) {
newElement[name] = newProperty;
}
this._hasNestedProperty = false;
}
}, this);
@ -110,12 +125,15 @@ ModelCloneHelper.prototype._deepClone = function _deepClone(element) {
return prop !== '$type';
});
if (!properties.length) {
this._hasNestedProperty = true;
}
forEach(properties, function(propName) {
// check if the element has this property defined
if (element[propName] !== undefined && (element[propName].$type || isArray(element[propName]))) {
if (isArray(element[propName])) {
newProp[propName] = [];
forEach(element[propName], function(property) {
var extProp = element.$model.getTypeDescriptor(property.$type),
@ -145,15 +163,27 @@ ModelCloneHelper.prototype._deepClone = function _deepClone(element) {
newDeepProp.$parent = newProp;
if (!newProp[propName]) {
newProp[propName] = [];
}
this._hasNestedProperty = true;
newProp[propName].push(newDeepProp);
}, this);
} else if (element[propName].$type) {
newProp[propName] = this._deepClone(element[propName]);
newProp[propName].$parent = newProp;
if (newProp[propName]) {
this._hasNestedProperty = true;
newProp[propName].$parent = newProp;
}
}
} else {
this._hasNestedProperty = true;
// just assign directly if it's a value
newProp[propName] = element[propName];
}

View File

@ -208,7 +208,7 @@ describe('util/ModelCloneHelper', function() {
var extElem = userTask.extensionElements;
// then
expect(extElem.values).to.be.empty;
expect(extElem).to.not.exist;
}));
});
@ -230,10 +230,12 @@ describe('util/ModelCloneHelper', function() {
});
var signalEvtDef = moddle.create('bpmn:SignalEventDefinition', {
timeDuration: 'foobar'
async: true
});
var multiInst = moddle.create('bpmn:MultiInstanceLoopCharacteristics');
var multiInst = moddle.create('bpmn:MultiInstanceLoopCharacteristics', {
elementVariable: 'foobar'
});
var timerStartEvent = moddle.create('bpmn:StartEvent', {
extensionElements: createExtElems(),
@ -364,7 +366,7 @@ describe('util/ModelCloneHelper', function() {
var extElems = clonedElement.extensionElements;
// then
expect(extElems.values).be.empty;
expect(extElems).not.exist;
}));
});