pipeline.js

MultiWaySwitch

function
MultiWaySwitch()

Option name Type Description
Object onfi

configuration object

Each time split context for current step and use it in current stage

config as Object

  • condition
    desicion function or boolean condition
    used to decide what way to go.

  • success
    Stage or stage function to run in case of successful evaluation of condition

  • failed
    Stage or stage function to run in case of failure evaluation of condition

other confguration as Stage because it is its child Class.

if cases have no declaration for split configured or default will be used

function MultiWaySwitch(config) {

	var self = this;

	if (!(self instanceof MultiWaySwitch)) {
		throw new Error('constructor is not a function');
	}

	if (config && config.run instanceof Function) {
		config.stage = new Stage(config.run);
		delete config.run;
	}

	Stage.apply(self, arguments);

	if (!config) {
		config = {};
	}

	if (config instanceof Array) {
		config = {
			cases: config
		};
	}
	self.cases = config.cases ? config.cases : [];

	if (config.split instanceof Function) {
		self.split = config.split;
	}

	if (config.combine instanceof Function) {
		self.combine = config.combine;
	}

	self.name = config.name;
	if (!self.name) {
		self.name = [];
	}
}

cases

property
MultiWaySwitch.prototype.cases

internal declaration fo store different cases

MultiWaySwitch.prototype.cases = undefined;

split

method
MultiWaySwitch.prototype.split()

Option name Type Description
Context t

soure context to be splitted

default implementation fo split for case

MultiWaySwitch.prototype.split = function(ctx) {
	return ctx;
};

combine

method
MultiWaySwitch.prototype.combine()

Option name Type Description
Context t

original contect

Context t

case-stage resulting context

default implementation fo combine for case

MultiWaySwitch.prototype.combine = function(ctx, resCtx) {
	return resCtx;
};

reportName

method
MultiWaySwitch.prototype.reportName()

internal declaration fo reportName

MultiWaySwitch.prototype.reportName = function() {
	var self = this;
	return "MWS:" + self.name;
};

compile

method
MultiWaySwitch.prototype.compile()

overrides inherited compile

MultiWaySwitch.prototype.compile = function() {
	var self = this;
	var i;

	var len = self.cases.length;
	var caseItem;
	var statics = [];
	var dynamics = [];
	var nameUndefined = (Array.isArray(self.name) || !self.name);
	if (nameUndefined) {
		self.name = [];
	}

	// Apply to each stage own environment: evaluate, split, combine
	for (i = 0; i < len; i++) {
		caseItem = self.cases[i];
		
		if (caseItem instanceof Function) {
			caseItem = {
				stage: new Stage(caseItem),
				evaluate: true
			};
		}

		if (caseItem instanceof Stage) {
			caseItem = {
				stage: caseItem,
				evaluate: true
			};
		}

		if (caseItem.stage) {
			if (caseItem.stage instanceof Function) {
				caseItem.stage = new Stage(caseItem.stage);
			}
			if (!(caseItem.stage instanceof Stage) && (caseItem.stage instanceof Object)) {
				caseItem.stage = new Stage(caseItem.stage);
			}
			if (!(caseItem.split instanceof Function)) {
				caseItem.split = self.split;
			}
			if (!(caseItem.combine instanceof Function)) {
				caseItem.combine = self.combine;
			}
			if (typeof caseItem.evaluate === 'function') {
				dynamics.push(caseItem);
			} else {
				if (typeof caseItem.evaluate === 'boolean' && caseItem.evaluate) {
					statics.push(caseItem);
				}
			}
		}
		if (nameUndefined) {
			self.name.push(caseItem.stage.reportName());
		}
	}

	if (nameUndefined) self.name = self.name.join('|');

	var run = function(err, ctx, done) {
		var i;
		var len = dynamics.length;
		var actuals = [];
		actuals.push.apply(actuals, statics);

		for (i = 0; i < len; i++) {
			if (dynamics[i].evaluate(ctx)) {
				actuals.push(dynamics[i]);
			}
		}
		len = actuals.length;
		var iter = 0;

		var errors = [];

		function finish() {
			if (errors.length > 0) {
				done(new ErrorList(errors));
			} else {
				done();
			}
		}
		
		var next = function(index) {

			function logError(err) {
				errors.push({
					index: index,
					err: err
				});
			}

			return function(err, retCtx) {
				iter++;
				var cur = actuals[index];
				if (err) {
					logError(err);
				} else {
					cur.combine(ctx, retCtx);
				}
				if (iter >= len) {
					finish();
				}
			};
		};
		var stg;
		for (i = 0; i < len; i++) {
			stg = actuals[i];
			stg.stage.execute(ctx.ensureIsChild(stg.split(ctx)), next(i));
		}

		if (len === 0) {
			finish();
		}
	};
	self.run = run;
};

execute

method
MultiWaySwitch.prototype.execute()

Option name Type Description
context Context

evaluating context

[callback] Context

returning callback

override of execute
!!!Note!!! Errors that will be returned to callback will be stored in array

MultiWaySwitch.prototype.execute = function(context, callback) {
	var self = this;
	if (!self.run) {
		self.compile();
	}
	MultiWaySwitch.super_.prototype.execute.apply(self, arguments);
};