// Generated by CoffeeScript 1.7.1 /* Engine ================== > The heart of the WebAPI ECA System. The engine loads action invoker modules > corresponding to active rules actions and invokes them if an appropriate event > is retrieved. */ (function() { var db, dynmod, exports, isRunning, jsonQuery, listUserRules, pollQueue, processEvent, updateActionModules, validConditions; db = require('./persistence'); dynmod = require('./dynamic-modules'); jsonQuery = require('js-select'); listUserRules = {}; isRunning = false; /* Module call ----------- Initializes the Engine and starts polling the event queue for new events. @param {Object} args */ exports = module.exports = (function(_this) { return function(args) { if (!isRunning) { isRunning = true; _this.log = args.logger; db(args); dynmod(args); pollQueue(); return module.exports; } }; })(this); /* This is a helper function for the unit tests so we can verify that action modules are loaded correctly *TODO we should change this to functions returning true or false rather than returning *the whole list @public getListUserRules () */ exports.getListUserRules = function() { return listUserRules; }; /* An event associated to rules happened and is captured here. Such events are basically CRUD on rules. @public internalEvent ( *evt* ) @param {Object} evt */ exports.internalEvent = (function(_this) { return function(evt) { var oRule, oUser; if (!listUserRules[evt.user] && evt.event !== 'del') { listUserRules[evt.user] = { rules: {}, actions: {} }; } oUser = listUserRules[evt.user]; oRule = evt.rule; if (evt.event === 'new' || (evt.event === 'init' && !oUser.rules[oRule.id])) { oUser.rules[oRule.id] = oRule; updateActionModules(oRule, false); } if (evt.event === 'del' && oUser) { delete oUser.rules[oRule.id]; return updateActionModules(oRule, true); } }; })(this); /* As soon as changes were made to the rule set we need to ensure that the aprropriate action invoker modules are loaded, updated or deleted. @private updateActionModules ( *oNewRule* ) @param {Object} oNewRule */ updateActionModules = function(oNewRule, isDeleteOp) { var fAddRequired, fRemoveNotRequired, name, oUser, userName, _results; fRemoveNotRequired = function(oUser) { var action, fRequired, req, _results; fRequired = function(actionName) { var action, mod, nmRl, oRl, _i, _len, _ref, _ref1; _ref = oUser.rules; for (nmRl in _ref) { oRl = _ref[nmRl]; _ref1 = oRl.actions; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { action = _ref1[_i]; mod = (action.split(' -> '))[0]; if (mod === actionName) { return true; } } } return false; }; _results = []; for (action in oUser.actions) { req = fRequired(action); if (!req) { _results.push(delete oUser.actions[action]); } else { _results.push(void 0); } } return _results; }; for (name in listUserRules) { oUser = listUserRules[name]; fRemoveNotRequired(oUser); } fAddRequired = function(userName, oUser) { var fCheckRules, nmRl, oRl, _ref; fCheckRules = function(oRule) { var action, fAddIfNewOrNotExisting, _i, _len, _ref, _results; fAddIfNewOrNotExisting = function(actionName) { var moduleName; moduleName = (actionName.split(' -> '))[0]; if (!isDeleteOp && (!oUser.actions[moduleName] || oRule.id === oNewRule.id)) { return db.actionInvokers.getModule(moduleName, function(err, obj) { var params, res; params = {}; res = dynmod.compileString(obj.data, userName, moduleName, params, obj.lang); return oUser.actions[moduleName] = res.module; }); } }; _ref = oRule.actions; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { action = _ref[_i]; _results.push(fAddIfNewOrNotExisting(action)); } return _results; }; _ref = oUser.rules; for (nmRl in _ref) { oRl = _ref[nmRl]; fCheckRules(oRl); } if (JSON.stringify(oUser.rules) === "{}") { return delete listUserRules[userName]; } }; _results = []; for (userName in listUserRules) { oUser = listUserRules[userName]; _results.push(fAddRequired(userName, oUser)); } return _results; }; pollQueue = function() { if (isRunning) { return db.popEvent(function(err, obj) { if (!err && obj) { processEvent(obj); } return setTimeout(pollQueue, 50); }); } }; /* Checks whether all conditions of the rule are met by the event. @private validConditions ( *evt, rule* ) @param {Object} evt @param {Object} rule */ validConditions = function(evt, rule) { var prop, _i, _len, _ref; _ref = rule.conditions; for (_i = 0, _len = _ref.length; _i < _len; _i++) { prop = _ref[_i]; if (jsonQuery(evt, prop).nodes().length === 0) { return false; } } return true; }; /* Handles retrieved events. @private processEvent ( *evt* ) @param {Object} evt */ processEvent = (function(_this) { return function(evt) { var action, arr, oRule, oUser, ruleName, userName, _results; _this.log.info('EN | processing event: ' + evt.event + '(' + evt.eventid + ')'); _results = []; for (userName in listUserRules) { oUser = listUserRules[userName]; _results.push((function() { var _ref, _results1; _ref = oUser.rules; _results1 = []; for (ruleName in _ref) { oRule = _ref[ruleName]; if (evt.event === oRule.event && validConditions(evt, oRule)) { this.log.info('EN | EVENT FIRED: ' + evt.event + '(' + evt.eventid + ') for rule ' + ruleName); _results1.push((function() { var _i, _len, _ref1, _results2; _ref1 = oRule.actions; _results2 = []; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { action = _ref1[_i]; arr = action.split(' -> '); _results2.push(listUserRules[userName]['actions'][arr[0]][arr[1]](evt)); } return _results2; })()); } else { _results1.push(void 0); } } return _results1; }).call(_this)); } return _results; }; })(this); exports.shutDown = function() { return isRunning = false; }; }).call(this);