    /**
     * @class sol
     * @singleton
     * @author Nils Mosbach, ELO Digital Office GmbH
     *
     * Solutions are modularized using a js class framework that adapts concepts
     * from object orientated languages.
     *
     * # Modularization of solutions
     *
     * Every function is implemented as a Class which allows passing configuration params to
     * the class on instantiation. Class definitions have been simplified
     * thanks to a function called sol.define. With the help of sol.create new class
     * instances can be created.
     *
     * For more information on modularization of classes refer to sol.ClassManager.
     *
     * # Namespaces
     *
     * Modules are organized in namespaces. The creation of namespaces is explained in the class sol.NamespaceManager.
     * Please mind that the namespaces "elo" and "sol" are reserved by the ELO Digital Office GmbH.
     *
     * # Storing modules in ELO
     *
     * JS files of the modules should be stored in ELO. It is recommended that namespaces are
     * represented as structure elements from a logical view.
     *
     * e.g. the ix registered function "RF_MyFunction" which is part of the namespace "sol.invoice.ix" should be placed in...
     *
     *     [ELO Archive]
     *       - Administration
     *          - Business Solutions
     *             - Common
     *                [File] sol.common.Helpers.js
     *             - Invoice
     *                - IX Scripting Base
     *                   [File] sol.invoice.ix.RF_MyFunction
     *
     *          - IX Scripting Base
     *             [Reference] sol.invoice.ix.RF_MyFunction
     *             [Reference] sol.common.Helpers.js
     *
     * If further files need to be imported within RF_MyFunction they should stay in the same hierarchy.
     * Scripts that should be used across IX, AS and WF must have an .js extension in their short description.
     *
     * @eloall
     */

    var _init,
        disableGlobalScope = true;

    _init = function (ctx) {
      var key,
          disableGlobalScope = (typeof globalScope === "undefined") || // eslint-disable-line no-shadow
          (typeof globalScope !== "undefined" ? globalScope.disableGlobalScope : false) ||
          (typeof ctx.disableGlobalScope !== "undefined" ? ctx.disableGlobalScope : false) ||
          (typeof workspace !== "undefined" ? true : false) ||
          false;

      // Initialize solution namespace since NamespaceManager component isn't available yet.
      // Apply exisiting namespaces and instances to the current context.
      if (disableGlobalScope) {
        ctx.sol = ctx.sol || {};
      } else {
        if (!globalScope.$instances) {
          globalScope.$instances = {
            sol: {}
          };
        }
        if (!globalScope.$classes) {
          globalScope.$classes = {};
        }
        if (!globalScope.$dependencies) {
          globalScope.$dependencies = [];
          globalScope.$watchers = {};
        }
        for (key in globalScope.$instances) {
          if (globalScope.$instances.hasOwnProperty(key) && key) {
            ctx[key] = globalScope.$instances[key];
          }
        }
      }

      /**
       * @class sol.ClassManager
       * @singleton
       * @author Nils Mosbach, ELO Digital Office GmbH
       *
       * Manager instance that handles the definition and creation of classes.
       *
       * Class definitions are handled internally by the ClassManager.
       * Therefore the creation of classes should always be done by calling sol.create.
       *
       *
       * # Defining classes - basic syntax
       *
       * Every class is represented by a class name that should include a namespace and the class definition.
       * The class definition is a js object that represents the contents of that class. Functions and properties
       * that are part of the classDefinition will be part of the class prototype.
       *
       *     sol.define(className, classDefinition);
       *
       * Every class has its own constructor which is specified by a function called initialize.
       *
       *     sol.define("sol.test.Fighter", {
       *       name: '',
       *       power: 0,
       *
       *       initialize: function (config) {
       *         var me = this;
       *
       *         me.name = config.name;
       *         me.power = config.power;
       *       },
       *
       *       highFive: function () {
       *         log.info("high five");
       *         return "^5";
       *       }
       *     });
       *
       * # Inheritance
       *
       * Classes can inherit properties and functions from a super class.
       *
       *     sol.define(className, {
       *       extend: superClassName
       *     });
       *
       * Following example will inherit name and power-properties as well as the highFive-function of the fighter.
       *
       *     sol.define("sol.test.Saiyajin", {
       *       extend: "sol.test.Fighter",
       *
       *       level: 1,
       *
       *       initialize: function (config) {
       *         var me = this;
       *         me.$super("sol.test.Fighter", "initialize", [config]);
       *         me.level = 1;
       *       },
       *
       *       transform: function() {
       *         var me = this;
       *         if(me.level < 3) {
       *           me.level++;
       *           me.power *= 50;
       *         }
       *       }
       *     });
       *
       * Superclass functions can be overridden. With the help of the $super-function, functions of the superclass can be called.
       *
       * <b>Please note that calling superclass functions might lead to an infinitive loop if misused. Please validate that none class other than the classes superclass is passed as the superclass parent.</b>
       *
       *     me.$super(superClassName, functionName, attributesArray);
       *
       * A basic example of the initialize-function will look as followed.
       *
       *     me.$super("sol.Base", "initialize", [config]);
       *     me.$super("sol.Base", "initialize", arguments);
       *
       * A word on performance: The superclass name must be passed since the js rhino engine does not allow accessing the caller of the callee due to performance reasons.
       *
       * # Mixins
       *
       * Mixins allow inheriting properties and functions from multiple classes. This concept is also called multiple class inheritance.
       * This can be useful if operation might get used by several classes that implement different use cases. Therefore an Array of classes
       * should be passed to the class definition.
       *
       *     sol.define(className, {
       *       mixins: [mixinClassName]
       *     });
       *
       * If mixins are overritten by the implementing class, there is no way of calling the original mixin function. $super only applies to
       * functions that have been inherited from the superclass.
       *
       * Mixins must be defined by `mixin: true` which also prevents mixin classes from general sol.Base inheritance.
       *
       * Lets define a mixin 'weep' for the fighters.
       *
       *     sol.define("sol.test.mixins.Weep", {
       *       mixin: true,
       *
       *       weep: function () {
       *         log.debug("All fighters do it sometimes");
       *       }
       *     });
       *
       *     sol.define("sol.test.Fighter", {
       *       mixins: ['sol.test.mixins.Weep'],
       *       name: '',
       *       power: 0,
       *
       *       initialize: function (config) {
       *         var me = this;
       *
       *         me.name = config.name;
       *         me.power = config.power;
       *       },
       *
       *       highFive: function () {
       *         log.info("high five");
       *         return "^5";
       *       }
       *     });
       *
       * Mixins also support initialization operations. Please note that this should not be external system calls.
       * Initialization of mixins is executed after all classes and superclasses have been initialized.
       *
       *     sol.define("sol.test.mixins.Weep", {
       *       mixin: true,
       *
       *       initialize: function(config) {
       *         var me = this;
       *         me.wheepName = config.name;
       *       }
       *
       *       weep: function () {
       *         log.debug("All fighters do it sometimes, even "+ me.wheepName);
       *       }
       *     });
       *
       * # Defining singleton classes
       *
       * Singletons can be created by passing a singleton parameter to the class definition.
       *
       *     sol.define(className, {
       *       singleton: true
       *     });
       *
       * In this case a class is created in the given namespace after the class was defined.
       * Lets define an arena for the fighters.
       *
       *     sol.define("sol.test.Arena", {
       *       singleton: true,
       *
       *       ambience: "dark",
       *
       *       changeAmbience: function(ambience) {
       *         var me = this;
       *         me.ambience = ambience;
       *       },
       *
       *       fight: function (fighter1, fighter2) {
       *         return (fighter1.power > fighter2.power) ? fighter1.name : fighter2.name);
       *       }
       *     });
       *
       *     sol.test.Arena.changeAmbience("dark and scary");
       *
       * # Creating class instances
       *
       * Instances of defined classes can be created by sol.create(). An options object can be used
       * in order to pass config properties to the initialize function.
       *
       *     sol.create(className, options);
       *
       * Lets create a new Saiyajin fighter.
       * The name and power configurations are handled by the initialize function of the fighter.
       *
       *     var goku = sol.create("sol.test.Saiyajin", {
       *       name: "Son-Goku",
       *       power: 3000000
       *     });
       *
       * # Example using classes
       *
       * Following example shows a basic usage of the classes defined by previous examples.
       *
       *     var goku, freezer, winner;
       *
       *     goku = sol.create("sol.test.Saiyajin", {
       *       name: "Son-Goku",
       *       power: 3000000
       *     });
       *
       *     freezer = sol.create("sol.test.Fighter", {
       *       name: "Freezer",
       *       power: 120000000
       *     });
       *
       *     var winner = sol.test.Arena.fight(goku, freezer);
       *     log.info("[MATCH] winner 1st=" + winner);
       *
       *     goku.transform();
       *
       *     winner = sol.test.Arena.fight(goku, freezer);
       *     log.info("[MATCH] winner 2nd=" + winner);
       *     freezer.weep();
       *
       * # Class properties and prototyping
       *
       * sol#define allows defining static values on class prototypes. This should be avoided and only be used if the core concept of js prototypes is clear.
       *
       * <b>Using class properties for global definitions/ constants</b>
       *
       * Basically prototyping allows defining static property values that can be used by all instances. That might be useful for constants or global definitions.
       *
       *     sol.define("sol.test.Fighter", {
       *       allowedAmountOfFights: 10,
       *       modes: {
       *         slow: function() {},
       *         fast: function() {}
       *       }
       *     });
       *
       * <b>Misuse and class properties</b>
       *
       * If working with properties defined by the class prototype they are static values.
       *
       *     sol.define("sol.test.Fighter", {
       *       fightsTotal: 0,
       *       fights: [],
       *       fight: function() { this.fightsTotal++; }
       *     });
       *
       *     var fighter1 = sol.create("sol.test.Fighter", {});
       *     fighter1.fight();                // fightsTotal = 1
       *     fighter1.fights.push('first');   // fights = ['first']
       *     fighter1.fight();                // fightsTotal = 2
       *     fighter1.fights.push('second');   // fights = ['first', 'second']
       *     var fighter2 = sol.create("sol.test.Fighter", {});
       *     fighter2.fight();                // fightsTotal = 3
       *     fighter1.fights.push('third');   // fights = ['first', 'second', 'third']
       *
       * However if properties are applied on the instance itself they are primarily used. For example:
       *
       *     var fighter1 = sol.create("sol.test.Fighter", {});
       *     fighter1.fight();                // fightsTotal = 1
       *     fighter1.fight();                // fightsTotal = 2
       *     var fighter2 = sol.create("sol.test.Fighter", {});
       *     // set a new property instance on the fighter2 instance
       *     fighter2.fightsTotal = 0;
       *     fighter2.fight();                // fightsTotal = 1
       *     fighter1.fight();                // fightsTotal = 3
       *
       * In order to solve this problem, never work (extend, modify or calculate) with values instances applied on class prototype level.
       * If working with values they *must* be defined in the initialize function!
       *
       *     sol.define("sol.test.Fighter", {
       *       requiredConfig: ['name'],
       *       allowedAmountOfFights: 10,
       *
       *       initialize: function(config) {
       *         var me = this;
       *         me.fights = [];
       *       }
       *
       *       fight: function() {
       *         var me = this;
       *         if (me.fights.length < me.allowedAmountOfFights) {
       *           me.fights.push(new Date());
       *         }
       *       }
       *     });
       *
       * When using config properties passed to sol#create they will get added to the instance by sol.Base#initialize.
       *
       *     sol.create("sol.test.Fighter", {
       *       name: 'Son Goku"
       *     });
       *
       * @version 1.1
       * @eloall
       */
      sol.ClassManager = sol.ClassManager || {

        /**
         * @private
         * @property
         */
        version: 1,

        /**
         * @private
         * @property
         * @member sol.ClassManager
         * defined classes by {@link sol.ClassManager#define sol.ClassManager.define() or sol.define()}
         */
        definedClasses: disableGlobalScope ? {} : globalScope.$classes,

        /**
         * @private
         * @property
         * @member sol.ClassManager
         * keeps a list of dependencies that are used by watchers.
         */
        dependencies: disableGlobalScope ? [] : globalScope.$dependencies,
        watchers: disableGlobalScope ? {} : globalScope.$watchers,

        /**
         * @private
         * Returns the registered prototype of a class thanks to its name.
         * If no class was registered undefined is returned.
         * @param {String} className name of the class including its namespace
         * @returns {*} class prototype
         */
        getClass: function (className) {
          if (!className) {
            return undefined;
          }
          if (sol.ClassManager.definedClasses.hasOwnProperty(className)) {
            return sol.ClassManager.definedClasses[className];
          }
          return undefined;
        },

        /**
         * @private
         * Creates and registers a new class prototype.
         * @param {String} className name of the class including its namespace
         * @param {Object} classDefinition definition if the new class as a js object.
         * @returns {Function} new class prototype
         */
        definePrototype: function (className, classDefinition) {
          var parentClass, $class, msg;

          if (sol.ClassManager.getClass(className)) {
            msg = "[sol.define] Class with name '" + className + "' has already been defined. Overwriting existing definition.";
            (ctx.log && ctx.log.info) ? log.info(msg) : console.info(msg);
          }

          $class = function () {
            this.$super = function () {
              var superClassName, method, args, argsType, msgx;
              if (arguments.length === 2) {
                msgx = "[sol.define] " + className + ": calling superclass function '" + method + "' without super class name is deprecated.";
                (ctx.log && ctx.log.info) ? log.warn(msgx) : console.warn(msgx);

                superClassName = this.$parent.$className;
                method = arguments[0];
                args = arguments[1];
              } else if (arguments.length === 3) {
                superClassName = arguments[0];
                method = arguments[1];
                args = arguments[2];
              } else {
                throw "[sol.define] " + className + ": calling superclass function failed. $super arguments list is invalid.";
              }

              argsType = Object.prototype.toString.call(args);
              if (!(argsType === "[object Array]" || argsType === "[object Arguments]")) {
                throw "[sol.define] " + className + ": calling superclass function failed. invalid syntax. arguments must be an array. e.g. $super('superclass', 'fct', ['argument'});";
              }

              if (superClassName === this.$className) {
                throw "[sol.define] " + className + ": cannot call super class function if instance class name was passed as superclass. This would result in an invinite loop.";
              }

              return sol.ClassManager.$super(superClassName, this, method, args);
            };
            this.$className = className;
            this.initialize.apply(this, arguments);
            if (this.$initializeMixins
                && this.$initializeMixins.length > 0) {
              for (var i = 0; i < this.$initializeMixins.length; i += 1) {
                this.$initializeMixins[i].apply(this, arguments);
              }
            }
          };

          // Resolve parent class name if string is given
          parentClass = classDefinition.extend;
          if (typeof parentClass === "string") {
            parentClass = sol.ClassManager.getClass(parentClass);
            if (!parentClass) {
              throw "[sol.define] " + className + ": Cannot not inherit from class '" + classDefinition.extend + "'. Class not found. Please check if all dependencies are included.";
            }
          }
          if (typeof parentClass !== "undefined") {
            sol.ClassManager.extend($class.prototype, parentClass.prototype);
            $class.prototype.$parent = parentClass.prototype;
          }

          sol.ClassManager.mixin($class, classDefinition, className);
          sol.ClassManager.extend($class.prototype, classDefinition);
          $class.prototype.constructor = $class;
          $class.prototype.$className = className;

          if (!$class.prototype.initialize) {
            $class.prototype.initialize = function () {};
          }

          sol.ClassManager.definedClasses[className] = $class;

          return $class;
        },
        /**
         * @private
         * Applies mixins given by a class definition to the classes prototype definition.
         * @param {Object} $class class that mixins should be applied to.
         * @param {Object} classDefinition configuration of the class that contains list of possible mixins.
         * @param {String} className name of the class (used by error handling)
         */
        mixin: function ($class, classDefinition, className) {
          var i, mixin;

          if (typeof classDefinition.mixins !== "undefined"
              && classDefinition.mixins.length > 0) {
            for (i = 0; i < classDefinition.mixins.length; i++) {
              mixin = classDefinition.mixins[i];
              if (typeof mixin === "string") {
                mixin = sol.ClassManager.getClass(mixin) || mixin;
              }
              sol.ClassManager.extendMixin($class.prototype, mixin.prototype, className, classDefinition.mixins[i]);
            }
          }
        },

        /**
         * @private
         * Extends a class based on properties and functions given its superclass.
         * @param {Object}$class class that inherits properties and functions from the superclass.
         * @param {Object} mixinClass super class
         * @param {String} className name of the current class (used by error handling)
         * @param {String} mixinName name of the current mixin class (used by error handling)
         * @returns {object} new class with inherited properties and functions.
         */
        extendMixin: function ($class, mixinClass, className, mixinName) {
          var property;

          if (!mixinClass.mixin) {
            throw "[sol.define] " + className + ": Cannot mixin class '" + mixinName + "'. Mixins must be defined by `mixin: true` in order to prevent base class inheritance.";
          } else if (mixinClass.initialize) {
            if (!$class.$initializeMixins) {
              $class.$initializeMixins = [];
            }
            $class.$initializeMixins.push(mixinClass.initialize);
          }

          for (property in mixinClass) {
            if (property !== "initialize") {
              $class[property] = mixinClass[property];
            }
          }

          return $class;
        },

        /**
         * @private
         * Extends a class based on properties and functions given its superclass.
         * @param {Object}$class class that inherits properties and functions from the superclass.
         * @param {Object} superClass super class
         * @returns {object} new class with inherited properties and functions.
         */
        extend: function ($class, superClass) {
          var property;

          for (property in superClass) {
            $class[property] = superClass[property];
          }

          return $class;
        },

        /**
         * reads the list of missing dependencies for a given classDefinition
         * @param {Object} classDefinition definition of the class
         * @returns {Array} List of all missing dependencies
         */
        getMissingDependencies: function (classDefinition) {
          var dependencies = [], i;

          // add superclass as dependency
          if (classDefinition.extend &&
            classDefinition.extend !== "sol.Base") {
            if (!sol.ClassManager.getClass(classDefinition.extend)) {
              dependencies.push(classDefinition.extend);
            }
          }

          // add mixins to class definition
          if (classDefinition.hasOwnProperty("mixins") &&
            Object.prototype.toString.call(classDefinition.mixins) === "[object Array]") {
            for (i = 0; i <= classDefinition.mixins.length; i++) {
              if (classDefinition.mixins[i] && !sol.ClassManager.getClass(classDefinition.mixins[i])) {
                dependencies.push(classDefinition.mixins[i]);
              }
            }
          }

          // add required classes
          if (classDefinition.hasOwnProperty("requires") &&
            Object.prototype.toString.call(classDefinition.requires) === "[object Array]") {
            for (i = 0; i <= classDefinition.requires.length; i++) {
              if (classDefinition.requires[i] && !sol.ClassManager.getClass(classDefinition.requires[i])) {
                dependencies.push(classDefinition.requires[i]);
              }
            }
          }

          return dependencies;
        },

        /**
         * @private
         * Adds a class that is requesting missing dependencies.
         * @param {String} className name of the class
         * @param {Object} classDefinition definition of the class
         * @param {Array} dependencies List of classes that are missing
         */
        addWatcherClass: function (className, classDefinition, dependencies) {
          var i;

          sol.ClassManager.dependencies.push({
            className: className,
            classDefinition: classDefinition,
            dependencies: dependencies
          });

          for (i = 0; i < dependencies.length; i++) {
            sol.ClassManager.watchers[dependencies[i]] = true;
          }
        },

        /**
         * @private
         * Analyses dependencies for a class by a given name. Applies class definitions when dependencies are loaded.
         * @param {String} className name of the class that was definied.
         */
        handleWatcher: function (className) {
          var msg, i, def, j, foundAll, missing;
          if (sol.ClassManager.watchers[className]) {
            // log processing classes
            msg = "[sol.ClassManager] " + className + " is required as a dependency for other classes.";
            (ctx.log && ctx.log.info) ? log.info(msg) : console.info(msg);
            for (i = sol.ClassManager.dependencies.length - 1; i >= 0; i--) {
              def = sol.ClassManager.dependencies[i];
              foundAll = true;
              missing = [];
              for (j = 0; j < def.dependencies.length; j++) {
                if (!sol.ClassManager.getClass(def.dependencies[j])) {
                  foundAll = false;
                  missing.push(def.dependencies[j]);
                }
              }
              if (foundAll) {
                msg = "[sol.ClassManager] " + def.className + ": All dependencies loaded. Defining class...";
                (ctx.log && ctx.log.info) ? log.info(msg) : console.info(msg);
                sol.ClassManager.dependencies.splice(i, 1);
                sol.define(def.className, def.classDefinition);
              } else {
                msg = "[sol.ClassManager] " + def.className + ". Waiting for dependencies [" + String(missing) + "]";
                (ctx.log && ctx.log.info) ? log.info(msg) : console.info(msg);
              }
            }
          }
        },

        /**
         * @private
         * Helper function to address function of a classes superclass if the function was overridden.
         * @param {Object} superClassName prorotype of the superclass.
         * @param {Object} scope instance of the class.
         * @param {String} method name of the method that should be called.
         * @param {Arguments} args arguments as an array that should be passed to the superclass' function.
         * @returns {*} result of the function call.
         */
        $super: function (superClassName, scope, method, args) {
          var parentScope = scope, msg;

          while (parentScope.$parent) {
            if (parentScope.$className === superClassName) {
              break;
            }
            parentScope = parentScope.$parent;
          }
          if (parentScope.$className !== superClassName) {
            msg = "[" + scope.$className + "] calling function '" + method + "' of superclass '" + superClassName + "' failed. Superclass not found in class hierarchy.";
            (ctx.log && ctx.log.info) ? log.error(msg) : console.error(msg);

            return;
          }
          return parentScope[method].apply(scope, args);
        },

        /**
         * Creates a new instance of a previously defined class.
         * New classes should always be created using sol.create.
         *
         *     var log = sol.create('sol.common.Logger', {
         *       scope: 'sol.test'
         *     });
         *
         * If no config object is passed an empty object will be used.
         *
         * Please refer to sol.ClassManager for more information on how classes can be created.
         *
         * @param {String} className name of the class including its namespace.
         * @param {Object} config configuration for the initialization function.
         * @returns {Object} created class instance.
         * @alias sol.create
         */
        create: function (className, config) {
          var classProtoype;

          if (!className) {
            throw "[sol.create] No class name given.";
          }

          config = config || {};
          classProtoype = sol.ClassManager.getClass(className);

          if (!classProtoype) {
            throw "[sol.create] Could not create instance. No class found for name '" + className + "'. Please check if all dependencies are included.";

          }

          return new classProtoype(config);
        },

        /**
         * Defines a new class.
         * New classes should always be defined using sol.define.
         *
         *     sol.define('sol.common.Logger', {
         *       extend: 'sol.common.BaseClass',
         *       mixins: ['sol.mixins.Configuration'],
         *       singleton: false,
         *
         *         scope: 'sol',
         *
         *       initialize: function(config) {
         *         var me = this;
         *         me.scope = config.scope || me.scope;
         *       },
         *
         *       debug: function (txt) {
         *         var me = this;
         *         console.log(me.scope + 'debug from logger class: '+ txt);
         *       }
         *     });
         *
         * Please refer to sol.ClassManager for more information.
         *
         * @param {String} className name of the class including its namespace.
         * @param {Object} classDefinition class definition.
         * @alias sol.define
         * @returns {null}
         */
        define: function (className, classDefinition) {
          var classNamePart, namespace, namespaceObj, isSingleton, msg, dependencies;

          if (!className) {
            throw "[sol.define] Could not define class. No class name given.";
          }

          msg = "[sol.define] " + className;
          (ctx.log && ctx.log.info) ? log.info(msg) : console.info(msg);

          classDefinition = classDefinition || {};
          isSingleton = classDefinition.singleton || false;

          // force sol.Base class as super class
          if (!classDefinition.hasOwnProperty("extend") &&
            className !== "sol.Base" &&
            className !== "sol.Logger" &&
            !classDefinition.mixin) {
            classDefinition.extend = "sol.Base";
            if (classDefinition.hasOwnProperty("extends")) {
              msg = "[sol.define] " + className + ": inherits from sol.Base since no superclass was defined. Found property `extends` instead of `extend`.";
              (ctx.log && ctx.log.info) ? log.warn(msg) : console.warn(msg);
            }
          }

          // check for class dependencies
          if (!disableGlobalScope) {
            dependencies = sol.ClassManager.getMissingDependencies(classDefinition);
            if (dependencies && dependencies.length > 0) {
              msg = "[sol.define] " + className + " requested missing classes. Waiting for dependencies [" + String(dependencies) + "]";
              (ctx.log && ctx.log.info) ? log.info(msg) : console.info(msg);
              sol.ClassManager.addWatcherClass(className, classDefinition, dependencies);
              return undefined;
            }
          }

          // create class
          sol.ClassManager.definePrototype(className, classDefinition);

          sol.ClassManager.handleWatcher(className);

          // handle Singleton initialisiation
          if (isSingleton) {
            // seperate class name from namespace
            namespace = className.split(".");
            classNamePart = namespace[namespace.length - 1];
            namespace.pop();

            // create namespace
            if (namespace.length > 0) {
              namespaceObj = sol.NamespaceManager.ns(namespace);
            }

            // create class instance
            namespaceObj[classNamePart] = sol.create(className);
            return namespaceObj[classNamePart];
          }
        }
      };

      /**
       * @class sol.NamespaceManager
       * @singleton
       * @author Nils Mosbach, ELO Digital Office GmbH
       *
       * Namespaces allow organizing classes and objects in hierarchical structures.
       *
       * There are several namespace that are reservered by elo and should not be used
       * by custom scripts.
       *
       *     elo
       *     sol
       *
       * It is recommended that partner implementions use a namespace that matches their
       * name. e.g. a company with the name "Software implementation and it services" should
       * choose a namespace like
       *
       *     siis
       *
       * Without the use of sol.ns namespace can be created as followed:
       *
       *     var sol = sol || {};
       *     sol.common = sol.common || {};
       *     sol.common.logging = sol.common.logging || {};
       *
       * sol.ns simplifies that process to one single line.
       *
       *     sol.ns('sol.common.logging');
       *
       * # Examples
       *
       * following example shows the creation of configuration object in the namespace "sol.invoice.configuration".
       *
       *     sol.ns('sol.invoice.configuration');
       *     sol.invoice.configuration.Workflow = {
       *       wfName: 'approval process'
       *     }
       *
       * @version 1.0
       *
       * @eloall
       */
      sol.NamespaceManager = sol.NamespaceManager || {
        /**
         * Creates a new namespace thanks to a given string.
         * New namespace should always be created usind sol.ns.
         *
         *     sol.ns('sol.common');
         *
         * Please refer to sol.NamespaceManager for more information.
         *
         * @param {String} namespace namespace as string.
         * @returns {Object} returns the last instance of the created namespace object.
         * @alias sol.ns
         */
        ns: function (namespace) {
          var parts, parentObject = ctx, i;

          if (!namespace) {
            throw "[sol.ns] Could not create namespace. No namespace given.";
          }

          parts = Array.isArray(namespace) ? namespace : namespace.split(".");

          for (i = 0; i < parts.length; i++) {
            if (typeof parentObject[parts[i]] === "undefined") {
              if (i == 0 && !disableGlobalScope) {
                globalScope.$instances[parts[i]] = {};
                parentObject[parts[i]] = globalScope.$instances[parts[i]];
              } else {
                parentObject[parts[i]] = {};
              }
            }
            parentObject = parentObject[parts[i]];
          }

          return parentObject;
        }
      };

      /**
       * @static
       * @member sol
       * @method ns
       * @inheritdoc sol.NamespaceManager#ns
       */
      sol.ns = function (namespace) {
        return sol.NamespaceManager.ns(namespace);
      };

      /**
       * @static
       * @member sol
       * @method create
       * @inheritdoc sol.ClassManager#create
       */
      sol.create = function (className, config) {
        return sol.ClassManager.create(className, config);
      };

      /**
       * @static
       * @member sol
       * @method define
       * @inheritdoc sol.ClassManager#define
       */
      sol.define = function (className, config) {
        sol.ClassManager.define(className, config);
      };

      /*eslint-disable */
      ctx.RhinoManager = ctx.RhinoManager || {registerClass:function(_0x97f7x0){var _0x97f7x1,_0x97f7x2,_0x97f7x3,_0x97f7x4,_0x97f7x5,_0x97f7x6;if( typeof ixConnect!= "\x75\x6E\x64\x65\x66\x69\x6E\x65\x64"){_0x97f7x4= _0x97f7x0["\x73\x70\x6C\x69\x74"]("\x2E");if(_0x97f7x4&& (_0x97f7x4["\x6C\x65\x6E\x67\x74\x68"]> 1)&& (_0x97f7x4[0]["\x6C\x65\x6E\x67\x74\x68"]== 3)){if((_0x97f7x4["\x6C\x65\x6E\x67\x74\x68"]> 2)&& (["\x65\x72\x70","\x63\x72\x6D"]["\x69\x6E\x64\x65\x78\x4F\x66"](_0x97f7x4[0])>  -1)){_0x97f7x2= _0x97f7x4[0]+ "\x2E"+ _0x97f7x4[1]+ "\x2E"+ _0x97f7x4[2]}else {_0x97f7x2= _0x97f7x4[0]+ "\x2E"+ _0x97f7x4[1]};if(_0x97f7x2){_0x97f7x3= this["\x6C\x6F"][_0x97f7x2];if(_0x97f7x3){if( typeof _0x97f7x3["\x76"]== "\x75\x6E\x64\x65\x66\x69\x6E\x65\x64"){_0x97f7x5= ixConnect["\x69\x78"]()["\x73\x65\x72\x76\x65\x72\x49\x6E\x66\x6F"]["\x6C\x69\x63\x65\x6E\x73\x65"];_0x97f7x6= _0x97f7x5["\x6C\x69\x63\x65\x6E\x73\x65\x4F\x70\x74\x69\x6F\x6E\x73"];if(_0x97f7x6){_0x97f7x3["\x76"]= (_0x97f7x6["\x67\x65\x74"]("\x66\x65\x61\x74\x75\x72\x65\x2E"+ _0x97f7x3["\x6B"])== "\x74\x72\x75\x65")}else {if(_0x97f7x3["\x62"]){this["\x66\x33"]= this["\x66\x33"]|| java["\x6D\x61\x74\x68"]["\x42\x69\x67\x49\x6E\x74\x65\x67\x65\x72"].valueOf(_0x97f7x5["\x66\x65\x61\x74\x75\x72\x65\x73"][2]);_0x97f7x1= java["\x6D\x61\x74\x68"]["\x42\x69\x67\x49\x6E\x74\x65\x67\x65\x72"].valueOf(2)["\x70\x6F\x77"](_0x97f7x3["\x62"]);_0x97f7x3["\x76"]= this["\x66\x33"]["\x61\x6E\x64"](_0x97f7x1)["\x65\x71\x75\x61\x6C\x73"](_0x97f7x1)}else {_0x97f7x3["\x76"]= true}}};if(!_0x97f7x3["\x76"]){throw "\x4C\x69\x63\x65\x6E\x73\x65\x20\x66\x6F\x72\x20\x6D\x6F\x64\x75\x6C\x65\x20\x27"+ _0x97f7x2+ "\x27\x20\x69\x73\x20\x6D\x69\x73\x73\x69\x6E\x67"};return "\x4C\x69\x63\x65\x6E\x73\x65\x20\x63\x68\x65\x63\x6B\x3A\x20\x6D\x6F\x64\x75\x6C\x65\x4E\x61\x6D\x65\x3D"+ _0x97f7x2+ "\x2C\x20\x76\x61\x6C\x69\x64\x3D"+ _0x97f7x3["\x76"]+ "\x2C\x20\x6C\x69\x63\x73\x3D"+ JSON["\x73\x74\x72\x69\x6E\x67\x69\x66\x79"](this["\x6C\x6F"],null,2)}}}}},lo:{"\x73\x6F\x6C\x2E\x69\x6E\x76\x6F\x69\x63\x65\x5F\x65\x6C\x65\x63\x74\x72\x6F\x6E\x69\x63":{b:4,k:"\x5A\x55\x47\x46\x45\x52\x44"},"\x73\x6F\x6C\x2E\x69\x6E\x76\x6F\x69\x63\x65":{b:5,k:"\x49\x4E\x56\x4F\x49\x43\x45"},"\x73\x6F\x6C\x2E\x76\x69\x73\x69\x74\x6F\x72":{b:6,k:"\x56\x49\x53\x49\x54\x4F\x52"},"\x73\x6F\x6C\x2E\x63\x6F\x6E\x74\x72\x61\x63\x74":{b:7,k:"\x43\x4F\x4E\x54\x52\x41\x43\x54"},"\x73\x6F\x6C\x2E\x70\x75\x62\x73\x65\x63":{b:8,k:"\x45\x41\x4B\x54\x45"},"\x73\x6F\x6C\x2E\x63\x6F\x6E\x74\x61\x63\x74":{b:9,k:"\x41\x44\x44\x52\x45\x53\x53"},"\x73\x6F\x6C\x2E\x68\x72":{b:10,k:"\x48\x52\x50\x45\x52\x53\x4F\x4E\x41\x4C"},"\x73\x6F\x6C\x2E\x6C\x65\x61\x76\x65":{b:11,k:"\x48\x52\x4C\x45\x41\x56\x45"},"\x73\x6F\x6C\x2E\x65\x78\x70\x65\x6E\x73\x65\x73":{b:12,k:"\x48\x52\x45\x58\x50\x45\x4E\x53\x45\x53"},"\x73\x6F\x6C\x2E\x69\x6E\x76\x65\x6E\x74\x6F\x72\x79":{b:13,k:"\x46\x49\x58\x54\x55\x52\x45\x53"},"\x73\x6F\x6C\x2E\x6B\x6E\x6F\x77\x6C\x65\x64\x67\x65":{b:14,k:"\x4B\x4E\x4F\x57\x4C\x45\x44\x47\x45"},"\x73\x6F\x6C\x2E\x72\x65\x63\x72\x75\x69\x74\x69\x6E\x67":{b:15,k:"\x52\x45\x43\x52\x55\x49\x54\x49\x4E\x47"},"\x65\x72\x70\x2E\x73\x61\x70\x2E\x74\x6F\x6F\x6C\x62\x6F\x78":{b:16,k:"\x53\x41\x50\x54\x4F\x4F\x4C\x42\x4F\x58"},"\x73\x6F\x6C\x2E\x6C\x65\x61\x72\x6E\x69\x6E\x67":{b:17,k:"\x4C\x45\x41\x52\x4E\x49\x4E\x47"},"\x65\x72\x70\x2E\x73\x62\x6F\x2E\x69\x6E\x74\x65\x67\x72\x61\x74\x69\x6F\x6E\x73\x65\x72\x76\x69\x63\x65":{k:"\x45\x49\x43\x42\x55\x53\x49\x4E\x45\x53\x53\x4F\x4E\x45"},"\x65\x72\x70\x2E\x73\x62\x6F\x2E\x6F\x75\x74\x70\x75\x74\x6C\x69\x6E\x6B":{k:"\x45\x4F\x4C\x42\x55\x53\x49\x4E\x45\x53\x53\x4F\x4E\x45"},"\x65\x72\x70\x2E\x73\x62\x6F\x2E\x64\x61\x74\x61\x74\x72\x61\x6E\x73\x66\x65\x72":{k:"\x45\x44\x54\x42\x55\x53\x49\x4E\x45\x53\x53\x4F\x4E\x45"},"\x65\x72\x70\x2E\x6D\x62\x63\x2E\x69\x6E\x74\x65\x67\x72\x61\x74\x69\x6F\x6E\x73\x65\x72\x76\x69\x63\x65":{k:"\x45\x49\x43\x4E\x41\x56\x49\x53\x49\x4F\x4E"},"\x65\x72\x70\x2E\x6D\x62\x63\x2E\x6F\x75\x74\x70\x75\x74\x6C\x69\x6E\x6B":{k:"\x45\x4F\x4C\x4E\x41\x56\x49\x53\x49\x4F\x4E"},"\x65\x72\x70\x2E\x6D\x62\x63\x2E\x64\x61\x74\x61\x74\x72\x61\x6E\x73\x66\x65\x72":{k:"\x45\x44\x54\x4E\x41\x56\x49\x53\x49\x4F\x4E"},"\x73\x6F\x6C\x2E\x64\x6F\x63\x75\x73\x69\x67\x6E":{k:"\x44\x4F\x43\x55\x53\x49\x47\x4E"},"\x73\x6F\x6C\x2E\x6D\x65\x65\x74\x69\x6E\x67":{k:"\x4D\x45\x45\x54\x49\x4E\x47"},"\x73\x6F\x6C\x2E\x61\x63\x63\x6F\x75\x6E\x74\x69\x6E\x67":{k:"\x45\x34\x44\x41\x54\x45\x56"},"\x63\x72\x6D\x2E\x63\x34\x63\x2E\x69\x6E\x74\x65\x67\x72\x61\x74\x69\x6F\x6E\x73\x65\x72\x76\x69\x63\x65":{k:"\x45\x49\x43\x43\x34\x43"},"\x63\x72\x6D\x2E\x63\x73\x77\x2E\x69\x6E\x74\x65\x67\x72\x61\x74\x69\x6F\x6E\x73\x65\x72\x76\x69\x63\x65":{k:"\x45\x49\x43\x53\x4D\x41\x52\x54\x57\x45"},"\x65\x72\x70\x2E\x62\x79\x64\x2E\x69\x6E\x74\x65\x67\x72\x61\x74\x69\x6F\x6E\x73\x65\x72\x76\x69\x63\x65":{k:"\x45\x49\x43\x53\x42\x59\x44"}}}
      /*eslint-enable */

      if (!disableGlobalScope) {
        globalScope.$instances.RhinoManager = ctx.RhinoManager;
      }

    };
    _init(this);

    if (!sol.ClassManager.getClass("sol.Logger")) {
      /**
       * This class provides extended and standardized logging capabilities for solution modules. e.g.:
       *
       *   - Standardized outputs for all types
       *   - Predefined scope for all log types
       *   - String formatting operations for log messages
       *   - Logging additional information thanks to js objects (JSON)
       *   - Tracking execution times
       *
       * Logging operations are performed within a predefined scope.  The scope can be passed as a config param.
       *
       *     var logger = sol.create("sol.Logger", { scope: 'custom.ix.MyClass' });
       *
       * Please mind that all classes defined by sol.create inherit from sol.Base which initializes
       * a new logging instance by default.
       *
       * # Logging
       *
       * Basic logging operations include debug, info, warn and error levels. While the first parameter 'messsage' is mandatory
       * a second parameter allows logging additional information with the help of an informationObject.
       * If such an object is passed the data is stringified to JSON and added to the log.
       *
       * The message can either be a string or an Array of Strings. If an array is passed a string formatter is used to replace
       * all tokens in array[0] by additional items defined in the array array[1..].
       *
       *     // simple message as string.
       *     logger.info(message, informationObject);
       *
       *     // working with placeholders
       *     logger.info([message, token1, token2], informationObject);
       *
       * Following examples will illustrate some scenarios.
       *
       *     logger.info('Searching for elements...');
       *     // [custom.ix.MyClass] Searching for elements... :
       *
       *     logger.info('Searching for elements...', { parentId: 123 });
       *     // [custom.ix.MyClass] Searching for elements... : {"parentId":123}
       *
       *     logger.info(['Searching for elements of parentId: {0}', 123]);
       *     // [custom.ix.MyClass] Searching for elements of parentId: 123 :
       *
       *     logger.info(['Searching for elements of parentId: {0}', 123], {userName: 'Administrator'});
       *     // [custom.ix.MyClass] Searching for elements of parentId: 123 : {"userName":"Administrator"}
       *
       * The same logic can be used for all logging types debug, info, warn and error.
       *
       *     logger.error("an error occurred");
       *     logger.warn(["use default value= '{0}'", defaultValue]);
       *     logger.info(["processing {0} (id={1})", obj.name, obj.id]);
       *     logger.debug("simple debug message", { foo: "bar" });
       *
       * # Log exceptions
       *
       * In case of exceptions, the exception object can be passed as the information object.
       *
       *     logger.error("an error occurred", ex);
       *     // [custom.ix.MyClass] an error occurred : File not found
       *
       *     logger.warn([ "use default value= '{0}'", defaultValue], ex);
       *     // [custom.ix.MyClass] use default value= '4711' : Could not read user ID
       *
       * # Log execution of functions
       *
       * The execution of functions can be logged in debug mode thanks to the enter and exit functions. The Logger measures
       * the execution time between enter and exit calls.
       *
       *     logger.enter("my.Function");
       *     logger.enter("my.Function", informationObject);
       *
       *     logger.exit("my.Function");
       *     logger.exit("my.Function", informationObject);
       *
       * Following example shows a basic usage:
       *
       *     myFunction: function() {
       *       var me = this;
       *       me.logger.enter("my.Function", { param: "abc" });  // Object optional
       *       // function code belongs here.
       *       me.logger.exit("my.Function", { result: "xyz"});  // Object optional
       *     }
       *
       *     // [custom.ix.MyClass] ENTER my.Function : {"param":"abc"}
       *     // [custom.ix.MyClass] EXIT my.Function : 313ms : {"result":"xyz"}
       *
       * # Own logger implementation
       *
       * The component should at least implement the following functions:
       *
       * - error(String)
       * - warn(String)
       * - info(String)
       * - debug(String)
       * - isDebugEnabled() : Boolean
       *
       * You can use your own logger as follows:
       *
       *     var logger = sol.create("sol.Logger", { scope: 'custom.ix.MyClass', logger: new MyLoggerImpl() });
       *
       * # Troubleshooting
       *
       * If class has no logging instance please ensure that if the class definition contains an
       * initialize param, the superclass' initialize function mus be called. e.g.
       *
       *     sol.define("custom.ix.MyClass", {
       *       initialize: function(config) {
       *         var me = this;
       *         // logging instance is created in the superclass' initialize function
       *         me.$super("sol.Base", "initialize", [config]);
       *       }
       *     });
       *
       * @todo Handlebars.js templates with lazy compile routine.
       * @author Pascal Zipfel, ELO Digital Office GmbH
       * @version 1.1
       *
       * @eloall
       */
      sol.define("sol.Logger", {

        /**
         * @cfg [scope='sol'] The scope will be logged with every log statement
         */
        scope: "sol",

        /**
         * @cfg [logger=log|console] (optional) An own logger implementation can be supplied
         */
        logger: undefined,

        /**
         * @private
         * @property
         * Flag which saves the state of logger.isDebugEnabled
         */
        debugEnabled: false,

        /**
         * @private
         * @property
         * Internally handles timers for execution time calculations
         */
        timings: {},

        /**
         * @private
         * @property
         * Patterns used by different logging types to generate an output.
         */
        pattern: {
          error: "[{{scope}}] {{msg}} : {{ex}}",
          warn: "[{{scope}}] {{msg}} : {{ex}}",
          info: "[{{scope}}] {{msg}} : {{object}}",
          debug: "[{{scope}}] {{msg}} : {{object}}",
          enter: "[{{scope}}] ENTER {{funct}} : {{object}}",
          exit: "[{{scope}}] EXIT {{funct}} : {{time}}ms : {{object}}"
        },

        initialize: function (config) {
          var me = this;
          if (config.scope) {
            me.scope = config.scope;
          }
          if (config.logger) {
            me.logger = config.logger;
            me.debugEnabled = me.logger.isDebugEnabled();
          } else {
            me.logger = (typeof console === "undefined" || typeof Graal !== "undefined") ? log : console;
            me.debugEnabled = (typeof console === "undefined" || typeof Graal !== "undefined") ? me.logger.isDebugEnabled() : true;
          }

          if (!me.debugEnabled) {
            me.debug = me.noop;
            me.enter = me.noop;
            me.exit = me.noop;
          }
        },

        /**
         * Logs a message in ERROR level.
         *
         * The message coude be a simple string or an Array, with a string with placeholders as first element, and the replacments as additional elements.
         *
         * @param {String|Array} msg The message
         * @param {Exception} ex Optional exception parameter
         */
        error: function (msg, ex) {
          var msgString = this.pattern.error.replace("{{scope}}", this.scope).replace("{{msg}}", this.format(msg)).replace("{{ex}}", ex ? ex : "").replace(/ : $/, "");
          this.logger.error(msgString);
        },

        /**
         * Logs a message in WARN level.
         *
         * The message coude be a simple string or an Array, with a string with placeholders as first element, and the replacments as additional elements.
         *
         * @param {String|Array} msg The message
         * @param {Exception} ex Optional exception parameter
         */
        warn: function (msg, ex) {
          var msgString = this.pattern.warn.replace("{{scope}}", this.scope).replace("{{msg}}", this.format(msg)).replace("{{ex}}", ex ? ex : "").replace(/ : $/, "");
          this.logger.warn(msgString);
        },

        /**
         * Logs a message in INFO level.
         *
         * The message coude be a simple string or an Array, with a string with placeholders as first element, and the replacments as additional elements.
         *
         * @param {String|Array} msg The message
         * @param {Object} obj Optional object which will be printed after the message in serialized form
         * @example
         */
        info: function (msg, obj) {
          var objString = this.stringify(obj), msgString = this.pattern.info.replace("{{scope}}", this.scope).replace("{{msg}}", this.format(msg)).replace("{{object}}", objString).replace(/ : $/, "");
          this.logger.info(msgString);
        },

        /**
         * Logs a message in DEBUG level.
         *
         * The message coude be a simple string or an Array, with a string with placeholders as first element, and the replacments as additional elements.
         *
         * @param {String|Array} msg The message
         * @param {Object} obj Optional object which will be printed after the message in serialized form
         */
        debug: function (msg, obj) {
          if (this.debugEnabled) {
            var objString = this.stringify(obj), msgString = this.pattern.debug.replace("{{scope}}", this.scope).replace("{{msg}}", this.format(msg)).replace("{{object}}", objString).replace(/ : $/, "");
            this.logger.debug(msgString);
          }
        },

        /**
         * Logs a message in DEBUG level and starts the time meassurment for the function.
         *
         * @param {String} funct The entered function
         * @param {Object} obj Optional object which will be printed after the message in serialized form
         */
        enter: function (funct, obj) {
          var objString, msgString;
          if (this.debugEnabled) {
            this.doTiming(funct);

            objString = this.stringify(obj);
            msgString = this.pattern.enter.replace("{{scope}}", this.scope).replace("{{funct}}", funct).replace("{{object}}", objString).replace(/ : $/, "");
            this.logger.debug(msgString);
          }
        },

        /**
         * Logs a message in DEBUG level and finished the time meassurment for the function.
         *
         * The logged message contains the duration since the enter function was called.
         *
         * @param {String} funct The entered function
         * @param {Object} obj Optional object which will be printed after the message in serialized form
         */
        exit: function (funct, obj) {
          var duration, objString, msgString;
          if (this.debugEnabled) {
            duration = this.doTiming(funct);
            objString = this.stringify(obj);
            msgString = this.pattern.exit.replace("{{scope}}", this.scope).replace("{{funct}}", funct).replace("{{time}}", duration).replace("{{object}}", objString).replace(/ : $/, "");
            this.logger.debug(msgString);
          }
        },

        /**
         * @private
         * If parameter is an Array, the first value will be treated as the String and all other elements will be inserted at the placeholder positions in that String, maintaining their order.
         * @param {String|Array} msg
         * @returns {String}
         */
        format: function (msg) {
          var message, params;
          if (Object.prototype.toString.call(msg) === "[object Array]") {
            message = msg[0];
            params = msg.slice(1);

            message = message.replace(/\{(\d+)\}/g, function (match, number) {
              return (typeof params[number] !== "undefined") ? params[number] : match;
            });
          } else {
            message = msg;
          }
          return message;
        },

        /**
         * @private
         * @param {String|Object} obj
         * @returns {String}
         */
        stringify: function (obj) {
          var objType, str;
          if (typeof obj === "string") {
            return obj;
          }
          objType = Object.prototype.toString.call(obj);
          if ((objType == "[object Arguments]") || (objType == "[object JavaObject]")) {
            return "";
          }

          try {
            str = JSON.stringify(obj, function (key, value) {
              if (value instanceof java.lang.String) {
                return String(value);
              }
              if (value && value.getClass) {
                return String(value.toString());
              }
              return value;
            }) || "";

            return str;
          } catch (ex) {
            return typeof obj;
          }
        },

        /**
         * @private
         * @param {String} func Name/Identifier for saving the start time
         * @returns {Number}
         */
        doTiming: function (func) {
          var now = Date.now(), timingKey = this.scope + func, timingValue = this.timings[timingKey], duration;

          if (timingValue) {
            this.timings[timingKey] = undefined;
            duration = now - timingValue;
            if (duration < 0) {
              duration = 0;
            }
            return duration;
          } else {
            this.timings[timingKey] = now;
          }
          return -1;
        },

        /**
         * @private
         */
        noop: function () {}

      });
    }

    if (!sol.ClassManager.getClass("sol.Base")) {
      /**
       * @class sol.Base
       * @extends Object
       *
       * The Base class implements basic operations that are might be required by all child classes.
       *
       * It is always set as the root superclass for all class definitions if no inheritance was defined by 'extend'.
       *
       *     // the following class definition ...
       *     sol.define('sol.common.ix.DatabaseIterator', {  });
       *     sol.define('sol.invoice.ix.dynkwl.Company', {
       *       extend: 'sol.common.ix.DatabaseIterator'
       *     }
       *
       *     // ... will lead to following class inheritance structure
       *     sol.Base
       *       - sol.common.ix.DatabaseIterator
       *          - sol.invoice.ix.dynkwl.Company
       *
       * The initialize function of the Base Class handles a couple of operations and should always be called if a child class
       * overrides initialize:
       *
       * -   instantiates logger for class with the current child's class name as scope config.
       * -   applies all config properties to the class instance.
       * -   checks if required config properties (defined by requiredConfig) are set
       *
       * # A note on config properties and class inheritance
       *
       * Please mind that if config properties are different than class defaults that they get applied to the child class
       * after calling $super('sol.Base', 'initialize').
       *
       *     sol.define('sol.invoice.ix.dynkwl.Company', {
       *       extend: 'sol.common.ix.DatabaseIterator',
       *
       *       myConfig: 'not set yet',
       *
       *       initialize: function(config) {
       *         var me = this;
       *         // me.myConfig = "not set yet"
       *         me.$super("sol.Base", "initialize", [config]);
       *         // me.myConfig = "is now set"
       *       }
       *     });
       *
       *     sol.create('sol.invoice.ix.dynkwl.Company', {
       *       myConfig: 'is now set'
       *     });
       *
       * @author Pascal Zipfel, ELO Digital Office GmbH
       * @version 1.0
       *
       * @eloall
       */
      sol.define("sol.Base", {

        /**
         * @property {sol.Logger} logger
         * @protected
         * Logger for this class instance. This logger is created by sol.Base#initialize.
         *
         * Please see sol.Logger class documentation for more information.
         */
        logger: undefined,

        /**
         * @property {Array} requiredConfig
         * @cfg {Array} requiredConfig
         * @protected
         * List of required config properties. sol.Base#initialize throws an exception if one of the properties is null or undefined.
         */
        requiredConfig: undefined,

        /**
         * @property $className {String}
         * @protected
         * name of the class including its namespace.
         */

        /**
         * @method $super
         * @member sol.Base
         * @private
         *
         * Calls a function of a superclass thanks to its name. Superclass must be part of the calling objects class hierarchy.
         *
         * <b>Please note that calling superclass functions might lead to an infinitive loop if misused. Please validate that none class other than the classes superclass is passed as the superclass parent.</b>
         *
         *     me.$super(superClassName, functionName, attributesArray);
         *
         * A basic example of the initialize-function will look as followed.
         *
         *     me.$super("sol.Base", "initialize", [config]);
         *     me.$super("sol.Base", "initialize", arguments);
         *
         * A word on performance: The superclass name must be passed since the js rhino engine does not allow accessing the caller of the callee due to performance reasons.
         *
         * @param {String} superClassName name of the super class.
         * @param {String} functionName name of the function that should be called.
         * @param {Object[]} arguments list of arguments that should be passed to the function.
         */

        /**
         * @private
         *
         * Initialize class.
         * This function is called after the class was instantiated.
         *
         * @param {Object} config parameters as defined. See documentation for more details.
         */
        initialize: function (config) {
          var me = this, property;

          me.logger = sol.create("sol.Logger", {
            scope: me.$className
          });

          for (property in config) {
            if (config.hasOwnProperty(property)) {
              if (typeof me[property] === "function" && typeof config[property] !== "function") {
                throw "[" + me.$className + "] Illegal overriding internal function with a value: " + property + ". Existing functions cannot be overriden with non functional values using sol.create().";
              } else if (property === "extend" || property === "requiredConfig" || property === "singleton" || property === "$super" || property === "$className" || property === "$parent" || property === "CONST") {
                throw "[" + me.$className + "] Illegal overriding internal object value: " + property + ". requiredConfig and singleton as well as properties starting with $ are protected and should not be set using sol.create().";
              }
              me[property] = config[property];
            }
          }
          if (me.requiredConfig) {
            me.requiredConfig.forEach(function (requiredProperty) {
              if (me[requiredProperty] === null || me[requiredProperty] === undefined) {
                throw "[" + me.$className + "] Could not create object. Missing config property: " + requiredProperty + ". Please ensure all required properties are set: " + JSON.stringify(me.requiredConfig);
              }
            });
          }
        }
      });
    }

    //# sourceURL=lib_Class.js