<commit_before>"use strict";

var fs = require("fs");
var path = require("path");
var w = require("winston");
w.level = process.env.LOG_LEVEL;

var Entity = require("./Entity.js");

/**
 * Constructs a new action.
 * @class
 * @param {Object} action JSON describing an action
 */
function Action(action) {
    if(this.constructor === Object &&
       action && action.action && actionConstructors[action.action]) {
        throw new Error("Action: Use Action.createAction to generate Action of type '"+action.action+"'");
    } else {
        if(action === undefined) {
            this.action = "";
            this.args = [];
        } else {
            if(action.action === undefined) {
                var m = "Action does not specify which action to exectue.";
                w.error(m);
                throw new Error(m);
            }

            this.action = action.action;

            if(action.args !== undefined) {
                var l = action.args.length;
                this.args = [];

                for(var i = 0; i < l; i++) {
                    if(action.args[i] && action.args[i].type) {
                        this.args[i] = new Entity(action.args[i]);
                    } else
                        this.args[i] = action.args[i];
                }
            }
        }
    }
}

/**
 * Stores constructors of all actions registered with this module
 * using the static method [register]{@link Action#register}
 * (mostly called from within an action implementation)
 * @static
 * @access private
 */
var actionConstructors = {};

function readActions(dir) {
    var actionFiles = [];
    var actions = [];
    var loads = [];

    try {
        actionFiles = fs.readdirSync(dir);
    } catch(err) {
        return Promise.reject(err);
    }

    actionFiles.forEach(function(actionFile) {
        var filePath = path.join(dir, actionFile);
        var stats = fs.statSync(filePath);
        if (stats.isFile()) {
            if (/\.js$/.test(filePath)) {
                loads.push(new Promise( function(resolve, reject) {
                    try {
                        var newAction = require(filePath);
                        newAction(Action);
                        w.log('info', "Success: Action in '"+filePath+"' is now registered.");
                        resolve();
                    } catch(err) {
                        w.log('error', "Unable to load action in '"+filePath+"'!");
                        reject(err);
                    }
                }));
            }
        }
    });

    return Promise.all(loads);
}

/**
 * Initializes the action system, reading all actions from the directory specified in
 * settings.
 * @arg {Object} settings Checks whether <code>settings.actions</code> is an absolute path. If it is
 * the actions are loaded from this path. If not, actions are loaded from this path relative to the path
 * the application was started from
 * @return {Promise} The returned promise resolves if all actions were loaded successfully, rejects otherwise.
 * @static
 */
Action.init = function(settings) {
    var baseDir = process.cwd();

    if(!settings) {
        var m = "Unable to initialize Actions. Missing settings information!";
        w.error(m);
        return Promise.reject(new Error(m));
    }

    if(!settings.actions) {
        w.error("Unable to initialize Actions. Invalid 'settings.actions' property!");
        return Promise.reject(new Error("Unable to initialize Actions. Invalid 'settings.actions' property!"));
    }
<commit_msg>Enable multiple initializations<commit_after>"use strict";

var fs = require("fs");
var path = require("path");
var w = require("winston");
w.level = process.env.LOG_LEVEL;

var Entity = require("./Entity.js");

function valid(o) {
    return ((o !== undefined) && (o !== null));
}

/**
 * Constructs a new action.
 * @class
 * @param {Object} action JSON describing an action
 */
function Action(action) {
    if(this.constructor === Object &&
       action && action.action && actionConstructors[action.action]) {
        throw new Error("Action: Use Action.createAction to generate Action of type '"+action.action+"'");
    } else {
        if(action === undefined) {
            this.action = "";
            this.args = [];
        } else {
            if(action.action === undefined) {
                var m = "Action does not specify which action to exectue.";
                w.error(m);
                throw new Error(m);
            }

            this.action = action.action;

            if(action.args !== undefined) {
                var l = action.args.length;
                this.args = [];

                for(var i = 0; i < l; i++) {
                    if(action.args[i] && action.args[i].type) {
                        this.args[i] = new Entity(action.args[i]);
                    } else
                        this.args[i] = action.args[i];
                }
            }
        }
    }
}

/**
 * Stores constructors of all actions registered with this module
 * using the static method [register]{@link Action#register}
 * (mostly called from within an action implementation)
 * @static
 * @access private
 */
var actionConstructors = {};

function readActions(dir) {
    var actionFiles = [];
    var actions = [];
    var loads = [];

    try {
        actionFiles = fs.readdirSync(dir);
    } catch(err) {
        return Promise.reject(err);
    }

    actionFiles.forEach(function(actionFile) {
        var filePath = path.join(dir, actionFile);
        var stats = fs.statSync(filePath);
        if (stats.isFile()) {
            if (/\.js$/.test(filePath)) {
                loads.push(new Promise( function(resolve, reject) {
                    try {
                        var newAction = require(filePath);
                        newAction(Action);
                        w.info("Success: Action in '"+filePath+"' is now registered.");
                        resolve();
                    } catch(err) {
                        w.error("Unable to load action in '"+filePath+"'!");
                        reject(err);
                    }
                }));
            }
        }
    });

    return Promise.all(loads);
}

/**
 * Initializes the action system, reading all actions from the directory specified in
 * settings.
 * @arg {Object} settings Checks whether <code>settings.actions</code> is an absolute path. If it is
 * the actions are loaded from this path. If not, actions are loaded from this path relative to the path
 * the application was started from
 * @return {Promise} The returned promise resolves if all actions were loaded successfully, rejects otherwise.
 * @static
 */
Action.init = function(settings) {
    if(valid(actionConstructors) && Object.keys(actionConstructors).length > 0) {
        w.warn("Action system has already been initialized. Skip this initialization.");
        return Promise.resolve();
    }
    
    var baseDir = process.cwd();

    if(!settings) {
        var m = "Unable to initialize Actions. Missing settings information!";
        w.error(m);
        return Promise.reject(new Error(m));
    }

    if(!settings.actions) {
        w.error("Unable to initialize Actions. Invalid 'settings.actions' property!");
        return Promise.reject(new Error("Unable to initialize Actions. Invalid 'settings.actions' property!"));
    }

{'fraction_non_alphanumeric': 0.12528813559322033, 'fraction_numerical': 0.00040677966101694915, 'mean_word_length': 1.9445109780439123, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2414756', 'n_tokens_mistral': 1964, 'n_tokens_neox': 1890, 'n_words': 567}