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

Closes #512
This commit is contained in:
Ricardo Matias 2017-02-01 10:42:49 +01:00
parent d8098c2feb
commit 1cb3a8eedc
2 changed files with 44 additions and 10 deletions

View File

@ -37,8 +37,11 @@ module.exports = ModelCloneHelper;
ModelCloneHelper.prototype.clone = function(refElement, newElement, properties) {
// hasNestedProperty: property allows us to avoid ending up with empty (xml) tags
// f.ex: if extensionElements.values is empty, don't set it
var context = {
newElement: newElement
newElement: newElement,
hasNestedProperty: false
};
// we want the extensionElements to be cloned last
@ -51,7 +54,7 @@ ModelCloneHelper.prototype.clone = function(refElement, newElement, properties)
var refElementProp = refElement.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
@ -78,16 +81,27 @@ ModelCloneHelper.prototype.clone = function(refElement, newElement, properties)
newProp = this._deepClone(extElement, context);
newProp.$parent = newElement;
if (context.hasNestedProperty) {
newProp.$parent = newElement;
newElementProp.push(newProp);
newElementProp.push(newProp);
}
context.hasNestedProperty = false;
}, this);
} else {
name = propName.replace(/bpmn:/, '');
context.refTopLevelProperty = refElementProp;
newElement[name] = this._deepClone(refElementProp, context);
newProperty = this._deepClone(refElementProp, context);
if (context.hasNestedProperty) {
newElement[name] = newProperty;
}
context.hasNestedProperty = false;
}
}, this);
@ -116,6 +130,10 @@ ModelCloneHelper.prototype._deepClone = function _deepClone(propertyElement, con
return prop !== '$type';
});
if (!properties.length) {
context.hasNestedProperty = true;
}
forEach(properties, function(propName) {
// check if the propertyElement has this property defined
if (propertyElement[propName] !== undefined &&
@ -153,15 +171,27 @@ ModelCloneHelper.prototype._deepClone = function _deepClone(propertyElement, con
newDeepProp.$parent = newProp;
if (!newProp[propName]) {
newProp[propName] = [];
}
context.hasNestedProperty = true;
newProp[propName].push(newDeepProp);
}, this);
} else if (propertyElement[propName].$type) {
newProp[propName] = this._deepClone(propertyElement[propName], context);
newProp[propName].$parent = newProp;
if (newProp[propName]) {
context.hasNestedProperty = true;
newProp[propName].$parent = newProp;
}
}
} else {
context.hasNestedProperty = true;
// just assign directly if it's a value
newProp[propName] = propertyElement[propName];
}

View File

@ -214,7 +214,7 @@ describe('util/ModelCloneHelper', function() {
var extElem = userTask.extensionElements;
// then
expect(extElem.values).to.be.empty;
expect(extElem).to.not.exist;
}));
});
@ -236,10 +236,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(),
@ -368,8 +370,10 @@ describe('util/ModelCloneHelper', function() {
'bpmn:extensionElements'
]);
var extElems = clonedElement.extensionElements;
// then
expect(clonedElement.eventDefinitions).to.be.empty;
expect(extElems).to.not.exist;
}));
});