Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions lib/Context.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Context.prototype.applyMessage = function(message) {

Context.prototype.getLoopCharacteristics = function(loopCharacteristics) {
if (!loopCharacteristics) return;
return new (mapper(loopCharacteristics.$type))(loopCharacteristics, this);
return new (mapper.fromType(loopCharacteristics.$type))(loopCharacteristics, this);
};

Context.prototype.getState = function() {
Expand Down Expand Up @@ -138,7 +138,7 @@ Context.prototype.getElementService = function(element) {
const contextService = contextHelper.getElementService(element);
if (!contextService) return;
if (contextService.connector) {
return new (mapper(contextService.connector.$type))(contextService.connector, this);
return new (mapper.fromType(contextService.connector.$type))(contextService.connector, this);
}
return new mapper.ServiceConnector(contextService, this);
};
Expand Down Expand Up @@ -167,11 +167,13 @@ function getService(serviceDef) {
return serviceDef;
} else if (!serviceDef.module) {
return module;
} else if (!serviceDef.type || serviceDef.type === 'require') {
module = require(getRelativePath(serviceDef.module));
} else { // global
module = serviceDef.module === 'require' ? require : global[serviceDef.module];
}
// remove dynamic require to support react native
// else if (!serviceDef.type || serviceDef.type === 'require') {
// module = require(getRelativePath(serviceDef.module));
// } else { // global
// module = serviceDef.module === 'require' ? require : global[serviceDef.module];
// }

if (serviceDef.fnName) {
module = module[serviceDef.fnName];
Expand All @@ -189,7 +191,7 @@ function loadSequenceFlows(scopeId) {
this.sequenceFlows = [];
this.messageFlows = [];
return contextHelper.getAllOutboundSequenceFlows(this.moddleContext, scopeId).map((sf) => {
const Flow = mapper(sf.element.$type);
const Flow = mapper.fromType(sf.element.$type);
const flow = new Flow(sf, this);

this.sequenceFlows.push(flow);
Expand Down Expand Up @@ -221,7 +223,7 @@ function loadChildren(scopeId) {

function createChildById(id, context, options) {
const activityDefinition = this.moddleContext.elementsById[id];
const ChildActivity = mapper(activityDefinition.$type);
const ChildActivity = mapper.fromType(activityDefinition.$type);
return new ChildActivity(activityDefinition, context, options);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/activities/BaseProcess.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ BaseProcess.prototype.onMessage = function(message, via) {
};

BaseProcess.prototype.onFlowDiscarded = function(flow) {
emitListenerEvent.call(this, 'discared', flow);
emitListenerEvent.call(this, 'discarded', flow);
};

BaseProcess.prototype.onFlowTaken = function(flow) {
Expand Down
41 changes: 41 additions & 0 deletions lib/activities/BaseTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,45 @@ function getLoopCallback(loopDef, executionContext, inboundMessage, callback) {
};
}

const keyValueMapper = {
'properties': {
key: 'name',
value: 'value'
},
'formData': {
key: 'id',
value: 'defaultValue'
}
};

// type = properties/formData
function getValues(activity, type) {
const dataByType = getExtensions(activity, type)
return dataByType
? dataByType.reduce((acc, value) =>
Object.assign(acc, {[value[keyValueMapper[type].key]]: value[keyValueMapper[type].value]})
, {})
: {};
}

function getExtensions(activity, type) {
const dataByType = activity.extensionElements.values.find(value => value.$type === `camunda:${type}`);
return dataByType
? dataByType.$children
: [];
}

BaseTask.prototype.getFormData = function() {
return getExtensions(this.activity, 'formData');
};

BaseTask.prototype.getProperties = function() {
if (!this.activity.extensionElements) return;
return getValues(this.activity, 'properties');
};

BaseTask.prototype.getInputParameter = function() {
return getExtensions(this.activity, 'inputParameter');
};

module.exports = BaseTask;
2 changes: 1 addition & 1 deletion lib/activities/BoundaryEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const mapper = require('../mapper');

function BoundaryEvent(activity) {
const ctorArgs = Array.prototype.slice.call(arguments);
const Type = mapper(activity.eventDefinitions[0].$type);
const Type = mapper.fromType(activity.eventDefinitions[0].$type);
const event = new (Function.prototype.bind.apply(Type, [null].concat(ctorArgs)))();
return event;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/activities/IntermediateCatchEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const mapper = require('../mapper');

function IntermediateCatchEvent(activity) {
const ctorArgs = Array.prototype.slice.call(arguments);
const Type = mapper(activity.eventDefinitions[0].$type);
const Type = mapper.fromType(activity.eventDefinitions[0].$type);
const event = new (Function.prototype.bind.apply(Type, [null].concat(ctorArgs)))();
return event;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/activities/MultiInstanceLoopCharacteristics.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ MultiInstanceLoopCharacteristics.prototype.run = function(variables, message, re

if (this.characteristics.collection) {
const collection = this.getCollection(variables);
if (this.iteration > collection.length) {
if ( collection.length <= 1) {
this.completed = true;
debug('completed collection', this.completed);
} else {
this.item = collection[this.iteration];
this.item = collection[0];
}
}

Expand Down
11 changes: 9 additions & 2 deletions lib/expressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const getPropertyValue = require('./getPropertyValue');

const isExpressionPattern = /^\${(.+?)}$/;
const expressionPattern = /\${(.+?)}/;
const expressionCondition = /[><!=]/;

function resolveExpressions(templatedString, context) {
let result = templatedString;
Expand All @@ -17,13 +18,19 @@ function resolveExpressions(templatedString, context) {
return false;
}

const contextValue = getPropertyValue(context, innerProperty);
let contextValue = getPropertyValue(context, innerProperty);

if (expressionMatch.input === expressionMatch[0]) {
return contextValue;
}

result = result.replace(expressionMatch[0], contextValue === undefined ? '' : contextValue);
if (typeof contextValue === 'string') {
contextValue = '"' + contextValue + '"';
}
result = result.replace(expressionMatch[0], contextValue === undefined ? '' : contextValue );
}
if (expressionCondition.test(result)) {
return eval(result);
}
return result;
}
Expand Down
10 changes: 6 additions & 4 deletions lib/mapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const activityTypes = {};

module.exports = function fromType(type) {
module.exports.fromType = function fromType(type) {
const activityType = activityTypes[type];

if (!activityType) {
Expand All @@ -17,9 +17,6 @@ module.exports.isTask = function(type) {
return /task$/i.test(type);
};

module.exports.Definition = activityTypes['bpmn:Definition'] = require('./Definition');
module.exports.Process = activityTypes['bpmn:Process'] = require('./activities/BaseProcess');

activityTypes['bpmn:SequenceFlow'] = require('./activities/SequenceFlow');
activityTypes['bpmn:MessageFlow'] = require('./activities/MessageFlow');

Expand Down Expand Up @@ -49,7 +46,12 @@ activityTypes['bpmn:MultiInstanceLoopCharacteristics'] = require('./activities/M
activityTypes['bpmn:DataObjectReference'] = require('./activities/Dummy');
activityTypes['bpmn:DataObject'] = require('./activities/Dummy');

module.exports.Definition = activityTypes['bpmn:Definition'] = require('./Definition');
module.exports.Process = activityTypes['bpmn:Process'] = require('./activities/BaseProcess');

module.exports.ActivityIO = activityTypes ['camunda:inputOutput'] = require('./activities/InputOutput');
module.exports.ActivityProperties = activityTypes ['camunda:properties'] = require('./activities/Properties');
module.exports.Form = activityTypes['camunda:formData'] = require('./activities/Form');
module.exports.ServiceConnector = activityTypes['camunda:Connector'] = require('./activities/ServiceConnector');


2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "bpmn-engine",
"description": "BPMN 2.0 execution engine. Open source javascript workflow engine.",
"version": "4.1.2",
"version": "4.2.0",
"author": "Pål Edman <pal.edman@gmail.com> (https://github.com/paed01)",
"main": "index.js",
"repository": {
Expand Down
4 changes: 2 additions & 2 deletions test/activities/BoundaryEvent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ const testHelpers = require('../helpers/testHelpers');

const lab = exports.lab = Lab.script();
const Bpmn = require('../..');
const TimerEvent = require('../../lib/mapper')('bpmn:TimerEventDefinition');
const ErrorEvent = require('../../lib/mapper')('bpmn:ErrorEventDefinition');
const TimerEvent = require('../../lib/mapper').fromType('bpmn:TimerEventDefinition');
const ErrorEvent = require('../../lib/mapper').fromType('bpmn:ErrorEventDefinition');

lab.experiment('BoundaryEvent', () => {
lab.test('supports TimerEvent type', (done) => {
Expand Down
4 changes: 2 additions & 2 deletions test/activities/IntermediateCatchEvent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ const Bpmn = require('../..');
const expect = Code.expect;

const mapper = require('../../lib/mapper');
const TimerEvent = mapper('bpmn:TimerEventDefinition');
const MessageEvent = mapper('bpmn:MessageEventDefinition');
const TimerEvent = mapper.fromType('bpmn:TimerEventDefinition');
const MessageEvent = mapper.fromType('bpmn:MessageEventDefinition');

lab.experiment('IntermediateCatchEvent', () => {
lab.test('TimerEvent', (done) => {
Expand Down
2 changes: 1 addition & 1 deletion test/activities/MultiInstanceLoopCharacteristics-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const Lab = require('lab');
const lab = exports.lab = Lab.script();
const expect = Code.expect;

const MultiInstanceLoopCharacteristics = require('../../lib/mapper')('bpmn:MultiInstanceLoopCharacteristics');
const MultiInstanceLoopCharacteristics = require('../../lib/mapper').fromType('bpmn:MultiInstanceLoopCharacteristics');

lab.experiment('MultiInstanceLoopCharacteristics', () => {

Expand Down
2 changes: 1 addition & 1 deletion test/activities/SequenceFlow-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const EventEmitter = require('events').EventEmitter;
const factory = require('../helpers/factory');
const Lab = require('lab');
const testHelper = require('../helpers/testHelpers');
const SequenceFlow = require('../../lib/mapper')('bpmn:SequenceFlow');
const SequenceFlow = require('../../lib/mapper').fromType('bpmn:SequenceFlow');

const lab = exports.lab = Lab.script();
const expect = Code.expect;
Expand Down
6 changes: 3 additions & 3 deletions test/mapper-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ const mapper = require('../lib/mapper');

lab.experiment('mapper', () => {
lab.test('returns Bpmn instance type from context', (done) => {
const event = mapper('bpmn:StartEvent');
const event = mapper.fromType('bpmn:StartEvent');
expect(event).to.be.a.function();
done();
});

lab.test('throws if Bpmn instance type is not mapped', (done) => {
expect(() => {
mapper('bpmn:NonExisting');
mapper.fromType('bpmn:NonExisting');
}).to.throw();
done();
});

lab.test('if $type is missing from input', (done) => {
expect(() => {
mapper({});
mapper.fromType({});
}).to.throw(Error);
done();
});
Expand Down
8 changes: 4 additions & 4 deletions test/resume-task-loop-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ lab.experiment('Resume task loop', () => {
<process id="taskLoopProcess" isExecutable="true">
<task id="recurring" name="Recurring">
<multiInstanceLoopCharacteristics isSequential="true">
<loopCardinality xsi:type="tFormalExpression">5</loopCardinality>
<loopCardinality xsi:type="tFormalExpression">8</loopCardinality>
</multiInstanceLoopCharacteristics>
</task>
</process>
Expand Down Expand Up @@ -57,7 +57,7 @@ lab.experiment('Resume task loop', () => {
engine2.once('end', () => {
testHelpers.expectNoLingeringListenersOnEngine(engine2);

expect(startCount).to.equal(5);
expect(startCount).to.equal(8);
done();
});
});
Expand Down Expand Up @@ -100,7 +100,7 @@ lab.experiment('Resume task loop', () => {
const options = {
listener: listener1,
variables: {
list: [7, 3, 2, 1]
list: [9, 8, 7, 6, 5, 4, 3, 2, 1]
},
services: {
loop: {
Expand All @@ -125,7 +125,7 @@ lab.experiment('Resume task loop', () => {
});

engine2.once('end', (def) => {
expect(def.processes[0].variables.taskInput.recurring[0]).to.equal(13);
expect(def.processes[0].variables.taskInput.recurring[0]).to.equal(45);
done();
});

Expand Down
4 changes: 2 additions & 2 deletions test/tasks/ScriptTask-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ lab.experiment('ScriptTask', () => {
};

function test() {
new (mapper(activity.$type))(activity); // eslint-disable-line no-new
new (mapper.fromType(activity.$type))(activity); // eslint-disable-line no-new
}

expect(test).to.throw(Error, /Java is unsupported/i);
Expand All @@ -34,7 +34,7 @@ lab.experiment('ScriptTask', () => {
};

function test() {
new (mapper(activity.$type))(activity); // eslint-disable-line no-new
new (mapper.fromType(activity.$type))(activity); // eslint-disable-line no-new
}

expect(test).to.throw(Error, /undefined is unsupported/i);
Expand Down
2 changes: 1 addition & 1 deletion test/tasks/ServiceTask-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const BaseProcess = require('../../lib/mapper').Process;
const bpmnModdle = new BpmnModdle({
camunda: require('camunda-bpmn-moddle/resources/camunda')
});
const ServiceTask = mapper('bpmn:ServiceTask');
const ServiceTask = mapper.fromType('bpmn:ServiceTask');

const bupServiceFn = testHelpers.serviceFn;

Expand Down
12 changes: 6 additions & 6 deletions test/tasks/task-loop-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,14 +381,14 @@ lab.experiment('task loop', () => {
}
},
variables: {
input: [1, 2, 3, 7]
input: [1, 2, 3, 7, 9]
}
}, (err, instance) => {
if (err) return done(err);

instance.once('end', () => {
expect(startCount).to.equal(4);
expect(instance.variables.sum).to.equal(13);
expect(startCount).to.equal(5);
expect(instance.variables.sum).to.equal(22);
testHelpers.expectNoLingeringListenersOnDefinition(instance);
done();
});
Expand Down Expand Up @@ -431,21 +431,21 @@ lab.experiment('task loop', () => {

const result = prevResult + executionContext.item;

if (result > 2) {
if (result > 6) {
return callback(new Error('Too much'));
}

callback(null, result);
}
},
variables: {
input: [1, 2, 3, 7]
input: [1, 2, 3, 7, 9]
}
}, (err, instance) => {
if (err) return done(err);

instance.once('end', () => {
expect(startCount).to.equal(2);
expect(startCount).to.equal(4);
testHelpers.expectNoLingeringListenersOnDefinition(instance);
done();
});
Expand Down