'use strict'; var is = require('bpmn-js/lib/util/ModelUtil').is, isAny = require('bpmn-js/lib/features/modeling/util/ModelingUtil').isAny, getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject; var filter = require('lodash/filter'); var extensionElementsHelper = require('../../../helper/ExtensionElementsHelper'), cmdHelper = require('../../../helper/CmdHelper'), elementHelper = require('../../../helper/ElementHelper'), eventDefinitionHelper = require('../../../helper/EventDefinitionHelper'); var extensionElementsEntry = require('./implementation/ExtensionElements'); var entryFactory = require('../../../factory/EntryFactory'); /** * return depend on parameter 'type' activiti:in or activiti:out extension elements */ function getActivitiInOutMappings(element, type) { var bo = getBusinessObject(element); var signalEventDefinition = eventDefinitionHelper.getSignalEventDefinition(bo); return extensionElementsHelper.getExtensionElements(signalEventDefinition || bo, type) || []; } /** * return depend on parameter 'type' activiti:in or activiti:out extension elements * with source or sourceExpression attribute */ function getVariableMappings(element, type) { var activitiMappings = getActivitiInOutMappings(element, type); return filter(activitiMappings, function(mapping) { return !mapping.businessKey; }); } function getInOutType(mapping) { var inOutType = 'source'; if (mapping.variables === 'all') { inOutType = 'variables'; } else if (typeof mapping.source !== 'undefined') { inOutType = 'source'; } else if (typeof mapping.sourceExpression !== 'undefined') { inOutType = 'sourceExpression'; } return inOutType; } var ACTIVITI_IN_EXTENSION_ELEMENT = 'activiti:In', ACTIVITI_OUT_EXTENSION_ELEMENT = 'activiti:Out'; var WHITESPACE_REGEX = /\s/; module.exports = function(group, element, bpmnFactory, translate) { var inOutTypeOptions = [ { name: translate('Source'), value: 'source' }, { name: translate('Source Expression'), value: 'sourceExpression' }, { name: translate('All'), value: 'variables' } ]; var signalEventDefinition = eventDefinitionHelper.getSignalEventDefinition(element); if (!is(element, 'activiti:CallActivity') && !signalEventDefinition) { return; } if (signalEventDefinition && !(isAny(element, [ 'bpmn:IntermediateThrowEvent', 'bpmn:EndEvent' ]))) { return; } var isSelected = function(element, node) { return !!getSelected(element, node); }; var getSelected = function(element, node) { var parentNode = node.parentNode; var selection = inEntry.getSelected(element, parentNode); var parameter = getVariableMappings(element, ACTIVITI_IN_EXTENSION_ELEMENT)[selection.idx]; if (!parameter && outEntry) { selection = outEntry.getSelected(element, parentNode); parameter = getVariableMappings(element, ACTIVITI_OUT_EXTENSION_ELEMENT)[selection.idx]; } return parameter; }; var setOptionLabelValue = function(type) { return function(element, node, option, property, value, idx) { var variableMappings = getVariableMappings(element, type); var mappingValue = variableMappings[idx]; var label = (mappingValue.target || '') + ' := '; var mappingType = getInOutType(mappingValue); if (mappingType === 'variables') { label = 'all'; } else if (mappingType === 'source') { label = label + (mappingValue.source || ''); } else if (mappingType === 'sourceExpression') { label = label + (mappingValue.sourceExpression || ''); } else { label = label + ''; } option.text = label; }; }; var newElement = function(type) { return function(element, extensionElements, value) { var newElem = elementHelper.createElement(type, { source: '' }, extensionElements, bpmnFactory); return cmdHelper.addElementsTolist(element, extensionElements, 'values', [ newElem ]); }; }; var removeElement = function(type) { return function(element, extensionElements, value, idx) { var variablesMappings= getVariableMappings(element, type); var mapping = variablesMappings[idx]; if (mapping) { return extensionElementsHelper .removeEntry(signalEventDefinition || getBusinessObject(element), element, mapping); } }; }; // in mapping for source and sourceExpression /////////////////////////////////////////////////////////////// var inEntry = extensionElementsEntry(element, bpmnFactory, { id: 'variableMapping-in', label: translate('In Mapping'), modelProperty: 'source', prefix: 'In', idGeneration: false, resizable: true, businessObject: signalEventDefinition || getBusinessObject(element), createExtensionElement: newElement(ACTIVITI_IN_EXTENSION_ELEMENT), removeExtensionElement: removeElement(ACTIVITI_IN_EXTENSION_ELEMENT), getExtensionElements: function(element) { return getVariableMappings(element, ACTIVITI_IN_EXTENSION_ELEMENT); }, onSelectionChange: function(element, node, event, scope) { outEntry && outEntry.deselect(element, node.parentNode); }, setOptionLabelValue: setOptionLabelValue(ACTIVITI_IN_EXTENSION_ELEMENT) }); group.entries.push(inEntry); // out mapping for source and sourceExpression /////////////////////////////////////////////////////// if (!signalEventDefinition) { var outEntry = extensionElementsEntry(element, bpmnFactory, { id: 'variableMapping-out', label: translate('Out Mapping'), modelProperty: 'source', prefix: 'Out', idGeneration: false, resizable: true, createExtensionElement: newElement(ACTIVITI_OUT_EXTENSION_ELEMENT), removeExtensionElement: removeElement(ACTIVITI_OUT_EXTENSION_ELEMENT), getExtensionElements: function(element) { return getVariableMappings(element, ACTIVITI_OUT_EXTENSION_ELEMENT); }, onSelectionChange: function(element, node, event, scope) { inEntry.deselect(element, node.parentNode); }, setOptionLabelValue: setOptionLabelValue(ACTIVITI_OUT_EXTENSION_ELEMENT) }); group.entries.push(outEntry); } // label for selected mapping /////////////////////////////////////////////////////// group.entries.push(entryFactory.label({ id: 'variableMapping-typeLabel', get: function(element, node) { var mapping = getSelected(element, node); var value = ''; if (is(mapping, ACTIVITI_IN_EXTENSION_ELEMENT)) { value = translate('In Mapping'); } else if (is(mapping, ACTIVITI_OUT_EXTENSION_ELEMENT)) { value = translate('Out Mapping'); } return { label: value }; }, showLabel: function(element, node) { return isSelected(element, node); } })); group.entries.push(entryFactory.selectBox({ id: 'variableMapping-inOutType', label: translate('Type'), selectOptions: inOutTypeOptions, modelProperty: 'inOutType', get: function(element, node) { var mapping = getSelected(element, node) || {}; return { inOutType: getInOutType(mapping) }; }, set: function(element, values, node) { var inOutType = values.inOutType; var props = { 'source' : undefined, 'sourceExpression' : undefined, 'variables' : undefined }; if (inOutType === 'source') { props.source = ''; } else if (inOutType === 'sourceExpression') { props.sourceExpression = ''; } else if (inOutType === 'variables') { props.variables = 'all'; props.target = undefined; } var mapping = getSelected(element, node); return cmdHelper.updateBusinessObject(element, mapping, props); }, hidden: function(element, node) { return !isSelected(element, node); } })); group.entries.push(entryFactory.textField({ id: 'variableMapping-source', dataValueLabel: 'sourceLabel', modelProperty: 'source', get: function(element, node) { var mapping = getSelected(element, node) || {}; var label = ''; var inOutType = getInOutType(mapping); if (inOutType === 'source') { label = translate('Source'); } else if (inOutType === 'sourceExpression') { label = translate('Source Expression'); } return { source: mapping[inOutType], sourceLabel: label }; }, set: function(element, values, node) { values.source = values.source || undefined; var mapping = getSelected(element, node); var inOutType = getInOutType(mapping); var props = {}; props[inOutType] = values.source || ''; return cmdHelper.updateBusinessObject(element, mapping, props); }, // one of both (source or sourceExpression) must have a value to make // the configuration easier and more understandable // it is not engine conform validate: function(element, values, node) { var mapping = getSelected(element, node); var validation = {}; if (mapping) { if (!values.source) { validation.source = validation.source = values.sourceLabel ? translate('Mapping must have a {value}', { value: values.sourceLabel.toLowerCase() }) : translate('Mapping must have a value'); } var inOutType = getInOutType(mapping); if (WHITESPACE_REGEX.test(values.source) && inOutType !== 'sourceExpression') { validation.source = translate('{label} must not contain whitespace', { label: values.sourceLabel }); } } return validation; }, hidden: function(element, node) { var selectedMapping = getSelected(element, node); return !selectedMapping || (selectedMapping && selectedMapping.variables); } })); group.entries.push(entryFactory.textField({ id: 'variableMapping-target', label: translate('Target'), modelProperty: 'target', get: function(element, node) { return { target: (getSelected(element, node) || {}).target }; }, set: function(element, values, node) { values.target = values.target || undefined; var mapping = getSelected(element, node); return cmdHelper.updateBusinessObject(element, mapping, values); }, validate: function(element, values, node) { var mapping = getSelected(element, node); var validation = {}; if (mapping) { var mappingType = getInOutType(mapping); if (!values.target && mappingType !== 'variables') { validation.target = translate('Mapping must have a target'); } if (values.target && WHITESPACE_REGEX.test(values.target) && mappingType !== 'variables') { validation.target = translate('Target must not contain whitespace'); } } return validation; }, hidden: function(element, node) { var selectedMapping = getSelected(element, node); return !selectedMapping || (selectedMapping && selectedMapping.variables); } })); group.entries.push(entryFactory.checkbox({ id: 'variableMapping-local', label: translate('Local'), modelProperty: 'local', get: function(element, node) { return { local: (getSelected(element, node) || {}).local }; }, set: function(element, values, node) { values.local = values.local || false; var mapping = getSelected(element, node); return cmdHelper.updateBusinessObject(element, mapping, values); }, hidden: function(element, node) { return !isSelected(element, node); } })); };