<commit_before>'use strict';
/* This service handles everything related to configuration files
 *
 * It is a provider of resources and services.
 *
 * this.configuration needs to be set from the outside through
 * defineConfiguration(), typically by a route that enters the application.
 *
 *
 *
 * As of now a valid conf file contains four sections
 *   main
 *   navbar
 *   plugins
 *   resources
 *
 */
angular.module('arethusa.core').service('configurator', [
  '$injector',
  '$http',
  '$rootScope',
  'Resource',
  'Auth',
  '$timeout',
  '$location',
  '$q',
  function ($injector, $http, $rootScope, Resource, Auth,
            $timeout, $location, $q) {
    var self = this;
    var includeParam = 'fileUrl';

    function notifier() {
      return $injector.get('notifier');
    }

    // The second param is optional.
    this.defineConfiguration = function (confFile, location) {
      this.configuration = confFile;
      this.confFileLocation = location;

      // As this could be called from a resolve event through
      // $routeProvider, we $timeout to call, so that we are
      // guaranteed to see it in the ArethusaCtrl
      $timeout(function() {
        $rootScope.$broadcast('confLoaded');
      });
    };

    function parseConfUrl(url) {
      if (url.match('^http:\/\/')) {
        return url;
      } else {
        return 'http://services.perseids.org/arethusa-configs/' + url + '.json';
      }
    }

    this.loadAdditionalConf = function(confs) {
      var proms = arethusaUtil.inject([], confs, function(memo, plugin, url) {
        var promise;
        // Use the notifier for error handling!
        if (plugin == 'fullFile') {

          var success = function(res) {
            self.shallowMerge(self.configuration, res.data);
            notifier().info(url + ' configuration loaded!');
          };

          var error = function() {
            notifier().warning('Failed to retrieve ' + url);
          };
          promise = $http.get(parseConfUrl(url)).then(success, error);
        } else {
          promise = $http.get(url).then(function(res) {
            angular.extend(self.configurationFor(plugin), res.data);
          });
        }
        memo.push(promise);
      });
      return $q.all(proms);
    };

    // Returns an empty configuration files with all sections
    // as empty object properties.
    // Useful for the configuration editor.
    this.getConfTemplate = function () {
      return {
        main: {},
        navbar: {},
        plugins: {},
        resources: {}
      };
    };

    // Merges two configuration objects.
    // There is a clear contract that has to be fulfilled to make this work:
    //
    // The datatypes of individual properties need to be static.
    // E.g.
    //
    // {
    //   plugins: {
    //     morph: {
    //       retrievers: ['x']
    //     }
    //   }
    // }
    //
    // If plugins.morph.retrievers is an Array, it can only be an Array and nothing
    // else. The same goes for Objects, Strings, and Numbers.
    //
    // Objects call the function recursively.
    // Arrays are flat-pushed.
    // Strings and Numbers are overwritten.
    // a is extended with properties in b, that are not present in a.
    //
    // Currently unused after the events in
    //    http://github.com/latin-language-toolkit/arethusa/pull/365
    this.mergeConfigurations = function (a, b) {
      var that = this;
      angular.forEach(b, function (value, key) {
        var origVal = a[key];<commit_msg>Guarantee a valid conf template in configurator<commit_after>'use strict';
/* This service handles everything related to configuration files
 *
 * It is a provider of resources and services.
 *
 * this.configuration needs to be set from the outside through
 * defineConfiguration(), typically by a route that enters the application.
 *
 *
 *
 * As of now a valid conf file contains four sections
 *   main
 *   navbar
 *   plugins
 *   resources
 *
 */
angular.module('arethusa.core').service('configurator', [
  '$injector',
  '$http',
  '$rootScope',
  'Resource',
  'Auth',
  '$timeout',
  '$location',
  '$q',
  function ($injector, $http, $rootScope, Resource, Auth,
            $timeout, $location, $q) {
    var self = this;
    var includeParam = 'fileUrl';

    function notifier() {
      return $injector.get('notifier');
    }

    // The second param is optional.
    this.defineConfiguration = function (confFile, location) {
      this.configuration = angular.extend(new Template(), confFile);
      this.confFileLocation = location;

      // As this could be called from a resolve event through
      // $routeProvider, we $timeout to call, so that we are
      // guaranteed to see it in the ArethusaCtrl
      $timeout(function() {
        $rootScope.$broadcast('confLoaded');
      });
    };

    function parseConfUrl(url) {
      if (url.match('^http:\/\/')) {
        return url;
      } else {
        return 'http://services.perseids.org/arethusa-configs/' + url + '.json';
      }
    }

    this.loadAdditionalConf = function(confs) {
      var proms = arethusaUtil.inject([], confs, function(memo, plugin, url) {
        var promise;
        // Use the notifier for error handling!
        if (plugin == 'fullFile') {

          var success = function(res) {
            self.shallowMerge(self.configuration, res.data);
            notifier().info(url + ' configuration loaded!');
          };

          var error = function() {
            notifier().warning('Failed to retrieve ' + url);
          };
          promise = $http.get(parseConfUrl(url)).then(success, error);
        } else {
          promise = $http.get(url).then(function(res) {
            angular.extend(self.configurationFor(plugin), res.data);
          });
        }
        memo.push(promise);
      });
      return $q.all(proms);
    };

    function Template() {
      this.main = {};
      this.plugins = {};
      this.resources = {};
    }

    // Returns an empty configuration files with all sections
    // as empty object properties.
    // Useful for the configuration editor.
    this.getConfTemplate = function () {
      return new Template();
    };

    // Merges two configuration objects.
    // There is a clear contract that has to be fulfilled to make this work:
    //
    // The datatypes of individual properties need to be static.
    // E.g.
    //
    // {
    //   plugins: {
    //     morph: {
    //       retrievers: ['x']
    //     }
    //   }
    // }
    //
    // If plugins.morph.retrievers is an Array, it can only be an Array and nothing
    // else. The same goes for Objects, Strings, and Numbers.
    //
    // Objects call the function recursively.
    // Arrays are flat-pushed.
    // Strings and Numbers are overwritten.
    // a is extended with properties in b, that are not present in a.
    //
    // Currently unused after the events in
    //    http://github.com/latin-language-toolkit/arethusa/pull/365
    this.mergeConfigurations = function (a, b) {
      var that = this;
      angular.forEach(b, function (value, key) {
        var origVal = a[key];
{'fraction_non_alphanumeric': 0.12596437087950624, 'fraction_numerical': 0.0008416327675690841, 'mean_word_length': 2.134065934065934, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '6595690', 'n_tokens_mistral': 2041, 'n_tokens_neox': 2006, 'n_words': 612}