<commit_before>/*!
GPII XML Settings Handler

Copyright 2012 Raising the Floor - International

Licensed under the New BSD license. You may not use this file except in
compliance with this License.

You may obtain a copy of the License at
https://github.com/gpii/universal/LICENSE.txt
*/

/*global require */
(function () {
    var fluid = require("infusion"),
        fs = require("fs"),
        xm = require('xml-mapping'),
        gpii = fluid.registerNamespace("gpii");

    fluid.registerNamespace("gpii.settingsHandlers.XMLHandler");

    /* -------- Transformation functions -------------------- */

    /**
     * Transform the given array to a hash, using the expandSpec.options.key values from each
     * object in the array as new keys. So for expandSpec.options.key = "name" and 
     * source {b: [ { name: b1, v: v1 } { name: b2, v: v2 } ] } we get the transformed json
     * {b: { b1: { v: v1 }}, { b2: { v: v2 }}}
     */
    gpii.settingsHandlers.XMLHandler.arrayToHash = function (arr, expander, expandSpec) {
        if (!expandSpec.options || !expandSpec.options.key) {
            fluid.fail("arrayToHash requires a hash of options, one of which is named 'key', at path named \"options\" supplied ", expandSpec);
        }
        if (!fluid.isArrayable(arr)) {
            fluid.fail("arrayToHash didn't find array at inputPath, so failing", expandSpec);
        }
        var newHash = {};
        var pivot = expandSpec.options.key;
        //check that options.key is set
        fluid.each(arr, function (v, k) {
            //check that we have a pivot entry in the object and it's a valid type:            
            var newKey = v[pivot];
            var keyType = typeof(newKey);
            if (keyType !== "string" && keyType !== "boolean" && keyType !== "number") {
                fluid.fail("arrayToHash encountered unhashable array due to missing or invalid key", v);
            }
            //use the value of the key element as key and use the remaining content as value
            var content = fluid.copy(v);
            delete content[pivot];
            //fix sub Arrays if needed:
            if (expandSpec.options.innerValue) {
                var expanded = {};
                var inputPrefixOp = expander.inputPrefixOp;
                var outputPrefixOp = expander.outputPrefixOp;
                var innerValue = expandSpec.options.innerValue;
                
                //build inputPrefix:
                inputPrefixOp.push(expander.outputPrefix);
                inputPrefixOp.push(k.toString()); //push doesn't accept ints
                outputPrefixOp.push(newKey); //push doesn't accept ints
                for (var i=0; i<innerValue.length; ++i) {
                    fluid.merge("preserve", expanded, expander.expand(innerValue[i]));
                }
                outputPrefixOp.pop(newKey); //push doesn't accept ints
                inputPrefixOp.pop(k.toString);
                inputPrefixOp.pop(expander.outputPrefix);
                content = expanded;
            }
            newHash[newKey] = content;
        });
        return newHash;
    };


    gpii.settingsHandlers.XMLHandler.arrayToHash.invertRules = function (expandSpec, expander) {
        var togo = fluid.copy(expandSpec);
        togo.type = "gpii.settingsHandlers.XMLHandler.arrayToHash.inverse";
        togo.inputPath = fluid.model.composePaths(expander.outputPrefix, expandSpec.outputPath);
        togo.outputPath = fluid.model.composePaths(expander.inputPrefix, expandSpec.inputPath);
        //invert expanders from innerValue as well:
        if (togo.options && togo.options.innerValue) {
            var innerValue = togo.options.innerValue;
            for (var i=0; i<innerValue.length; ++i) {
                innerValue[i] = fluid.model.transform.invertConfiguration(innerValue[i]);
            }            
        }
        return togo;
    };

    fluid.defaults("gpii.settingsHandlers.XMLHandler.arrayToHash", {
        gradeNames: ["fluid.standardTransformFunction", "fluid.lens" ],
        invertConfiguration: "gpii.settingsHandlers.XMLHandler.arrayToHash.invertRules"
    });

    /**
     * Inverse of gpii.settingsHandlers.XMLHandler.arrayToHash
     */
    gpii.settingsHandlers.XMLHandler.arrayToHash.inverse = function (hash, expander, expandSpec) {
        if (!expandSpec.options || !expandSpec.options.key) {
            fluid.fail("hashToArray requires a hash of options, one of which is named 'key', at path named \"options\" supplied ", expandSpec);
        }
        var newArray = [];
        var pivot = expandSpec.options.key;
        //check that options.key is set
        fluid.each(hash, function (v, k) {
            //Due to the xm.toxml function being dependent on the order of key/value pairs in objects (sigh)
            //the pivot/key element needs to be first
            var content = {};
            content[pivot] = k;
            if (expandSpec.options.innerValue) {
                var expanded = {};
                var inputPrefixOp = expander.inputPrefixOp;
                var outputPrefixOp = expander.outputPrefixOp;
                var innerValue = expandSpec.options.innerValue;

                inputPrefixOp.push(expandSpec.inputPath);
                inputPrefixOp.push(k);
                outputPrefixOp.push(expandSpec.inputPath);
                outputPrefixOp.push(newArray.length.toString()); 
                for (var i=0; i<innerValue.length; ++i) {
                    fluid.merge("preserve", expanded, expander.expand(innerValue[i]));
                }
                outputPrefixOp.pop(expandSpec.inputPath);
                outputPrefixOp.pop(newArray.length.toString());
                inputPrefixOp.pop(k);
                inputPrefixOp.pop(expandSpec.inputPath);
                v = expanded;
            }
            fluid.merge("replace", content, v);
            newArray.push(content);
        });
        return newArray;
    };
<commit_msg>GPII-32: Fixed all comments from antranig+colin review, except for using fluid.set when creating paths and renaming the hashToArray function<commit_after>/*!
GPII XML Settings Handler

Copyright 2012 Raising the Floor - International

Licensed under the New BSD license. You may not use this file except in
compliance with this License.

You may obtain a copy of the License at
https://github.com/gpii/universal/LICENSE.txt
*/

/*global require */
(function () {
    var fluid = require("infusion"),
        fs = require("fs"),
        xm = require('xml-mapping'),
        gpii = fluid.registerNamespace("gpii");

    fluid.registerNamespace("gpii.settingsHandlers.XMLHandler");

    /* -------- Transformation functions -------------------- */

    /**
     * Transform the given array to a hash, using the expandSpec.options.key values from each
     * object in the array as new keys. So for expandSpec.options.key = "name" and 
     * source {b: [ { name: b1, v: v1 } { name: b2, v: v2 } ] } we get the transformed json
     * {b: { b1: { v: v1 }}, { b2: { v: v2 }}}
     */
    gpii.settingsHandlers.XMLHandler.arrayToHash = function (arr, expander, expandSpec) {
        if (fluid.get(expandSpec, "options.key") === undefined) {
            fluid.fail("arrayToHash requires a hash of options, one of which is named 'key', at path named \"options\" supplied ", expandSpec);
        }
        if (!fluid.isArrayable(arr)) {
            fluid.fail("arrayToHash didn't find array at inputPath, so failing", expandSpec);
        }
        var newHash = {};
        var pivot = expandSpec.options.key;
        var inputPrefixOp = expander.inputPrefixOp;
        var outputPrefixOp = expander.outputPrefixOp;
        var innerValue = expandSpec.options.innerValue;

        //check that options.key is set
        fluid.each(arr, function (v, k) {
            //check that we have a pivot entry in the object and it's a valid type:            
            var newKey = v[pivot];
            var keyType = typeof(newKey);
            if (keyType !== "string" && keyType !== "boolean" && keyType !== "number") {
                fluid.fail("arrayToHash encountered unhashable array due to missing or invalid key", v);
            }
            //use the value of the key element as key and use the remaining content as value
            var content = fluid.copy(v);
            delete content[pivot];
            //fix sub Arrays if needed:
            if (innerValue) {
                var expanded = {};
                
                //build inputPrefix:
                inputPrefixOp.push(expander.outputPrefix);
                inputPrefixOp.push(k.toString()); //push doesn't accept ints
                outputPrefixOp.push(newKey); //push doesn't accept ints
                for (var i=0; i<innerValue.length; ++i) {
                    fluid.merge("preserve", expanded, expander.expand(innerValue[i]));
                }
                outputPrefixOp.pop();
                inputPrefixOp.pop();
                inputPrefixOp.pop();
                content = expanded;
            }
            newHash[newKey] = content;
        });
        return newHash;
    };


    gpii.settingsHandlers.XMLHandler.arrayToHash.invertRules = function (expandSpec, expander) {
        var togo = fluid.copy(expandSpec);
        togo.type = "gpii.settingsHandlers.XMLHandler.arrayToHash.inverse";
        togo.inputPath = fluid.model.composePaths(expander.outputPrefix, expandSpec.outputPath);
        togo.outputPath = fluid.model.composePaths(expander.inputPrefix, expandSpec.inputPath);
        //invert expanders from innerValue as well:
        if (togo.options && togo.options.innerValue) {
            var innerValue = togo.options.innerValue;
            for (var i=0; i<innerValue.length; ++i) {
                innerValue[i] = fluid.model.transform.invertConfiguration(innerValue[i]);
            }            
        }
        return togo;
    };

    fluid.defaults("gpii.settingsHandlers.XMLHandler.arrayToHash", {
        gradeNames: ["fluid.standardTransformFunction", "fluid.lens" ],
        invertConfiguration: "gpii.settingsHandlers.XMLHandler.arrayToHash.invertRules"
    });

    /**
     * Inverse of gpii.settingsHandlers.XMLHandler.arrayToHash
     */
    gpii.settingsHandlers.XMLHandler.arrayToHash.inverse = function (hash, expander, expandSpec) {
        if (!expandSpec.options || !expandSpec.options.key) {
            fluid.fail("hashToArray requires a hash of options, one of which is named 'key', at path named \"options\" supplied ", expandSpec);
        }
        var newArray = [];
        var pivot = expandSpec.options.key;
        //check that options.key is set
        fluid.each(hash, function (v, k) {
            //Due to the xm.toxml function being dependent on the order of key/value pairs in objects (sigh)
            //the pivot/key element needs to be first
            var content = {};
            content[pivot] = k;
            if (expandSpec.options.innerValue) {
                var expanded = {};
                var inputPrefixOp = expander.inputPrefixOp;
                var outputPrefixOp = expander.outputPrefixOp;
                var innerValue = expandSpec.options.innerValue;

                inputPrefixOp.push(expandSpec.inputPath);
                inputPrefixOp.push(k);
                outputPrefixOp.push(expandSpec.inputPath);
                outputPrefixOp.push(newArray.length.toString()); 
                for (var i=0; i<innerValue.length; ++i) {
                    fluid.merge("preserve", expanded, expander.expand(innerValue[i]));
                }
                outputPrefixOp.pop();
                outputPrefixOp.pop();
                inputPrefixOp.pop();
                inputPrefixOp.pop();
                v = expanded;
            }
            fluid.merge("replace", content, v);
            newArray.push(content);
        });
        return newArray;
    };

{'fraction_non_alphanumeric': 0.11145588728614558, 'fraction_numerical': 0.0026836632002683663, 'mean_word_length': 2.042091836734694, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, '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': '6201700', 'n_tokens_mistral': 3307, 'n_tokens_neox': 3162, 'n_words': 841}