Source: sandbox.js

var async=require('async');

/**
 * @class
 * All executions in the system happen within a Sandbox. Every map and reduce function is executed here. All environment
 * initializations also happen within the sandbox. It holds the custom scope that every function is supposed to run on.
 * Also, the stream logger is set as a utility for the sandbox.
 */

function Sandbox(streamlogger) {
	this.cleanSandbox();
	this.initializeUtilities(streamlogger);
}
/**
 * Function to clean and reset the Sandbox
 */
Sandbox.prototype.cleanSandbox = function() {
	this.mapFunction = "";
	this.reduceFunction = "";
	this.array = [];
	this.options = {};
	this.scope = null;
};


/**
 * Function to initialize Sandbox for executing remote procedures
 * @function
 * @param  {Function} map    The map function that has to be executed
 * @param  {Function} reduce The reduce function that has to be executed on the server
 * @param  {JSON} scope  The custom scope that each function needs to be run on
 */

Sandbox.prototype.initializeSandbox = function(array, map, reduce, scope) {
	if(map && typeof map == 'string') {
		this.mapFunction = eval(map);
	}
	else this.mapFunction = map;
	if(reduce && typeof reduce == 'string') {
		this.reduceFunction = eval(reduce);
	}
	else this.reduceFunction = reduce;
	this.array = array;
	this.scope = scope;
};
/**
 * Function to initialize Sandbox for the Parallel functionality, which does not contain an array.
 * @function
 * @param  {Function} map    The map function that has to be executed
 * @param  {Function} reduce The reduce function that has to be executed on the server
 * @param  {JSON} scope  The custom scope that each function needs to be run on
 */
Sandbox.prototype.initializeParallelSandbox = function(map, reduce, scope) {
	if(map && typeof map == 'string') {
		this.mapFunction = eval(map);
	}
	else this.mapFunction = map;
	if(reduce && typeof reduce == 'string') {
		this.reduceFunction = eval(reduce);
	}
	else this.reduceFunction = reduce;
	this.scope = scope;
}


/**
 * Setter for the array variable
 * @param {Array} array The array to be set
 */
Sandbox.prototype.setArray = function(array) {
	this.array = array;
};

 /**
 * Getter to get the data which will be emitted to other sockets
 * @function
 * @return {JSON} data The data that needs to be emitted. The Map, Reduce and the Scope
 */
Sandbox.prototype.getSandboxEmitData = function() {
	var data = {
		mapFunction: this.mapFunction.toString(),
		reduceFunction: this.reduceFunction.toString(),
		scope: this.scope
	};
	return data;
};
/**
* Function to initialize Sandbox for executing remote procedures
* @function
* @param {JSON} data The data object that contains the map and reduce functions along with scope.
* @param {function} finalCallback The final callback to be called.
*/
Sandbox.prototype.initializeEnvironment = function(data, finalCallback) {
	map = data.mapFunction;
  reduce = data.reduceFunction;
	var i = 0;
	var func_arr = []
	if (data.array) {
		for (i = 0; i < data.array.length; i++) {
			func_arr.push(eval('('+data.arrn[i]+')'));
		}
	}
	scope = data.scope;
	if (map && typeof map == 'string') {
		this.mapFunction=eval('('+map+')');
	}
	else this.mapFunction = map;
	if (reduce && typeof reduce == 'string') {
		this.reduceFunction=eval('('+reduce+')');
	}
	else this.reduceFunction = reduce;
	if (data.array) {
		this.array = data.array;
	}
	this.arrn = func_arr;
	finalCallback();
};

/**
 * Trigger to execute the Map Function
 * @param  {Function} finalCallback Callback called at the end of the Map Function execution. Returns err and results
 */
Sandbox.prototype.executeMapFunction = function(finalCallback) {
	if (this.array.length == 0) {
		async.series([this.mapFunction.bind(this.utilities), finalCallback]);
	}
	else {
		var i = 0;
		if (this.array[0] != null) {
			async.map.call({}, this.array, this.mapFunction.bind(this.utilities), finalCallback);
		}
		else{
			var i = 0;
		  for (i = 0; i < this.arrn.length; i++) {
				this.arrn[i] = this.arrn[i].bind(this.utilities)
			}
			async.series(this.arrn, function() {
				finalCallback();
			});
		}
	}
};
/**
 * Trigger to execute the Reduce Function
 * @param  {object} err The error object.
 * @param  {object} results The results object.
 * @param  {Function} finalCallback Callback called at the end of the Reduce Function execution.
 */
Sandbox.prototype.executeReduceFunction = function(err, results, finalCallback) {
	this.reduceFunction.call(this.scope, err, results);
	finalCallback();
};
/**
 * Function to set the stream logger as a utility
 * @param  {Object} streamlogger The stream logger object.
 */
Sandbox.prototype.initializeUtilities = function(streamlogger) {
	this.utilities = {
		logger: streamlogger
	}
}
module.exports = Sandbox;