fix(util/model): able to clone Event Definitions extension elements
Related to camunda/camunda-modeler#516 Related to camunda/camunda-modeler#517
This commit is contained in:
parent
1a4a8959fe
commit
2c51cfbe3d
|
@ -36,8 +36,10 @@ function ModelCloneHelper(eventBus) {
|
|||
module.exports = ModelCloneHelper;
|
||||
|
||||
|
||||
ModelCloneHelper.prototype.clone = function(oldElement, newElement, properties) {
|
||||
this._newElement = newElement;
|
||||
ModelCloneHelper.prototype.clone = function(refElement, newElement, properties) {
|
||||
var context = {
|
||||
newElement: newElement
|
||||
};
|
||||
|
||||
// we want the extensionElements to be cloned last
|
||||
// so that they can check certain properties
|
||||
|
@ -46,7 +48,7 @@ ModelCloneHelper.prototype.clone = function(oldElement, newElement, properties)
|
|||
});
|
||||
|
||||
forEach(properties, function(propName) {
|
||||
var oldElementProp = oldElement.get(propName),
|
||||
var refElementProp = refElement.get(propName),
|
||||
newElementProp = newElement.get(propName),
|
||||
propDescriptor = newElement.$model.getPropertyDescriptor(newElement, propName),
|
||||
name;
|
||||
|
@ -55,22 +57,26 @@ ModelCloneHelper.prototype.clone = function(oldElement, newElement, properties)
|
|||
// - same values from simple types
|
||||
// - cloning id's
|
||||
// - cloning reference elements
|
||||
if (newElementProp === oldElementProp ||
|
||||
if (newElementProp === refElementProp ||
|
||||
(propDescriptor && (propDescriptor.isId || propDescriptor.isReference))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the property is of type 'boolean', 'string', 'number' or 'null', just set it
|
||||
if (isType(oldElementProp, [ 'boolean', 'string', 'number' ]) || oldElementProp === null) {
|
||||
newElement.set(propName, oldElementProp);
|
||||
if (isType(refElementProp, [ 'boolean', 'string', 'number' ]) || refElementProp === null) {
|
||||
newElement.set(propName, refElementProp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isArray(oldElementProp)) {
|
||||
if (isArray(refElementProp)) {
|
||||
|
||||
forEach(oldElementProp, function(extElement) {
|
||||
var newProp = this._deepClone(extElement);
|
||||
forEach(refElementProp, function(extElement) {
|
||||
var newProp;
|
||||
|
||||
context.refTopLevelProperty = extElement;
|
||||
|
||||
newProp = this._deepClone(extElement, context);
|
||||
|
||||
newProp.$parent = newElement;
|
||||
|
||||
|
@ -79,21 +85,21 @@ ModelCloneHelper.prototype.clone = function(oldElement, newElement, properties)
|
|||
} else {
|
||||
name = propName.replace(/bpmn:/, '');
|
||||
|
||||
newElement[name] = this._deepClone(oldElementProp);
|
||||
context.refTopLevelProperty = refElementProp;
|
||||
|
||||
newElement[name] = this._deepClone(refElementProp, context);
|
||||
}
|
||||
}, this);
|
||||
|
||||
return newElement;
|
||||
};
|
||||
|
||||
ModelCloneHelper.prototype._deepClone = function _deepClone(element) {
|
||||
ModelCloneHelper.prototype._deepClone = function _deepClone(propertyElement, context) {
|
||||
var eventBus = this._eventBus;
|
||||
|
||||
var newElement = this._newElement;
|
||||
var newProp = propertyElement.$model.create(propertyElement.$type);
|
||||
|
||||
var newProp = element.$model.create(element.$type);
|
||||
|
||||
var properties = filter(Object.keys(element), function(prop) {
|
||||
var properties = filter(Object.keys(propertyElement), function(prop) {
|
||||
var descriptor = newProp.$model.getPropertyDescriptor(newProp, prop);
|
||||
|
||||
if (descriptor && (descriptor.isId || descriptor.isReference)) {
|
||||
|
@ -111,14 +117,15 @@ ModelCloneHelper.prototype._deepClone = function _deepClone(element) {
|
|||
});
|
||||
|
||||
forEach(properties, function(propName) {
|
||||
// check if the element has this property defined
|
||||
if (element[propName] !== undefined && (element[propName].$type || isArray(element[propName]))) {
|
||||
// check if the propertyElement has this property defined
|
||||
if (propertyElement[propName] !== undefined &&
|
||||
(propertyElement[propName].$type || isArray(propertyElement[propName]))) {
|
||||
|
||||
if (isArray(element[propName])) {
|
||||
if (isArray(propertyElement[propName])) {
|
||||
newProp[propName] = [];
|
||||
|
||||
forEach(element[propName], function(property) {
|
||||
var extProp = element.$model.getTypeDescriptor(property.$type),
|
||||
forEach(propertyElement[propName], function(property) {
|
||||
var extProp = propertyElement.$model.getTypeDescriptor(property.$type),
|
||||
newDeepProp;
|
||||
|
||||
// we're not going to copy undefined types
|
||||
|
@ -127,35 +134,36 @@ ModelCloneHelper.prototype._deepClone = function _deepClone(element) {
|
|||
}
|
||||
|
||||
var canClone = eventBus.fire('property.clone', {
|
||||
newElement: newElement,
|
||||
newElement: context.newElement,
|
||||
refTopLevelProperty: context.refTopLevelProperty,
|
||||
propertyDescriptor: extProp
|
||||
});
|
||||
|
||||
if (!canClone) {
|
||||
// if can clone is 'undefined' or 'false'
|
||||
// check for the meta information if it is allowed
|
||||
if (element.$type === 'bpmn:ExtensionElements' &&
|
||||
if (propertyElement.$type === 'bpmn:ExtensionElements' &&
|
||||
extProp.meta && extProp.meta.allowedIn &&
|
||||
!isAllowedIn(extProp, newElement.$type)) {
|
||||
!isAllowedIn(extProp, context.newElement.$type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
newDeepProp = this._deepClone(property);
|
||||
newDeepProp = this._deepClone(property, context);
|
||||
|
||||
newDeepProp.$parent = newProp;
|
||||
|
||||
newProp[propName].push(newDeepProp);
|
||||
}, this);
|
||||
|
||||
} else if (element[propName].$type) {
|
||||
newProp[propName] = this._deepClone(element[propName]);
|
||||
} else if (propertyElement[propName].$type) {
|
||||
newProp[propName] = this._deepClone(propertyElement[propName], context);
|
||||
|
||||
newProp[propName].$parent = newProp;
|
||||
}
|
||||
} else {
|
||||
// just assign directly if it's a value
|
||||
newProp[propName] = element[propName];
|
||||
newProp[propName] = propertyElement[propName];
|
||||
}
|
||||
}, this);
|
||||
|
||||
|
|
|
@ -276,16 +276,14 @@ describe('util/ModelCloneHelper', function() {
|
|||
newSubProcessExtElems = newSubProcess.extensionElements.values;
|
||||
|
||||
// then
|
||||
function expectTimeCycle(extElems) {
|
||||
expect(extElems[0].$type).to.equal('camunda:FailedJobRetryTimeCycle');
|
||||
expect(extElems[0].body).to.equal('foobar');
|
||||
}
|
||||
expect(intCatchEvtExtElems[0].$type).to.equal('camunda:FailedJobRetryTimeCycle');
|
||||
expect(intCatchEvtExtElems[0].body).to.equal('foobar');
|
||||
|
||||
expectTimeCycle(intCatchEvtExtElems);
|
||||
expect(startEvtExtElems[0].$type).to.equal('camunda:FailedJobRetryTimeCycle');
|
||||
expect(startEvtExtElems[0].body).to.equal('foobar');
|
||||
|
||||
expectTimeCycle(startEvtExtElems);
|
||||
|
||||
expectTimeCycle(newSubProcessExtElems);
|
||||
expect(newSubProcessExtElems[0].$type).to.equal('camunda:FailedJobRetryTimeCycle');
|
||||
expect(newSubProcessExtElems[0].body).to.equal('foobar');
|
||||
}));
|
||||
|
||||
|
||||
|
@ -298,10 +296,11 @@ describe('util/ModelCloneHelper', function() {
|
|||
|
||||
var extensionElements = moddle.create('bpmn:ExtensionElements', { values: [ connector ] });
|
||||
|
||||
var msgEvtDef = moddle.create('bpmn:MessageEventDefinition');
|
||||
var msgEvtDef = moddle.create('bpmn:MessageEventDefinition', {
|
||||
extensionElements: extensionElements
|
||||
});
|
||||
|
||||
var msgIntermThrowEvt = moddle.create('bpmn:IntermediateThrowEvent', {
|
||||
extensionElements: extensionElements,
|
||||
eventDefinitions: [ msgEvtDef ]
|
||||
});
|
||||
|
||||
|
@ -310,7 +309,7 @@ describe('util/ModelCloneHelper', function() {
|
|||
'bpmn:eventDefinitions'
|
||||
]);
|
||||
|
||||
var extElems = clonedElement.extensionElements.values;
|
||||
var extElems = clonedElement.eventDefinitions[0].extensionElements.values;
|
||||
|
||||
// then
|
||||
expect(extElems[0].$type).to.equal('camunda:Connector');
|
||||
|
@ -327,10 +326,11 @@ describe('util/ModelCloneHelper', function() {
|
|||
|
||||
var extensionElements = moddle.create('bpmn:ExtensionElements', { values: [ field ] });
|
||||
|
||||
var msgEvtDef = moddle.create('bpmn:MessageEventDefinition');
|
||||
var msgEvtDef = moddle.create('bpmn:MessageEventDefinition', {
|
||||
extensionElements: extensionElements
|
||||
});
|
||||
|
||||
var msgIntermThrowEvt = moddle.create('bpmn:IntermediateThrowEvent', {
|
||||
extensionElements: extensionElements,
|
||||
eventDefinitions: [ msgEvtDef ]
|
||||
});
|
||||
|
||||
|
@ -339,7 +339,7 @@ describe('util/ModelCloneHelper', function() {
|
|||
'bpmn:eventDefinitions'
|
||||
]);
|
||||
|
||||
var extElems = clonedElement.extensionElements.values;
|
||||
var extElems = clonedElement.eventDefinitions[0].extensionElements.values;
|
||||
|
||||
// then
|
||||
expect(extElems[0].$type).to.equal('camunda:Field');
|
||||
|
@ -356,10 +356,11 @@ describe('util/ModelCloneHelper', function() {
|
|||
|
||||
var extensionElements = moddle.create('bpmn:ExtensionElements', { values: [ field ] });
|
||||
|
||||
var msgEvtDef = moddle.create('bpmn:MessageEventDefinition');
|
||||
var msgEvtDef = moddle.create('bpmn:MessageEventDefinition', {
|
||||
extensionElements: extensionElements
|
||||
});
|
||||
|
||||
var msgIntermThrowEvt = moddle.create('bpmn:IntermediateThrowEvent', {
|
||||
extensionElements: extensionElements,
|
||||
eventDefinitions: [ msgEvtDef ]
|
||||
});
|
||||
|
||||
|
@ -367,10 +368,8 @@ describe('util/ModelCloneHelper', function() {
|
|||
'bpmn:extensionElements'
|
||||
]);
|
||||
|
||||
var extElems = clonedElement.extensionElements;
|
||||
|
||||
// then
|
||||
expect(extElems.values).be.empty;
|
||||
expect(clonedElement.eventDefinitions).to.be.empty;
|
||||
}));
|
||||
|
||||
});
|
||||
|
|
|
@ -41,27 +41,30 @@ function CamundaModdleExtension(eventBus) {
|
|||
|
||||
eventBus.on('property.clone', function(context) {
|
||||
var newElement = context.newElement,
|
||||
refTopLevelProperty = context.refTopLevelProperty,
|
||||
propDescriptor = context.propertyDescriptor;
|
||||
|
||||
return this.canCloneProperty(newElement, refTopLevelProperty, propDescriptor);
|
||||
}, this);
|
||||
}
|
||||
|
||||
CamundaModdleExtension.$inject = [ 'eventBus' ];
|
||||
|
||||
CamundaModdleExtension.prototype.canCloneProperty = function(newElement, refTopLevelProperty, propDescriptor) {
|
||||
|
||||
if (isAllowed('camunda:FailedJobRetryTimeCycle', propDescriptor, newElement)) {
|
||||
return includesType(newElement.eventDefinitions, 'bpmn:TimerEventDefinition') ||
|
||||
includesType(newElement.eventDefinitions, 'bpmn:SignalEventDefinition') ||
|
||||
is(newElement.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics');
|
||||
}
|
||||
|
||||
if (isAllowed('camunda:Connector', propDescriptor, newElement)) {
|
||||
return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition');
|
||||
if (isAllowed('camunda:Connector', propDescriptor, newElement) ||
|
||||
isAllowed('camunda:Field', propDescriptor, newElement)) {
|
||||
return is(refTopLevelProperty, 'bpmn:MessageEventDefinition');
|
||||
}
|
||||
|
||||
if (isAllowed('camunda:Field', propDescriptor, newElement)) {
|
||||
return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
CamundaModdleExtension.$inject = [ 'eventBus' ];
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
__init__: [ 'CamundaModdleExtension' ],
|
||||
CamundaModdleExtension: [ 'type', CamundaModdleExtension ]
|
||||
__init__: [ 'camundaModdleExtension' ],
|
||||
camundaModdleExtension: [ 'type', CamundaModdleExtension ]
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue