Show:
                            (function() {
                                'use strict';
                            
                                /**
                                 * Attribute implementation.
                                 *
                                 * @class Attribute
                                 * @constructor
                                */
                                function Attribute(config) {
                                    this.__config__ = config || {};
                                    this.__ATTRS__ = {};
                                }
                            
                                Attribute.prototype = {
                                    constructor: Attribute,
                            
                                    /**
                                     * Retrieves the value of an attribute.
                                     *
                                     * @method get
                                     * @param {String} attr The attribute which value should be retrieved.
                                     * @return {Any} The value of the attribute.
                                     */
                                    get: function(attr) {
                                        var currentAttr = this.constructor.ATTRS[attr];
                            
                                        if (!currentAttr) {
                                            return;
                                        }
                            
                                        if (!this._isInitialized(attr)) {
                                            this._init(attr);
                                        }
                            
                                        var curValue = this.__ATTRS__[attr];
                            
                                        if (currentAttr.getter) {
                                            curValue = this._callStringOrFunction(currentAttr.getter, curValue);
                                        }
                            
                                        return curValue;
                                    },
                            
                                    /**
                                     * Sets the value of an attribute.
                                     *
                                     * @method set
                                     * @param {String} attr The attribute which value should be set.
                                     * @param {Any} value The value which should be set to the attribute.
                                     */
                                    set: function(attr, value) {
                                        var currentAttr = this.constructor.ATTRS[attr];
                            
                                        if (!currentAttr) {
                                            return;
                                        }
                            
                                        if (!this._isInitialized(attr)) {
                                            this._init(attr);
                                        }
                            
                                        if (currentAttr.readOnly) {
                                            return;
                                        }
                            
                                        if (currentAttr.writeOnce && this._isInitialized(attr)) {
                                            return;
                                        }
                            
                                        if (currentAttr.validator && !this._callStringOrFunction(currentAttr.validator, value)) {
                                            return;
                                        }
                            
                                        if (currentAttr.setter) {
                                            value = this._callStringOrFunction(currentAttr.setter, value);
                                        }
                            
                                        this.__ATTRS__[attr] = value;
                                    },
                            
                                    /**
                                     * Calls the provided param as function with the supplied arguments.
                                     * If param provided as string, a corresponding function in this object will
                                     * be called. If provided param is a function, it will be directly called.
                                     *
                                     * @protected
                                     * @method _callStringOrFunction
                                     * @param  {String|Function} stringOrFunction The function which should be called
                                     * @param  {Any|Array} args The arguments which will be provided to the called function
                                     * @return {Any} The returned value from the called function
                                     */
                                    _callStringOrFunction: function(stringOrFunction, args) {
                                        var result = null;
                            
                                        if (!AlloyEditor.Lang.isArray(args)) {
                                            args = [args];
                                        }
                            
                                        if (AlloyEditor.Lang.isString(stringOrFunction) && AlloyEditor.Lang.isFunction(this[stringOrFunction])) {
                                            result = this[stringOrFunction].apply(this, args);
                                        } else if (AlloyEditor.Lang.isFunction(stringOrFunction)) {
                                            result = stringOrFunction.apply(this, args);
                                        }
                            
                                        return result;
                                    },
                            
                                    /**
                                     * Initializes an attribute. Sets its default value depending on the flags of the
                                     * attribute and the passed configuration object to the constructor.
                                     *
                                     * @protected
                                     * @method _init
                                     * @param {String} attr The name of the attribute which have to be initialized.
                                     */
                                    _init: function(attr) {
                                        var value;
                            
                                        var currentAttr = this.constructor.ATTRS[attr];
                            
                                        // Check if there is default value or passed one via configuration object
                                        var hasDefaultValue = Object.prototype.hasOwnProperty.call(currentAttr, 'value');
                                        var hasPassedValueViaConfig = Object.prototype.hasOwnProperty.call(this.__config__, attr);
                            
                                        // If there is valueFn, set the value to be the result of invocation of this function
                                        if (currentAttr.valueFn) {
                                            value = this._callStringOrFunction(currentAttr.valueFn, value);
                            
                                            this.__ATTRS__[attr] = value;
                                        }
                                        // else if the attribute has readOnly flag, set the default value from the attribute,
                                        // regardless if there is value or not
                                        else if (currentAttr.readOnly) {
                                            value = currentAttr.value;
                                        }
                                        // else if the attribute has writeOnce value, set it from the passed configuration or from the
                                        // default value, in this order. Otherwise, return miserable.
                                        else if (currentAttr.writeOnce) {
                                            if (hasPassedValueViaConfig) {
                                                value = this.__config__[attr];
                                            } else if (hasDefaultValue) {
                                                value = currentAttr.value;
                                            } else {
                                                return;
                                            }
                                        }
                                        // These two cases below are easy - set the value to be from the passed config or
                                        // from the default value, in this order.
                                        else if (hasPassedValueViaConfig) {
                                            value = this.__config__[attr];
                                        } else if (hasDefaultValue) {
                                            value = currentAttr.value;
                                        }
                            
                                        // If there is validator, and user passed config object - check the returned value.
                                        // If it is false, then set as initial value the default one.
                                        // However, if there is no default value, just return.
                                        if (currentAttr.validator && hasPassedValueViaConfig && !this._callStringOrFunction(currentAttr.validator, value)) {
                                            if (hasDefaultValue) {
                                                value = currentAttr.value;
                                            } else {
                                                return;
                                            }
                                        }
                            
                                        // If there is setter and user passed config object - pass the value thought the setter.
                                        // The value might be one from defaultFn, default value or provided from the config.
                                        if (currentAttr.setter && hasPassedValueViaConfig) {
                                            value = this._callStringOrFunction(currentAttr.setter, value);
                                        }
                            
                                        // Finally, set the value as initial value to the storage with values.
                                        this.__ATTRS__[attr] = value;
                                    },
                            
                                    /**
                                     * Checks if an attribute is initialized. An attribute is considered as initialized
                                     * when there is an own property with this name in the local collection of attribute values
                                     * for the current instance.
                                     *
                                     * @protected
                                     * @method _isInitialized
                                     * @param {String} attr The attribute which should be checked if it is initialized.
                                     * @return {Boolean} Returns true if the attribute has been initialized, false otherwise.
                                     */
                                    _isInitialized: function(attr) {
                                        return Object.prototype.hasOwnProperty.call(this.__ATTRS__, attr);
                                    }
                                };
                            
                                AlloyEditor.Attribute = Attribute;
                            }());