2018-04-02 19:01:53 +00:00
|
|
|
import inherits from 'inherits';
|
2016-01-05 23:28:01 +00:00
|
|
|
|
2018-04-02 19:01:53 +00:00
|
|
|
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
|
2016-01-05 23:28:01 +00:00
|
|
|
|
2018-04-02 19:01:53 +00:00
|
|
|
import {
|
|
|
|
add as collectionAdd,
|
|
|
|
remove as collectionRemove
|
|
|
|
} from 'diagram-js/lib/util/Collections';
|
2016-01-05 23:28:01 +00:00
|
|
|
|
2018-04-02 19:01:53 +00:00
|
|
|
import {
|
|
|
|
find
|
|
|
|
} from 'min-dash';
|
2016-01-05 23:28:01 +00:00
|
|
|
|
2018-04-02 19:01:53 +00:00
|
|
|
import {
|
|
|
|
is
|
|
|
|
} from '../../../util/ModelUtil';
|
2016-01-05 23:28:01 +00:00
|
|
|
|
|
|
|
var TARGET_REF_PLACEHOLDER_NAME = '__targetRef_placeholder';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This behavior makes sure we always set a fake
|
|
|
|
* DataInputAssociation#targetRef as demanded by the BPMN 2.0
|
|
|
|
* XSD schema.
|
|
|
|
*
|
|
|
|
* The reference is set to a bpmn:Property{ name: '__targetRef_placeholder' }
|
|
|
|
* which is created on the fly and cleaned up afterwards if not needed
|
|
|
|
* anymore.
|
|
|
|
*
|
|
|
|
* @param {EventBus} eventBus
|
|
|
|
* @param {BpmnFactory} bpmnFactory
|
|
|
|
*/
|
2018-04-02 19:01:53 +00:00
|
|
|
export default function DataInputAssociationBehavior(eventBus, bpmnFactory) {
|
2016-01-05 23:28:01 +00:00
|
|
|
|
|
|
|
CommandInterceptor.call(this, eventBus);
|
|
|
|
|
|
|
|
|
|
|
|
this.executed([
|
|
|
|
'connection.create',
|
|
|
|
'connection.delete',
|
|
|
|
'connection.move',
|
2019-11-14 07:52:19 +00:00
|
|
|
'connection.reconnect'
|
2016-01-05 23:28:01 +00:00
|
|
|
], ifDataInputAssociation(fixTargetRef));
|
|
|
|
|
|
|
|
this.reverted([
|
|
|
|
'connection.create',
|
|
|
|
'connection.delete',
|
|
|
|
'connection.move',
|
2019-11-14 07:52:19 +00:00
|
|
|
'connection.reconnect'
|
2016-01-05 23:28:01 +00:00
|
|
|
], ifDataInputAssociation(fixTargetRef));
|
|
|
|
|
|
|
|
|
|
|
|
function usesTargetRef(element, targetRef, removedConnection) {
|
|
|
|
|
|
|
|
var inputAssociations = element.get('dataInputAssociations');
|
|
|
|
|
|
|
|
return find(inputAssociations, function(association) {
|
|
|
|
return association !== removedConnection &&
|
|
|
|
association.targetRef === targetRef;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function getTargetRef(element, create) {
|
|
|
|
|
|
|
|
var properties = element.get('properties');
|
|
|
|
|
|
|
|
var targetRefProp = find(properties, function(p) {
|
|
|
|
return p.name === TARGET_REF_PLACEHOLDER_NAME;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!targetRefProp && create) {
|
|
|
|
targetRefProp = bpmnFactory.create('bpmn:Property', {
|
|
|
|
name: TARGET_REF_PLACEHOLDER_NAME
|
|
|
|
});
|
|
|
|
|
2018-04-02 19:01:53 +00:00
|
|
|
collectionAdd(properties, targetRefProp);
|
2016-01-05 23:28:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return targetRefProp;
|
|
|
|
}
|
|
|
|
|
|
|
|
function cleanupTargetRef(element, connection) {
|
|
|
|
|
|
|
|
var targetRefProp = getTargetRef(element);
|
|
|
|
|
|
|
|
if (!targetRefProp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!usesTargetRef(element, targetRefProp, connection)) {
|
2018-04-02 19:01:53 +00:00
|
|
|
collectionRemove(element.get('properties'), targetRefProp);
|
2016-01-05 23:28:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure targetRef is set to a valid property or
|
|
|
|
* `null` if the connection is detached.
|
|
|
|
*
|
|
|
|
* @param {Event} event
|
|
|
|
*/
|
|
|
|
function fixTargetRef(event) {
|
|
|
|
|
|
|
|
var context = event.context,
|
|
|
|
connection = context.connection,
|
|
|
|
connectionBo = connection.businessObject,
|
|
|
|
target = connection.target,
|
|
|
|
targetBo = target && target.businessObject,
|
|
|
|
newTarget = context.newTarget,
|
|
|
|
newTargetBo = newTarget && newTarget.businessObject,
|
|
|
|
oldTarget = context.oldTarget || context.target,
|
|
|
|
oldTargetBo = oldTarget && oldTarget.businessObject;
|
|
|
|
|
|
|
|
var dataAssociation = connection.businessObject,
|
|
|
|
targetRefProp;
|
|
|
|
|
|
|
|
if (oldTargetBo && oldTargetBo !== targetBo) {
|
|
|
|
cleanupTargetRef(oldTargetBo, connectionBo);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newTargetBo && newTargetBo !== targetBo) {
|
|
|
|
cleanupTargetRef(newTargetBo, connectionBo);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (targetBo) {
|
|
|
|
targetRefProp = getTargetRef(targetBo, true);
|
|
|
|
dataAssociation.targetRef = targetRefProp;
|
|
|
|
} else {
|
|
|
|
dataAssociation.targetRef = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-02 19:01:53 +00:00
|
|
|
DataInputAssociationBehavior.$inject = [
|
|
|
|
'eventBus',
|
|
|
|
'bpmnFactory'
|
|
|
|
];
|
2016-01-05 23:28:01 +00:00
|
|
|
|
|
|
|
inherits(DataInputAssociationBehavior, CommandInterceptor);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Only call the given function when the event
|
|
|
|
* touches a bpmn:DataInputAssociation.
|
|
|
|
*
|
|
|
|
* @param {Function} fn
|
|
|
|
* @return {Function}
|
|
|
|
*/
|
|
|
|
function ifDataInputAssociation(fn) {
|
|
|
|
|
|
|
|
return function(event) {
|
|
|
|
var context = event.context,
|
|
|
|
connection = context.connection;
|
|
|
|
|
|
|
|
if (is(connection, 'bpmn:DataInputAssociation')) {
|
|
|
|
return fn(event);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|