All files / universal/gpii/node_modules/transformer/src/js Transformer.js

100% Statements 53/53
91.67% Branches 22/24
100% Functions 10/10
100% Lines 53/53

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157                                      5x 5x 5x   5x   5x                         5x 275x     275x 275x 653x 6x 6x         275x   275x 258x 258x 258x     275x 275x 275x 275x                                         5x 168x 260x 260x 2x   2x   258x 258x 275x   258x 258x       168x 260x 2x     168x       5x       5x 7x                   5x         5x 14x 14x 14x 14x   14x 6x   8x       5x 42x 42x             5x 38x        
/*!
GPII Settings Transformer
 
Copyright 2012 OCAD University
Copyright 2012 Antranig Basman
Copyright 2013-2014 Raising the Floor
 
Licensed under the New BSD license. You may not use this file except in
compliance with this License.
 
The research leading to these results has received funding from the European Union's
Seventh Framework Programme (FP7/2007-2013) under grant agreement no. 289016.
 
You may obtain a copy of the License at
https://github.com/GPII/universal/blob/master/LICENSE.txt
*/
 
"use strict";
 
var fluid = fluid || require("infusion"),
    $ = fluid.registerNamespace("jQuery"),
    gpii = fluid.registerNamespace("gpii");
 
fluid.registerNamespace("gpii.transformer");
 
(function () {
    /**
     * Helper function for `gpii.transformer.configurationToSettings`. Used to modify the settings handler
     * blocks to be in the format required (i.e. including the application specific settings to be
     * set) by the actual settings handlers. This modifies the block in place - it has already been copied by the
     * the caller
     *
     * @param settingsHandler {Object} - The settingsHandler information from the solutions registry to be transformed - MODIFIED IN PLACE
     * @param oneUserSolution {Object} - the user preferences related to this solution and settings handler
     * @param solutionId {Object} - the ID of the solution for which the settingshandler is related
     *
     * @return {Object} - the modified settingshandler object - ready to be passed to the lifecycle manager
     */
    gpii.transformer.transformOneSettingsHandler = function (settingsHandler, oneUserSolution, solutionId) {
        var settings = fluid.copy(oneUserSolution.settings["http://registry.gpii.net/applications/" + solutionId]);
 
        // extract any common terms that were defined in the application block and delete them from the settings block
        var scopedCommon = {};
        fluid.each(settings, function (val, key) {
            if (key.startsWith("http://registry.gpii.net/common/")) {
                scopedCommon[key] = fluid.copy(val); // add to list of scoped common terms
                delete settings[key]; // remove from the settings
            }
        });
 
        // filter to only keep relevant application specific settings
        settings = gpii.settingsHandlers.filterSupportedSettings(settings, settingsHandler.supportedSettings);
 
        if (settingsHandler.capabilitiesTransformations) {
            var inferred = fluid.model.transformWithRules(oneUserSolution.settings, settingsHandler.capabilitiesTransformations);
            var inferredScoped = (scopedCommon === undefined || $.isEmptyObject(scopedCommon)) ? {} : fluid.model.transformWithRules(scopedCommon, settingsHandler.capabilitiesTransformations);
            settings = fluid.extend(true, {}, inferred, inferredScoped, settings);
        }
 
        settingsHandler.settings = settings || {};
        delete settingsHandler.capabilitiesTransformations;
        delete settingsHandler.capabilities;
        return settingsHandler;
    };
 
    /**
     * Converts a system configuration (output from the context manager from matchmaker output) to a format readable by the
     * lifecycle manager. This includes translation of common terms to application specific settings.
     * The following rules apply when doing this translation:
     * - the translation is based on the transformations in the solutionsRegistry entry
     * - if a common term transforms into a setting which is already specific as application specific
     *      in the configuration argument, the application specific takes priority. In other words:
     *      if the configuration contains both an application specific and (transformable) common
     *       term for some application setting, the application specific one will stay and the
     *      transformed will be discarded.
     *
     * @param configuration {Object} - An element of the matchmaker output payload for a particular context
     *      (by the context manager)
     * @param solutionsRegistry {Object} - a section of the solutions registry database, filtered for configured solutions (currently only done by OS and device context)
     *
     * @return An object isomorphic to the "configuration" with settings blocks transformed and evaluated - this is ready to be
     * dispatched to settings handlers
     */
    gpii.transformer.configurationToSettings = function (configuration, solutionsRegistryEntries) {
        var togo = fluid.transform(configuration.applications, function (oneUserSolution, solutionId) {
            var oneSolution = fluid.copy(solutionsRegistryEntries[solutionId]);
            if (oneSolution === undefined) {
                fluid.log("The configuration to be applied contains an entry for " + solutionId +
                    " which was not found in the solutionsRegistry. Aborting configuration");
                return undefined;
            }
            delete oneSolution.contexts; // solutions registry entries should include this as "old device reporter context info"
            oneSolution.settingsHandlers = fluid.transform(oneSolution.settingsHandlers, function (settingsHandler) {
                return gpii.transformer.transformOneSettingsHandler(settingsHandler, oneUserSolution, solutionId);
            });
            oneSolution.active = oneUserSolution.active; // copy over active directive for later use
            return oneSolution;
        });
 
        // ensure no empty entries exist in the settings payload
        for (var i in togo) {
            if (togo[i] === undefined) {
                delete togo[i];
            }
        }
        return togo;
    };
 
    // TODO: This transform has no tests
    fluid.defaults("gpii.transformer.booleanToNumber", {
        gradeNames: "fluid.standardTransformFunction"
    });
 
    gpii.transformer.booleanToNumber = function (value) {
        return value ? 1 : 0;
    };
 
    /**
     * timeInRange is implemented specifically for checking whether an input time falls in between
     * two given times. The valid and required inputs, besides the standard input/inputPath are `to`
     * and `from`. All inputs should be strings of the type "hh:mm" (eg. "17:30"). The range wraps
     * midnight, so given a `from` of "20:00" and a `to` of `"08:00"` all the following inputs would
     * result in true: "20:00", 23:00", "02:45".
     */
    fluid.defaults("gpii.transformer.timeInRange", {
        gradeNames: "fluid.standardTransformFunction"
    });
 
 
    gpii.transformer.timeInRange = function (value, transformSpec) {
        var timeInRange = gpii.transformer.timeInRange;
        var currentTime = timeInRange.timeParser(value);
        var fromTime = timeInRange.timeParser(transformSpec.from);
        var toTime = timeInRange.timeParser(transformSpec.to);
 
        if (timeInRange.isEarlier(toTime, fromTime)) { // if time wraps
            return (timeInRange.isEarlier(fromTime, currentTime) || timeInRange.isEarlier(currentTime, toTime));
        } else {
            return (timeInRange.isEarlier(fromTime, currentTime) && timeInRange.isEarlier(currentTime, toTime));
        }
    };
 
    gpii.transformer.timeInRange.timeParser = function (time) {
        time = time.split(":");
        return {
            hours: parseInt(time[0], 10),
            minutes: parseInt(time[1], 10)
        };
    };
 
    // checks whether 'first' is earlier than 'second' - returns true if so
    gpii.transformer.timeInRange.isEarlier = function (first, second) {
        return (60 * (first.hours - second.hours) + first.minutes - second.minutes) < 0;
    };
 
})();