Nickolay - Task.Joose.Stable-3.02

Documentation | Source

POD ERRORS

Hey! The above document had some coding errors, which are explained below:

Around line 2:

=cut found outside a pod block. Skipping to next block.

Joose = function(){ throw "Modules may not be instantiated." }

Joose.top = this

// Static helpers for Arrays
Joose.A = {

    each : function (array, func, scope) {
        for(var i = 0; i < array.length; i++) func.call(scope || this, array[i], i)
    },
    
    exists : function (array, value) {
        for(var i = 0; i < array.length; i++) 
        	if(array[i] == value) return true
        	
        return false
    },
    
    concat : function (source, array) {
        source.push.apply(source, array)
        return source
    },
    
    grep : function (array, func) {
        var a = []
        Joose.A.each(array, function (t) {
            if (func(t)) a.push(t)
        })
        return a
    },
    
    remove : function (array, removeEle) {
        var a = []
        Joose.A.each(array, function (t) {
            if (t !== removeEle) a.push(t)
        })
        return a
    }
    
}

// Static helpers for Strings
Joose.S = {
	
	saneSplit : function(str, delimeter) {
        var res = (str || '').split(delimeter)
        if (res.length == 1 && !res[0]) res.shift()
        
        return res
	},
	

    uppercaseFirst : function (string) { 
        return string.substr(0, 1).toUpperCase() + string.substr(1, string.length - 1)
    }
    
}


// Static helpers for objects
Joose.O = {

    each : function (object, func, scope) {
        for(var i in object) func.call(scope || this, object[i], i)
        
        if (Joose.is_IE) {
            Joose.A.each([ 'toString', 'constructor', 'hasOwnProperty' ], function(el){
                if (object.hasOwnProperty(el)) func.call(scope || this, object[el], el); 
            })
        } 
    },
    
    
    eachSafe : function (object, func, scope) {
        Joose.O.each(object, function(value, name){
            if (object.hasOwnProperty(name)) func.call(scope || this, value, name)
        }, scope)
    },
    
    
    copy : function (source, target) {
        Joose.O.each(source, function (value, name) { target[name] = value })
        return target
    },
    
    
    copySafe : function (source, target) {
        Joose.O.eachSafe(source, function (value, name) { target[name] = value })
        return target
    },
    
    
    getMutableCopy : function (object) {
        var f = function(){}
        f.prototype = object
        return new f()
    },
    
    
    extend : function (target, source) {
        return Joose.O.copy(source, target)
    },
    
    
    isEmpty : function (object) {
		for (var i in object) if (object.hasOwnProperty(i)) return false
		
		return true
    },
    
    
    isInstance: function(obj) {
        return obj && obj.meta && obj.constructor == obj.meta.c
    },
    
    
    wantArray : function (obj) {
        if (obj instanceof Array) return obj
        
        return [ obj ]
    }
    
}


//// Static helpers for functions?
//Joose.F = {
//    emptyFunction   : function () { return function(){} },
//    newArray        : function () { return [] },
//    newObject       : function () { return {} }
//}


//idea copied from Ext, source rewritten
//returns a function, tied to specifiec scope and arguments
//Joose.F.createDelegate = function (func, scope, argsArray, appendArgs) {
//    return function () {
//        var thisArgs
//        if (appendArgs) {
//            thisArgs = Array.prototype.slice(arguments).concat(argsArray)
//        } else {
//            thisArgs = argsArray
//        }
//        func.apply(scope || joose.top, thisArgs)
//    }
//}


// Rhino is the only popular JS engine that does not traverse objects in insertion order
// Check for Rhino (which uses the global Packages function) and set CHAOTIC_TRAVERSION_ORDER to true
//(function () {
//    
//    if(
//         typeof this["load"] == "function" &&
//         (
//            typeof this["Packages"] == "function" ||
//            typeof this["Packages"] == "object"
//         )
//   ) {
//        joose.CHAOTIC_TRAVERSION_ORDER = true
//   }
//})()


//XXX needs to be checked for IE8
try {
    Joose.is_IE = /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)
} catch (e) {
    Joose.is_IE = false
};
(function(){

    Joose.Proto = function(){ throw "Modules may not be instantiated." }
    
    
    Joose.Proto.Object = function (){
        throw "Joose.Proto.Object can't be instantiated"
    }
    
    
        
    var findSuperCall = function(startFrom){
        //sufficient for Joose.Proto.Class
        var self = startFrom.caller
        
        if (!self.SUPER) throw "Invalid call to SUPER"
        
        //self._original is always undefined for Joose.Proto.Class
        return self._original || self.SUPER[self.methodName]
    }
    
    var SUPER = function (){
        return findSuperCall(SUPER).apply(this, arguments)
    }
    
    var SUPERARG = function (){
        return findSuperCall(SUPERARG).apply(this, arguments[0])
    }
    
    //XXX switch to closures    
    var INNER = function (){
        //sufficient for augment modifiers and original methods from Joose.Proto.Class
        var self = INNER.caller.caller
        
        //required for original methods from Joose.Managed.Class which can be also 'around' modifiers
        if (self.SUPER || self.AROUND) self = self.caller
        
        var callstack = self.__INNER_STACK__
        if (!callstack) throw "Invalid call to INNER"
        
        var augmentWrapper = function(){
            var innerCall = callstack.pop()
            
            return innerCall ? innerCall.apply(this, arguments) : undefined
        }
        
        augmentWrapper.__INNER_STACK__ = callstack
        
        return augmentWrapper.apply(this, arguments)
    }        
    
    
    Joose.Proto.Object.prototype = {
        
        SUPERARG : SUPERARG,
        SUPER : SUPER,
        INNER : INNER,        
        
        
        initialize: function () {
        },
        
        
        toString: function () {
            return "a " + this.meta.name
        },
        
        
		detach : function() {
			//already detached
			if (this.meta instanceof Joose.Meta.Class.Detached) return
			
        	var detachedClass = new Joose.Meta.Class.Detached('', { isa : this.constructor }).c
        	
        	detachedClass.meta.stem.open()
        	
        	detachedClass.prototype = this
        	
        	this.meta = detachedClass.meta
        	this.meta.originalClass = this.constructor
        	this.constructor = detachedClass
        	
        	detachedClass.meta.stem.close()
		},
		
		
		attach : function() {
			//not detached
			if (!(this.meta instanceof Joose.Meta.Class.Detached)) return
			
			this.meta.stem.open()
			
			this.constructor.prototype = {}
			
			delete this.constructor
			delete this.meta
		}
        
    }
        
    
    Joose.Proto.Object.meta = {
    	constructor : Joose.Proto.Object,
    	
        methods : Joose.Proto.Object.prototype,
        attributes : {}
    }
    
    Joose.Proto.Object.prototype.meta = Joose.Proto.Object.meta
    
    
    Joose.Proto.Empty = function(){ throw "Joose.Proto.Empty can't be instantiated" }
    
    Joose.Proto.Empty.meta = {
        methods : {},
        attributes : {}
    }
    

})();
(function(){

    Joose.Proto.Class = function () {
        this.initialize.apply(this, arguments)
    }
    
    
    var bootstrap = {
        
        constructor: Joose.Proto.Class,
        superClass : null,
        
        name: null,
        
        attributes: null,
        
        methods: null,
        
        meta: null,
        
        c: null,
        
        defaultSuperClass : Joose.Proto.Object,
        
        
        initialize: function (name, extend) {
            this.name = name
            extend = extend || {}
    
            this.extractConstructor(extend)
            this.c.meta = this
            
            if (extend.constructorOnly) return
            
            this.construct(extend)
        },
        
        
        construct : function (extend) {
            this.extractSuperClass(extend)
            this.processSuperClass()
            
            this.adaptConstructor()
            
            this.processStem(extend)
            
            this.extend(extend)
        },
        
        
        extractConstructor : function (extend) {
            this.c = extend.hasOwnProperty('constructor') ? extend.constructor : this.defaultConstructor()
            delete extend.constructor
        },
        
        
        extractSuperClass : function (extend) {
            this.superClass = extend.isa || this.defaultSuperClass
            delete extend.isa
        },
        
        
        processStem : function () {
            var superMeta = this.superClass.meta
            
            this.methods        = Joose.O.getMutableCopy(superMeta.methods)
            this.attributes     = Joose.O.getMutableCopy(superMeta.attributes)
        },
        
        
        
        defaultConstructor: function () {
            return function defaultConstructor() {
                this.initialize.apply(this, arguments)
            }
        },
        
        
        processSuperClass: function () {
            this.c.prototype    = Joose.O.getMutableCopy(this.superClass.prototype)
            this.c.superClass   = this.superClass.prototype
        },
        
        
        adaptConstructor: function () {
            var c = this.c
        
            //this will fix weird semantic of native "constructor" property to more intuitive (idea borrowed from Ext)
            c.prototype.constructor = c
            c.prototype.meta = this
            c.meta = this
            
            if (!c.hasOwnProperty('toString')) c.toString = function () { return this.meta.name }
        },
    
        
        addMethod: function (name, func) {
            func.SUPER = this.superClass.prototype
            
            //chrome don't allow to redefine the "name" property
            func.methodName = name
            
            this.methods[name] = func
            this.c.prototype[name] = func
        },
        
        
        addAttribute: function (name, init) {
            this.attributes[name] = init
            this.c.prototype[name] = init
        },
        
        
        removeMethod : function (name){
            delete this.methods[name]
            delete this.c.prototype[name]
        },
    
        
        removeAttribute: function (name) {
            delete this.attributes[name]
            delete this.c.prototype[name]
        },
        
        
        hasMethod: function (name) { 
            return Boolean(this.methods[name])
        },
        
        
        hasAttribute: function (name) { 
            return typeof this.attributes[name] != 'undefined'
        },
        
    
        hasOwnMethod: function (name) { 
            return this.hasMethod(name) && this.methods.hasOwnProperty(name)
        },
        
        
        hasOwnAttribute: function (name) { 
            return this.hasAttribute(name) && this.attributes.hasOwnProperty(name)
        },
        
        
        extend : function (props) {
            Joose.O.eachSafe(props, function (value, name) {
                if (name != 'meta' && name != 'constructor') 
                    if (typeof value == 'function' && !value.meta) this.addMethod(name, value); else this.addAttribute(name, value)
            }, this)
        },
    
    
        subClassOf : function(classObject, extend) {
            extend = extend || {}
            extend.isa = classObject || this.c
            return new this.constructor(null, extend).c
        }
        
    }; 
    
    //micro bootstraping
    
    Joose.Proto.Class.prototype = Joose.O.getMutableCopy(Joose.Proto.Object.prototype)
    
    Joose.O.extend(Joose.Proto.Class.prototype, bootstrap)
    
    Joose.Proto.Class.prototype.meta = new Joose.Proto.Class('Joose.Proto.Class', bootstrap);    
    
})();
Joose.Managed = function(){ throw "Modules may not be instantiated." }

Joose.Managed.Property = new Joose.Proto.Class('Joose.Managed.Property', {
	
    name            : null,
    
    props           : null,
    value           : null,
    
    definedIn       : null,
    
    
    initialize : function(name, props) {
        this.name           = name
        this.props          = props
        
        this.definedIn      = props.definedIn
        
        this.computeValue(props)
    },
    
    
    computeValue : function(props){
        this.value = props.init
    },    
    
    
    //targetClass is still open at this stage ;)
    prepareApply : function(targetClass){
    },
    
    
    apply : function(target){
        target[this.name] = this.value
    },
    
    
    isAppliedTo : function(target) {
        return target[this.name] == this.value
    },
    
    
    unapply : function(from){
        if (!this.isAppliedTo(from)) throw "Unapply of property [" + this.name + "] from [" + from + "] failed"
        
        delete from[this.name]
    },
    
    
    clone : function (name){
        return new this.constructor(name || this.name, this.props)
    }
    
    
}).c;
Joose.Managed.Property.ConflictMarker = new Joose.Proto.Class('Joose.Managed.Property.ConflictMarker', {
    
	isa : Joose.Managed.Property,

    apply : function(target){
        throw "Attempt to apply ConflictMarker [" + this.name + "] to [" + target + "]"
    },
    
    
    unapply : function(from){
        throw "Attempt to unapply ConflictMarker [" + this.name + "] from [" + from + "]"
    }
    
}).c;
Joose.Managed.Property.Requirement = new Joose.Proto.Class('Joose.Managed.Property.Requirement', {
    
	isa : Joose.Managed.Property,

    apply : function(target){
        if (!target.meta.hasMethod(this.name)) throw "Requirement [" + this.name + "], defined in [" + this.definedIn.definedIn.name + "] is not satisfied for class [" + target + "]"
    },
    
    
    unapply : function(from){
    }
    
}).c;
Joose.Managed.Property.Attribute = new Joose.Proto.Class('Joose.Managed.Property.Attribute', {
    
	isa : Joose.Managed.Property,
    
    apply : function(target){
        Joose.Managed.Property.Attribute.superClass.apply.call(this, target.prototype)
    },
    
    
    unapply : function(from){
    	Joose.Managed.Property.Attribute.superClass.unapply.call(this, from.prototype)
    }
    
}).c;
Joose.Managed.Property.MethodModifier = new Joose.Proto.Class('Joose.Managed.Property.MethodModifier', {
    
	isa : Joose.Managed.Property,

    
    prepareWrapper : function(name, target, modifier, original, isOwn, superProto){
        throw "Abstract method [prepareWrapper] of " + this + " was called"
    },
    

    apply : function(target){
        var name = this.name
        var targetProto = target.prototype
        var isOwn = targetProto.hasOwnProperty(name)
        var original = targetProto[name]
        var superProto = target.meta.superClass.prototype
        var isCallToProto = superProto.meta.constructor == Joose.Proto.Class || superProto.meta.constructor == Joose.Proto.Object
        
        //original call (usual and array-variant)
        var originalCall, originalArgCall
        
        if (isOwn) { 
        	originalCall = function() {  return original.apply(this, arguments); }
        	originalArgCall = function() { return original.apply(this, arguments[0]); }
        } else if (isCallToProto) {
        	originalCall = function() {
        		var beforeSUPER = this.SUPER
        		var beforeSUPERARG = this.SUPERARG
        		
        		this.SUPER = superProto.SUPER
        		this.SUPERARG = superProto.SUPERARG
        		
	        	var res = superProto[name].apply(this, arguments)
	        	
	        	this.SUPER = beforeSUPER
	        	this.SUPERARG = beforeSUPERARG
	        	
	        	return res
	        }
	        
        	originalArgCall = function() {
        		var beforeSUPER = this.SUPER
        		var beforeSUPERARG = this.SUPERARG
        		
        		this.SUPER = superProto.SUPER
        		this.SUPERARG = superProto.SUPERARG
        		
	        	var res = superProto[name].apply(this, arguments[0])
	        	
	        	this.SUPER = beforeSUPER
	        	this.SUPERARG = beforeSUPERARG
	        	
	        	return res
	        }
        } else {
        	originalCall = function() { return superProto[name].apply(this, arguments); }
        	originalArgCall = function() { return superProto[name].apply(this, arguments[0]); }
        }
        
        var methodWrapper = this.prepareWrapper(name, this.value, originalCall, originalArgCall, superProto)
        
        if (isOwn) methodWrapper._original = original
        methodWrapper._contain = this.value
        
        targetProto[name] = methodWrapper
    },
    
    
    isAppliedTo : function(target) {
    	var targetCont = target.prototype[this.name]
    	
        return targetCont && targetCont._contain == this.value
    },
    
    
    unapply : function(from){
        var name = this.name
        var fromProto = from.prototype
        var original = fromProto[name]._original
        
        if (!this.isAppliedTo(from)) throw "Unapply of method [" + name + "] from class [" + from + "] failed"
        
        //if modifier was applied to own method - restore it
        if (original) 
        	fromProto[name] = original
        //otherwise - just delete it, to reveal the inherited method 
        else
            delete fromProto[name]
    }
    
}).c;
Joose.Managed.Property.MethodModifier.Override = new Joose.Proto.Class('Joose.Managed.Property.MethodModifier.Override', {
    
	isa : Joose.Managed.Property.MethodModifier,

    
    prepareWrapper : function(name, modifier, originalCall, originalArgCall, superProto) {
        
        var OVERRIDE = function (){
    		var beforeSUPER = this.SUPER
    		var beforeSUPERARG = this.SUPERARG
            
            this.SUPER  = originalCall
            this.SUPERARG = originalArgCall
            
            var res = modifier.apply(this, arguments)
            
        	this.SUPER = beforeSUPER
        	this.SUPERARG = beforeSUPERARG
            
            return res
        }
        
        OVERRIDE.methodName = name
        OVERRIDE.SUPER = superProto
        
        return OVERRIDE
    }
    
    
}).c;
Joose.Managed.Property.MethodModifier.Put = new Joose.Proto.Class('Joose.Managed.Property.MethodModifier.Put', {
    
	isa : Joose.Managed.Property.MethodModifier.Override,


    prepareWrapper : function(name, modifier, originalCall, originalArgCall, superProto) {
    	
//        if (isOwn) throw "Method [" + name + "] is applying over something [" + original + "] in class [" + target + "]"; 
        
        return Joose.Managed.Property.MethodModifier.Put.superClass.prepareWrapper.apply(this, arguments)
    }
    
    
}).c;
Joose.Managed.Property.MethodModifier.After = new Joose.Proto.Class('Joose.Managed.Property.MethodModifier.After', {
    
	isa : Joose.Managed.Property.MethodModifier,

    
    prepareWrapper : function(name, modifier, originalCall, originalArgCall, superProto) {
        
        var AFTER = function () {
            var res = originalCall.apply(this, arguments)
            modifier.apply(this, arguments)
            return res
        }
        
        return AFTER
    }    

    
}).c;
Joose.Managed.Property.MethodModifier.Before = new Joose.Proto.Class('Joose.Managed.Property.MethodModifier.Before', {
    
	isa : Joose.Managed.Property.MethodModifier,

    prepareWrapper : function(name, modifier, originalCall, originalArgCall, superProto) {
    	
        var BEFORE = function () {
            modifier.apply(this, arguments)
            return originalCall.apply(this, arguments)
        }
        
        return BEFORE
    }
    
}).c;
Joose.Managed.Property.MethodModifier.Around = new Joose.Proto.Class('Joose.Managed.Property.MethodModifier.Around', {
    
	isa : Joose.Managed.Property.MethodModifier,

    prepareWrapper : function(name, modifier, originalCall, originalArgCall, superProto) {
        
        var AROUND = function (){
            var me = this
            var bound = function () {
                return originalCall.apply(me, arguments)
            }
            
            return modifier.apply(this, Joose.A.concat([bound], arguments))
        }
        
        AROUND.AROUND = true
        
        return AROUND
    }
    
}).c;
Joose.Managed.Property.MethodModifier.Augment = new Joose.Proto.Class('Joose.Managed.Property.MethodModifier.Augment', {
    
	isa : Joose.Managed.Property.MethodModifier,

    prepareWrapper : function(name, modifier, originalCall, originalArgCall, superProto) {
    	
        var AUGMENT = function () {
            var callstack = []
            
            var self = AUGMENT
            
            do {
                callstack.push(self.OUTER ? self._contain : self)
                
                self = self.OUTER && (self._original || self.OUTER[self.methodName])
            } while (self)
            
            
            var augmentWrapper = function(){
                return callstack.pop().apply(this, arguments)
            }
            
            augmentWrapper.__INNER_STACK__ = callstack
            
            return augmentWrapper.apply(this, arguments)
        }
        
        AUGMENT.methodName = name
        AUGMENT.OUTER = superProto
        
        return AUGMENT
    }
    
}).c;
Joose.Managed.PropertySet = new Joose.Proto.Class('Joose.Managed.PropertySet', {
    
	isa                       : Joose.Managed.Property,

    properties                : null,
    
    propertyMetaClass         : Joose.Managed.Property,
    
    
    initialize : function(name, props) {
        props = props || {}
        
        Joose.Managed.PropertySet.superClass.initialize.call(this, name, props)
        
        this.properties = props.properties || {}
    },
    
    
    addProperty : function (name, props) {
        props.definedIn = this
        return this.properties[name] = new (props.meta || this.propertyMetaClass)(name, props)
    },
    
    
    addPropertyObject : function (object) {
        return this.properties[object.name] = object
    },
    
    
    removeProperty : function (name) {
        var prop = this.properties[name]
        
        //probably should be 
        //this.properties[name] = undefined
        delete this.properties[name]
        
        return prop
    },
    
    
    haveProperty : function(name) {
        return typeof this.properties[name] != 'undefined'
    },
    

    haveOwnProperty : function(name) {
        return this.haveProperty(name)
    },
    
    
    getProperty : function(name) {
        return this.properties[name]
    },
    
    
    each : function (func, scope){
        Joose.O.each(this.properties, function(property, name){
            if (typeof property != 'undefined') func.call(scope || this, property, name)
        })
    },
    
    
    clone : function (name){
        var propsCopy = Joose.O.copy(this.props, {})
        propsCopy.properties = Joose.O.getMutableCopy(this.properties)
        
        return new this.constructor(name || this.name, propsCopy); 
    },
    
    
    cleanClone : function (name){
    	//XXX benchmark both variants
        var propsCopy = Joose.O.copy(this.props, {})
//        var propsCopy = Joose.O.getMutableCopy(this.props)
        propsCopy.properties = {}
        
        return new this.constructor(name || this.name, propsCopy); 
    },
    
    
    alias : function (what){
    	var props = this.properties
    	
        Joose.O.each(what, function(aliasName, originalName){
            var original = props[originalName]
            
            if (original) this.addPropertyObject(original.clone(aliasName))
        }, this)
    },
    
    
    exclude : function (what){
        Joose.A.each(what, function(name){
            //not just "delete" to implicitly override possible inherited via getMutableCopy property
            if (this.properties[name]) this.properties[name] = undefined
        }, this)
    },
    
    
    flattenTo : function (target){
    	var targetProps = target.properties
    	
        this.each(function(property, name){
            var targetProperty = targetProps[name]
            
            if (targetProperty instanceof Joose.Managed.Property.ConflictMarker) return
            
            if (typeof targetProperty == 'undefined') {
                target.addPropertyObject(property)
                return
            }
            
            if (targetProperty == property) return
            
            target.removeProperty(name)
            target.addProperty(name, {
                meta : Joose.Managed.Property.ConflictMarker
            })
        }, this)
    },
    
    
    composeTo : function(target){
        this.each(function(property, name){
        	if (!target.haveOwnProperty(name)) target.addPropertyObject(property)
        })
    },
    
    
    composeFrom : function() {
    	if (!arguments.length) return
    	
        var flattening = this.cleanClone()
        
        Joose.A.each(arguments, function(arg) {
            var propSet = arg
            
            if (!(arg instanceof Joose.Managed.PropertySet)) {
                propSet = arg.propertySet
                
                if (arg.alias || arg.exclude) propSet = propSet.clone(); 
                
                if (arg.alias) propSet.alias(arg.alias)
                if (arg.exclude) propSet.exclude(arg.exclude)
            }
            
            propSet.flattenTo(flattening)
        })
        
        flattening.composeTo(this)
    },
    
    
    prepareApply : function(target){
        this.each(function(property){
            property.prepareApply(target)
        })
    },
    
    
    apply : function(target){
        this.each(function(property){
            property.apply(target)
        })
    },
    
    
    unapply : function(from){
        this.each(function(property){
            property.unapply(from)
        })
    }
    
    
}).c
;
(function(){
    
    var __ID__ = 1
    

    Joose.Managed.PropertySet.Mutable = new Joose.Proto.Class('Joose.Managed.PropertySet.Mutable', {
        
        isa                 : Joose.Managed.PropertySet,
    
        ID                  : null,
        
        derivatives         : null,
        
        //initially opened
        opened              : 1,
        
        composedFrom        : null,
        
        
        initialize : function(name, props) {
            Joose.Managed.PropertySet.Mutable.superClass.initialize.call(this, name, props)
            
            this.derivatives  = {}
            this.ID           = __ID__++
            this.composedFrom = []
        },
        
        
        setComposeInfo : function(){
            this.ensureOpen()
            
            Joose.A.each(this.composedFrom, function(arg) {
                var propSet = arg instanceof Joose.Managed.PropertySet ? arg : arg.propertySet
                    
                delete propSet.derivatives[this.ID]
            }, this)
            
            this.composedFrom = []
            
            this.addComposeInfo.apply(this, arguments)
        },
        
        
        addComposeInfo : function(){
            this.ensureOpen()
            
            Joose.A.each(arguments, function(arg) {
                this.composedFrom.push(arg)
                
                var propSet = arg instanceof Joose.Managed.PropertySet ? arg : arg.propertySet
                    
                propSet.derivatives[this.ID] = this
            }, this)
        },
        
        
        removeComposeInfo : function(){
            this.ensureOpen()
            
            Joose.A.each(arguments, function(arg) {
                
                var i = 0
                
                while (i < this.composedFrom.length) {
                    var propSet = this.composedFrom[i]
                    propSet = propSet instanceof Joose.Managed.PropertySet ? propSet : propSet.propertySet
                    
                    if (arg == propSet) {
                        delete propSet.derivatives[this.ID]
                        this.composedFrom.splice(i, 1)
                    } else i++
                }
                
            }, this)
        },
        
        
        ensureOpen : function(){
            if (!this.opened) throw "Mutation of closed property set: [" + this.name + "]"
        },
        
        
        addProperty : function (name, props) {
            this.ensureOpen()
            
            return Joose.Managed.PropertySet.Mutable.superClass.addProperty.call(this, name, props)
        },
        
    
        addPropertyObject : function (object) {
            this.ensureOpen()
            
            return Joose.Managed.PropertySet.Mutable.superClass.addPropertyObject.call(this, object)
        },
        
        
        removeProperty : function (name) {
            this.ensureOpen()
            
            return Joose.Managed.PropertySet.Mutable.superClass.removeProperty.call(this, name)
        },
        
        
        composeFrom : function() {
            this.ensureOpen()
            
            return Joose.Managed.PropertySet.Mutable.superClass.composeFrom.apply(this, this.composedFrom)
        },
        
        
        open : function(){
            this.opened++
            
            if (this.opened == 1) {
            
                Joose.O.each(this.derivatives, function(propSet){
                    propSet.open()
                })
                
                this.deCompose()
            }
        },
        
        
        close : function(){
            if (!this.opened) throw "Unmatched 'close' operation on property set: [" + this.name + "]"
            
            if (this.opened == 1) {
                this.reCompose()
                
                Joose.O.each(this.derivatives, function(propSet){
                    propSet.close()
                })
            }
            this.opened--
        },
        
        
        reCompose : function(){
            this.composeFrom()
        },
        
        
        deCompose : function(){
            this.each(function(property, name){
                if (property.definedIn != this) this.removeProperty(name)
            }, this)
        }
        
    }).c
    
    
})()

;
Joose.Managed.PropertySet.Containable = new Joose.Proto.Class('Joose.Managed.PropertySet.Containable', {
    
	isa                     : Joose.Managed.PropertySet.Mutable,

    //points to class
    targetMeta             : null,
    
    container               : null,

    
    initialize : function(name, props) {
        Joose.Managed.PropertySet.Containable.superClass.initialize.call(this, name, props)
        
        this.targetMeta        = props.targetMeta
        
        this.computeContainer()
    },
    
    
    computeContainer : function(){
        throw "Abstract method [computeContainer] of " + this + " was called"
    },
    
    
    addProperty : function (name, props) {
        return this.container[name] = Joose.Managed.PropertySet.Containable.superClass.addProperty.call(this, name, props)
    },
    

    addPropertyObject : function (object) {
        return this.container[object.name] = Joose.Managed.PropertySet.Containable.superClass.addPropertyObject.call(this, object)
    },
    

    removeProperty : function (name) {
        try {
            delete this.container[name]
        } catch(e) {
            this.container[name] = undefined
        }
        
        return Joose.Managed.PropertySet.Containable.superClass.removeProperty.call(this, name)
    },
    
    
    haveProperty : function(name) {
        return typeof this.container[name] != 'undefined'
    },
    
    
    haveOwnProperty : function(name) {
        return this.haveProperty(name) && this.container.hasOwnProperty(name)
    },
    
    
    getProperty : function(name) {
        return this.container[name]
    },
    
    
    cleanClone : function (name){
        var clon = Joose.Managed.PropertySet.Containable.superClass.cleanClone.call(this, name)
        clon.container = {}
        
        return clon; 
    }
    
    
}).c
;
Joose.Managed.StemElement = function(){ throw "Modules may not be instantiated." }

Joose.Managed.StemElement.Attributes = new Joose.Proto.Class('Joose.Managed.StemElement.Attributes', {
    
	isa : Joose.Managed.PropertySet.Containable,
    
    propertyMetaClass : Joose.Managed.Property.Attribute,
    
    
    computeContainer : function(props){
        this.container = this.targetMeta.attributes
    }
    
}).c
;
Joose.Managed.StemElement.Methods = new Joose.Proto.Class('Joose.Managed.StemElement.Methods', {
    
	isa : Joose.Managed.PropertySet.Containable,
    
    propertyMetaClass : Joose.Managed.Property.MethodModifier.Put,
    
    
    computeContainer : function(props){
        this.container = this.targetMeta.methods
    },
    
    
    prepareApply : function(){
    }
    
}).c;
Joose.Managed.StemElement.Requirements = new Joose.Proto.Class('Joose.Managed.StemElement.Requirements', {

	isa : Joose.Managed.PropertySet.Mutable,
    
    targetMeta             : null,
    
    propertyMetaClass : Joose.Managed.Property.Requirement,
    
    
    initialize : function(name, props) {
        Joose.Managed.StemElement.Requirements.superClass.initialize.call(this, name, props)
        
        this.targetMeta        = props.targetMeta
    },
    
    
    alias : function (){
    },
    
    
    exclude : function (){
    },
    
    
    flattenTo : function (target){
        this.each(function(property, name){
            if (!target.haveProperty(name)) target.addPropertyObject(property)
        }, this)
    },
    
    
    composeTo : function(target){
        this.flattenTo(target)
    },
    
    
    prepareApply : function(target){
    }
    
}).c;
Joose.Managed.StemElement.MethodModifiers = new Joose.Proto.Class('Joose.Managed.StemElement.MethodModifiers', {

	isa : Joose.Managed.PropertySet.Mutable,
	
	targetMeta             : null,
    
    propertyMetaClass : null,
    
    
    initialize : function(name, props) {
        Joose.Managed.StemElement.MethodModifiers.superClass.initialize.call(this, name, props)
        
        this.targetMeta        = props.targetMeta
    },
    
    
    addProperty : function (name, props) {
        props.definedIn         = this
        var modifier = new props.meta(name, props)
        
        if (!this.properties[name]) this.properties[name] = []
        this.properties[name].push(modifier)
        
        return modifier
    },
    

    addPropertyObject : function (object) {
        var name = object.name
        
        if (!this.properties[name]) this.properties[name] = []
        
        this.properties[name].push(object)
        
        return object
    },
    
    
    //remove only the last modifier
    removeProperty : function (name) {
        if (!this.haveProperty(name)) return undefined
        
        var modifier = this.properties[name].pop()
        
        //if all modifiers were removed - clearing the properties
        if (!this.properties[name].length) Joose.Managed.StemElement.MethodModifiers.superClass.removeProperty.call(this, name)
        
        return modifier
    },
    
    
    alias : function (){
    },
    
    
    exclude : function (){
    },
    
    
    flattenTo : function (target){
    	var targetProps = target.properties
    	
        this.each(function(modifiersArr, name){
            var targetModifiersArr = targetProps[name]
            
            if (typeof targetModifiersArr == 'undefined') targetModifiersArr = targetProps[name] = []
            
            Joose.A.each(modifiersArr, function(modifier) {
                if (!Joose.A.exists(targetModifiersArr, modifier)) targetModifiersArr.push(modifier)
            })
            
        }, this)
        
        return this
    },
    
    
    composeTo : function(target){
        this.flattenTo(target)
        
        return this
    },

    
    deCompose : function(){
        this.each(function(modifiersArr, name){
            var i = 0; 
            
            while (i < modifiersArr.length) if (modifiersArr[i].definedIn != this) modifiersArr.splice(i,1); else i++
            
        }, this)
    },
	
    
    prepareApply : function(target){
//        this.each(function(modifiersArr, name){
//            Joose.A.each(modifiersArr, function(modifier) {
//                modifier.prepareApply(target)
//            })
//        }, this)
    },

    
    apply : function(target){
        this.each(function(modifiersArr, name){
            Joose.A.each(modifiersArr, function(modifier) {
                modifier.apply(target)
            })
        }, this)
    },
    
    
    unapply : function(from){
        this.each(function(modifiersArr, name){
            for (var i = modifiersArr.length - 1; i >=0; i--) {
                modifiersArr[i].unapply(from)
            }
        }, this)
    }
    
    
    
}).c;
Joose.Managed.PropertySet.Composition = new Joose.Proto.Class('Joose.Managed.PropertySet.Composition', {
    
    isa                         : Joose.Managed.PropertySet.Mutable,
    
    propertyMetaClass           : Joose.Managed.PropertySet.Mutable,
    
    processOrder                : null,

    
    each : function (func, scope) {
    	var props = this.properties
    	
        Joose.A.each(this.processOrder, function(name){
            func.call(scope || this, props[name], name)
        }, this)
    },
    
    
    eachR : function (func, scope) {
    	var props = this.properties
    	
        for(var i = this.processOrder.length - 1; i >= 0; i--) 
            func.call(scope || this, props[this.processOrder[i]], this.processOrder[i])
    },
    
    
    clone : function (){
        var clone = this.cleanClone()
        
        this.each(function(property){
            clone.addPropertyObject(property.clone())
        })
        
        return clone
    },
    
    
    alias : function (what){
        this.each(function(property){
            property.alias(what)
        })
    },
    
    
    exclude : function (what){
        this.each(function(property){
            property.exclude(what)
        })
    },
    
    
    flattenTo : function (target){
    	var targetProps = target.properties
    	
        this.each(function(property, name){
            var subTarget = targetProps[name] || target.addProperty(name, {
                meta : property.constructor
            })
            
            property.flattenTo(subTarget)
        })
    },
    
    
    composeTo : function(target) {
    	var targetProps = target.properties
    	
        this.each(function(property, name){
            var subTarget = targetProps[name] || target.addProperty(name, {
                meta : property.constructor
            })
            
            property.composeTo(subTarget)
        })
    },
    
    
    
    deCompose : function() {
        this.eachR(function(property) {
            property.open()
        })
        
        Joose.Managed.PropertySet.Composition.superClass.deCompose.call(this)
    },
    
    
    reCompose : function() {
        Joose.Managed.PropertySet.Composition.superClass.reCompose.call(this)
        
        this.each(function(property) {
            property.close()
        })
    },
    
    
    unapply : function(from){
        this.eachR(function(property){
            property.unapply(from)
        })
    }
    
    
    
}).c
;
Joose.Managed.Stem = new Joose.Proto.Class('Joose.Managed.Stem', {
    
	isa                  : Joose.Managed.PropertySet.Composition,
    
    targetMeta          : null,
    
    attributesMC         : Joose.Managed.StemElement.Attributes,
    methodsMC            : Joose.Managed.StemElement.Methods,
    requirementsMC       : Joose.Managed.StemElement.Requirements,
    methodsModifiersMC   : Joose.Managed.StemElement.MethodModifiers,
    
    processOrder         : [ 'attributes', 'methods', 'requirements', 'methodsModifiers'],
    
    
    initialize : function(name, props) {
        var targetMeta = this.targetMeta = props.targetMeta
        
        Joose.Managed.Stem.superClass.initialize.call(this, name, props)
        
        this.addProperty('attributes', {
            meta : this.attributesMC,
            targetMeta : targetMeta
        })
        
        this.addProperty('methods', {
            meta : this.methodsMC,
            targetMeta : targetMeta
        })
        
        this.addProperty('requirements', {
            meta : this.requirementsMC,
            targetMeta : targetMeta
        })
        
        this.addProperty('methodsModifiers', {
            meta : this.methodsModifiersMC,
            targetMeta : targetMeta
        })
    },
    
    
    cleanClone : function (name){
        var emptyClass = new this.meta.constructor(null, {
            isa : Joose.Proto.Empty
        }).c
        
        return new this.constructor(name || this.name, {
            targetMeta : emptyClass.meta
        }); 
    },
    
    
    reCompose : function(){
        this.prepareApply(this.targetMeta.c)
        
        Joose.Managed.Stem.superClass.reCompose.call(this)
        
        this.apply(this.targetMeta.c)
    },
    
    
    deCompose : function(){
        this.unapply(this.targetMeta.c)
        
        Joose.Managed.Stem.superClass.deCompose.call(this)
    }
    
    
}).c
;
Joose.Managed.Builder = new Joose.Proto.Class('Joose.Managed.Builder', {
	
    //points to class
    targetMeta : null,
    
    initialize : function(props) {
        this.targetMeta = props.targetMeta
    },
    
    
    _buildStart : function(targetClassMeta, props){
        targetClassMeta.stem.open()
    },
    
    
    _extend : function(props) {
        var targetMeta = this.targetMeta
        
        this._buildStart(targetMeta, props)
        
        Joose.O.eachSafe(props, function(value, name) {
            var handler = this[name]
            
            if (!handler) throw "Unknow builder [" + name + "] was used during extending of [" + targetMeta.c + "]"
            
            handler.call(this, targetMeta, value)
        }, this)
        
        this._buildComplete(targetMeta, props)
    },
    

    _buildComplete : function(targetClassMeta, props){
        targetClassMeta.stem.close()
    },
    
    
    methods : function(targetClassMeta, info) {
        Joose.O.eachSafe(info, function(value, name) {
            targetClassMeta.addMethod(name, value)
        }, this)
    },
    

    removeMethods : function(targetClassMeta, info) {
        Joose.A.each(info, function(name) {
            targetClassMeta.removeMethod(name)
        }, this)
    },
    
    
    have : function(targetClassMeta, info) {
        Joose.O.eachSafe(info, function(value, name) {
            targetClassMeta.addAttribute(name, value)
        }, this)
    },
    
    
    havenot : function(targetClassMeta, info) {
        Joose.A.each(info, function(name) {
            targetClassMeta.removeAttribute(name)
        }, this)
    },
    

    havent : function(targetClassMeta, info) {
        this.havenot(targetClassMeta, info)
    },
    
    
    after : function(targetClassMeta, info) {
        Joose.O.each(info, function(value, name) {
            targetClassMeta.addMethodModifier(name, value, Joose.Managed.Property.MethodModifier.After)
        }, this)
    },
    
    
    before : function(targetClassMeta, info) {
        Joose.O.each(info, function(value, name) {
            targetClassMeta.addMethodModifier(name, value, Joose.Managed.Property.MethodModifier.Before)
        }, this)
    },
    
    
    override : function(targetClassMeta, info) {
        Joose.O.each(info, function(value, name) {
            targetClassMeta.addMethodModifier(name, value, Joose.Managed.Property.MethodModifier.Override)
        }, this)
    },
    
    
    around : function(targetClassMeta, info) {
        Joose.O.each(info, function(value, name) {
            targetClassMeta.addMethodModifier(name, value, Joose.Managed.Property.MethodModifier.Around)
        }, this)
    },
    
    
    augment : function(targetClassMeta, info) {
        Joose.O.each(info, function(value, name) {
            targetClassMeta.addMethodModifier(name, value, Joose.Managed.Property.MethodModifier.Augment)
        }, this)
    },
    
    
    removeModifier : function(targetClassMeta, info) {
        Joose.A.each(info, function(name) {
            targetClassMeta.removeMethodModifier(name)
        }, this)
    },
    
    
    does : function(targetClassMeta, info) {
        Joose.A.each(info, function(desc) {
            targetClassMeta.addRole(desc)
        }, this)
    },
    

    doesnot : function(targetClassMeta, info) {
        Joose.A.each(info, function(desc) {
            targetClassMeta.removeRole(desc)
        }, this)
    },
    
    
    doesnt : function(targetClassMeta, info) {
        this.doesnot(targetClassMeta, info)
    }
    
    
}).c;
Joose.Managed.Class = new Joose.Proto.Class('Joose.Managed.Class', {
    
    isa                         : Joose.Proto.Class,
    
    stem                        : null,
    stemClass                   : Joose.Managed.Stem,
    
    builder                     : null,
    builderClass                : Joose.Managed.Builder,
    
    
    construct: function (extend) {
        Joose.Managed.Class.superClass.construct.call(this, extend)
        
        this.stem.close()
    },
    
    
    processStem : function(){
        Joose.Managed.Class.superClass.processStem.call(this)
        
        this.builder    = new this.builderClass({ targetMeta : this })
        this.stem       = new this.stemClass(this.name, { targetMeta : this })
        
        var builderClass = this.getAttributedClass('builderClass')
        if (builderClass) this.addAttribute('builderClass', this.subClassOf(builderClass))
        
        var stemClass = this.getAttributedClass('stemClass')
        if (stemClass) this.addAttribute('stemClass', this.subClassOf(stemClass))
    },
    
    
    extend : function (props) {
        if (props.builder) {
        	this.getBuilderTarget().meta.extend(props.builder)
            delete props.builder
        }
        
        if (props.stem) {
        	this.getStemTarget().meta.extend(props.stem)
            delete props.stem
        }
        
        this.builder._extend(props)
    },
    
    
    getBuilderTarget : function(){
    	var builderClass = this.getAttributedClass('builderClass')
    	if (!builderClass) throw "Attempt to extend a builder on non-meta class"
    	
    	return builderClass
    },
    

    getStemTarget : function(){
    	var stemClass = this.getAttributedClass('stemClass')
    	if (!stemClass) throw "Attempt to extend a stem on non-meta class"
    	
    	return stemClass
    },
    
    
    getAttributedClass : function(attributeName) {
    	var attrClass = this.getAttribute(attributeName)
    	if (attrClass instanceof Joose.Managed.Property.Attribute) attrClass = attrClass.value
    	
    	return attrClass
    },
    
    
    addMethodModifier: function (name, func, type) {
        var props = {}
        props.init = func
        props.meta = type
        
        return this.stem.properties.methodsModifiers.addProperty(name, props)
    },
    
    
    removeMethodModifier: function (name) {
        return this.stem.properties.methodsModifiers.removeProperty(name)
    },
    
    
    addMethod: function (name, func, props) {
        props = props || {}
        props.init = func
        
        return this.stem.properties.methods.addProperty(name, props)
    },
    
    
    addAttribute: function (name, init, props) {
        props = props || {}
        props.init = init
        
        return this.stem.properties.attributes.addProperty(name, props)
    },
    
    
    removeMethod : function (name){
        return this.stem.properties.methods.removeProperty(name)
    },

    
    removeAttribute: function (name) {
        return this.stem.properties.attributes.removeProperty(name)
    },
    
    
    hasMethod: function (name) {
        return this.stem.properties.methods.haveProperty(name)
    },
    
    
    hasAttribute: function (name) { 
        return this.stem.properties.attributes.haveProperty(name)
    },
    
    
    hasOwnMethod: function (name) {
        return this.stem.properties.methods.haveOwnProperty(name)
    },
    
    
    hasOwnAttribute: function (name) { 
        return this.stem.properties.attributes.haveOwnProperty(name)
    },
    

    getMethod : function(name) {
        return this.stem.properties.methods.getProperty(name)
    },
    
    
    getAttribute : function(name) {
        return this.stem.properties.attributes.getProperty(name)
    },
    
    
    addRole : function(){
        Joose.A.each(arguments, function(arg) {
            var role = (arg.meta instanceof Joose.Managed.Class) ? arg : arg.role
            
            if (role.meta.builderRole) this.getBuilderTarget().meta.extend({
        		does : [ role.meta.builderRole ]
        	})
            
            if (role.meta.stemRole) this.getStemTarget().meta.extend({
        		does : [ role.meta.stemRole ]
        	})
            
            var desc = arg
            
            if (!(desc.meta instanceof Joose.Managed.Class)) {
                desc.propertySet = desc.role.meta.stem
                delete desc.role
            } else
                desc = desc.meta.stem
            
            this.stem.addComposeInfo(desc)
        }, this)
    },
    
    
    removeRole : function(){
        Joose.A.each(arguments, function(role) {
        	
            if (role.meta.builderRole) this.getBuilderTarget().meta.extend({
        		doesnt : [ role.meta.builderRole ]
        	})
            
            if (role.meta.stemRole) this.getStemTarget().meta.extend({
        		doesnt : [ role.meta.stemRole ]
        	})
        	
        	
            this.stem.removeComposeInfo(role.meta.stem)
        }, this)
    }
    
}).c;
Joose.Managed.Role = new Joose.Managed.Class('Joose.Managed.Role', {
    
    isa                         : Joose.Managed.Class,
    
    have : {
        defaultSuperClass       : Joose.Proto.Empty,
        
	    builderRole				: null,
	    stemRole				: null
    },
    
    
    methods : {
        
        defaultConstructor: function () {
            return function () {
                throw "Roles cant be instantiated"
            }
        },
        

        processSuperClass : function() {
            if (this.superClass != this.defaultSuperClass) throw "Roles cant inherit from anything"
        },
        
        
	    getBuilderTarget : function(){
	    	if (!this.builderRole) this.builderRole = new this.constructor().c
	    	
	    	return this.builderRole
	    },
	    
	
	    getStemTarget : function(){
	    	if (!this.stemRole) this.stemRole = new this.constructor().c
	    	
	    	return this.stemRole
	    },
        
    
        hasOwnMethod: function (name) { 
            return this.hasMethod(name)
        },
        
        
        hasOwnAttribute: function (name) { 
            return this.hasAttribute(name)
        },
        
    
        addRequirement : function(methodName){
            this.stem.properties.requirements.addProperty(methodName, {})
        }
        
    },
    

    stem : {
    	methods : {
	        prepareApply : function() {
	        },
	        
	        
	        apply : function(){
	        },
	        
	        
	        unapply : function(){
	        }
    	}
    },
    
    
    builder : {
    	methods : {
	        requires : function(targetClassMeta, info) {
	            Joose.A.each(info, function(methodName) {
	                targetClassMeta.addRequirement(methodName)
	            }, this)
	        }
    	}
    }
    
}).c;
Joose.Meta = function(){ throw "Modules may not be instantiated." }

Joose.Meta.Object = new Joose.Proto.Class('Joose.Meta.Object', {
	
	isa : Joose.Proto.Object,

	
    initialize: function (config) {
    	config = config || {}
    	
    	Joose.O.each(this.meta.attributes, function(value, name) {
    		
    		if (value instanceof Joose.Managed.Attribute) {
    			var setValue, isSet = false
    			
    			if (config.hasOwnProperty(name)) {
    				setValue = config[name]
    				isSet = true
    			} else if (typeof value.props.init == 'function') {
    				setValue = value.props.init.call(this, name, config)
    				isSet = true
    			}
    			
    			
    			if (isSet)
    				if (this.meta.hasMethod(value.setterName)) 
    					this[value.setterName].call(this, setValue)
    				else
    					this[name] = setValue
				else if (value.props.required) 
					throw "Required attribute [" + name + "] is missed during initialization of " + this
    			
    		} else if (config.hasOwnProperty(name)) this[name] = config[name]
    		
    		
    	}, this)
    }

}).c;
Joose.Meta.Class = new Joose.Managed.Class('Joose.Meta.Class', {
    
    isa                         : Joose.Managed.Class,
    
    have : {
    	defaultSuperClass : Joose.Meta.Object
    }
    
}).c;
Joose.Meta.Role = new Joose.Meta.Class('Joose.Meta.Role', {
    
    isa                         : Joose.Managed.Role,
    
    
    methods : {

	    //'to' must be instance 
        apply : function(to) {
        	if (!Joose.O.isInstance(to)) throw "Role can be applied only to Joose instance"
        	
        	if (!to.meta.hasMethod('detach')) throw "Apply failed: Instance [" + to + "] has no 'detach' method"
        	
        	to.detach()
        	
        	to.meta.extend({ does : [ this.c ] })
        },
        
        
        //instance remains detached
        unapply : function(from) {
        	if (!Joose.O.isInstance(from)) throw "Role can be unapplied only from Joose instance"
        	
        	if (!(from.meta instanceof Joose.Meta.Class.Detached)) throw "Instance [" + from + "] is not detached"
        	
        	from.meta.extend({ doesnt : [ this.c ] })
        }
        
    	
    }
    
}).c;
Joose.Meta.Class.Detached = new Joose.Meta.Class('Joose.Meta.Class.Detached', {
    
    isa                         : Joose.Meta.Class,
    
    have : {
    	originalClass : null
    },
    
    stem : {
    	
    	have : {
    		woAttributes         : [ 'methods', 'requirements', 'methodsModifiers']
    	},
    	
    	override : { 
    		
	        prepareApply : function(target) {
	        	this.processOrder = this.woAttributes
	        	
	        	this.SUPER(target)
	        	
	        	delete this.processOrder
	        },
	        
	        
	        apply : function(target){
	        	this.processOrder = this.woAttributes
	        	
	        	this.SUPER(target)
	        	
	        	delete this.processOrder
	        },
	        
	        
	        unapply : function(target){
	        	this.processOrder = this.woAttributes
	        	
	        	this.SUPER(target)
	        	
	        	delete this.processOrder
	        }
    	}
    	
    }
    
}).c;
Joose.Managed.Attribute = new Joose.Managed.Class('Joose.Managed.Attribute', {
	
	isa : Joose.Managed.Property.Attribute,
	
	have : {
		role : null,
		
		publicName : null,
		setterName : null,
		getterName : null
	},
	
	override : {
		
		computeValue : function(props) {
			if (typeof props.init != 'function') this.SUPER(props)
			
			this.publicName = this.name.replace(/^_+/, '')
			this.setterName = 'set' + Joose.S.uppercaseFirst(this.publicName)
			this.getterName = 'get' + Joose.S.uppercaseFirst(this.publicName)
			
			if (props.is) {
				var methods = {}
				
				if (props.is == 'rw') methods[this.setterName] = this.getSetter()
				if (props.is == 'rw' || props.is == 'ro') methods[this.getterName] = this.getGetter()
				
				this.role = new Joose.Managed.Role('attribute:' + this.name, { methods : methods }).c
			}
		},

		
	    prepareApply : function(targetClass) {
	    	if (this.role) targetClass.meta.extend({
	    		does : [ this.role ]
	    	})
	    },
		
	    
	    apply : function(target) {
	    	this.SUPER(target)
	    },
	    
	    
	    unapply : function(from) {
	    	if (this.role) from.meta.extend({
	    		doesnt : [ this.role ]
	    	})
	    	this.SUPER(from)
	    }
		
	},
	
	
	methods : {
		
		isPrivate : function() {
			return /^_/.test(this.name)
		},
		
		
		getSetter : function() {
			var name = this.name
			
			return function(value) {
				this[name] = value
				return this
			}
		},
		
		
		getGetter : function() {
			var name = this.name
			
			return function() {
				return this[name]
			}
			
		}
		
	}

}).c











///*
// * This handles the following attribute properties
// *  * init with function value in non-lazy initialization
// *  * required attributes in initializaion
// *  * handles for auto-decoration
// *  * predicate for attribute availability checks
// * 
// * 
// * See http://code.google.com/p/joose-js/wiki/JooseAttribute
// */
//Joose.Kernel.MetaClass.create('Joose.Managed.Attribute', {    
//    isa: Joose.Kernel.ProtoAttribute,
//    
//    before: {
//        handleProps: function(classObject){
//            this.handleIs(classObject)
//        }
//    },
//    
//    after: {
//        handleProps: function(classObject){
//            this.handlePredicate(classObject)
//            this.handleHandles(classObject)
//        }
//    },
//    
//    
//    methods: {
//        
////        isPrivate: function () {
////            return this.getName().charAt(0) == "_"
////        },
////        
////        
////        toPublicName: function () {
////            
////            if(this.__publicNameCache) { // Cache the publicName (very busy function)
////                return this.__publicNameCache
////            }
////            
////            var name = this.getName()
////            if(this.isPrivate()) {
////                this.__publicNameCache = name.substr(1)
////                return this.__publicNameCache
////            }
////            this.__publicNameCache = name
////            return this.__publicNameCache
////        },
//        
//        
//        getIsa: function () {
//            var props = this.getProps()
//            if("isa" in props && props.isa == null) {
//                throw new Error("You declared an isa property but the property is null.")
//            }
//            if(props.isa) {
//                if(!props.isa.meta) {
//                    return props.isa()
//                }
//                return props.isa
//            }
//            return
//        },
//        
//        
//        addSetter: function (classObject) {
//            var meta  = classObject.meta
//            var name  = this.getName()
//            var props = this.getProps()
//            
//            var setterName = this.setterName()
//            
//            if(meta.can(setterName)) { // do not override methods
//                return
//            }
//            
//            var isa   = this.getIsa()
//    
//            var func = this.makeTypeChecker(isa, props, "attribute", name)
//            
//            meta.addMethod(setterName, func)
//        },
//        
//        
//        addGetter: function (classObject) {
//            var meta  = classObject.meta
//            var name  = this.getName()
//            var props = this.getProps()
//            
//            var getterName = this.getterName()
//            
//            if(meta.can(getterName)) { // never override a method
//                return 
//            }
//            
//            var func  = function getter () {
//                return this[name]
//            }
//            
//            var init  = props.init
//            
//            if(props.lazy) {
//                func = function lazyGetter () {
//                    var val = this[name]
//                    if(typeof val == "function" && val === init) {
//                        this[name] = val.apply(this)
//                    }
//                    return this[name]
//                }
//            }
//            
//            meta.addMethod(getterName, func)
//        },
//        
//        
//        initializerName: function () {
//            return this.toPublicName()
//        },
//        
//        
////        getterName: function () {
////            if(this.__getterNameCache) { // Cache the getterName (very busy function)
////                return this.__getterNameCache
////            }
////            this.__getterNameCache = "get"+Joose.S.uppercaseFirst(this.toPublicName())
////            return this.__getterNameCache
////        },
////        
////        
////        setterName: function () {
////            if(this.__setterNameCache) { // Cache the setterName (very busy function)
////                return this.__setterNameCache
////            }
////            this.__setterNameCache = "set"+Joose.S.uppercaseFirst(this.toPublicName())
////            return this.__setterNameCache
////        },
//        
//        
////        handleIs: function (classObject) {
////    //        var name  = this.getName()
////            var props = this.getProps()
////            
////            var is    = props.is
////    
////            if(is == "rw" || is == "ro") {
////                this.addGetter(classObject)
////            }
////            if(is == "rw") {
////                this.addSetter(classObject)
////            }
////        },
//        
//        
//        doInitialization: function (object, paras) {
//            var  name  = this.initializerName()
//            var _name  = this.getName()
//            var value
//            var isSet  = false
//            if(typeof paras != "undefined" && typeof paras[name] != "undefined") {
//                value  = paras[name]
//                isSet  = true
//            } else {
//                var props = this.getProps()
//                
//                var init  = props.init
//                
//                if(typeof init == "function" && !props.lazy) {
//                    // if init is not a function, we have put it in the prototype, so it is already here
//                    value = init.call(object)
//                    isSet = true
//                } else {
//                    // only enforce required property if init is not run
//                    if(props.required) {
//                        throw "Required initialization parameter missing: "+name + "(While initializing "+object+")"
//                    }
//                }
//            }
//            if(isSet) {
//                var setterName = this.setterName()
//                if(object.meta.can(setterName)) { // use setter if available
//                    object[setterName](value)
//                } else { // direct attribute access
//                    object[_name] = value
//                }
//            }
//        },
//        
//        
//        handlePredicate: function (classObject) {
//            var meta  = classObject.meta
//            var name  = this.getName()
//            var props = this.getProps()
//            
//            var predicate = props.predicate
//            
//            var getter    = this.getterName()
//            
//            if(predicate) {
//                meta.addMethod(predicate, function () {
//                    var val = this[getter]()
//                    return val ? true: false
//                })
//            }
//        },
//        
//        
////XXX TypeChecker as Role (from Joose.TypeChecker)        
////        makeTypeChecker: function (isa, props, thing, name) {
////            var name  = this.getName()
////            
////            return function setter (value) {
////                this[name] = value
////                return this
////            }
////        },
//        
//        makeTypeChecker: function (isa, props, thing, name) {
//            var func
//            
//            if(isa) {
//                if(!isa.meta) {
//                    throw new Error("Isa declarations in attribute declarations must be Joose classes, roles or type constraints")
//                }
//                
//                var isRole  = false
//                var isType  = false
//                // We need to check whether Joose.Role and Joose.TypeContraint 
//                // are there yet, because they might not have been compiled yet
//                if(Joose.Role && isa.meta.meta.isa(Joose.Role)) {
//                    isRole  = true
//                } 
//                else if(Joose.TypeConstraint && isa.meta.isa(Joose.TypeConstraint)) {
//                    isType  = true
//                }
//                
//                // This setter is used if the attribute is constrained with an isa property in the attribute initializer
//                // If the isa refers to a class, then the new value must be an instance of that class.
//                // If the isa refers to a role,  then the new value must implement that role.
//                // If the isa refers to a type constraint, then the value must match that type contraint
//                // ...and if the coerce property is set, we try to coerce the new value into the type
//                // Throws an exception if the new value does not match the isa property.
//                // If errorHandler is given, it will be executed in case of an error with parameters (Exception, isa-Contraint)
//                func = function setterWithIsaCheck (val, errorHandler) {
//                    var value = val
//                    try {
//                        if ( props.nullable === true && value == undefined) {
//                            // Don't do anything here:)
//                        } else if ( isType ) {
//                            var newvalue = null
//                            if( props.coerce ) {
//                                newvalue = isa.coerce(value)
//                            }
//                            if ( newvalue == null && props.nullable !== true) {
//                                isa.validate(value)
//                            } else {
//                                value = newvalue
//                            }
//                        } else {
//                            if(!value || !value.meta) {
//                                throw new ReferenceError("The attribute "+name+" only accepts values that have a meta object.")
//                            }
//                            var typeCheck = isRole ? value.meta.does(isa): value.meta.isa(isa)
//                            if( ! typeCheck ) {
//                                throw new ReferenceError("The attribute "+name+" only accepts values that are objects of type "+isa.meta.className()+".")
//                            }
//                        }
//                    } catch (e) {
//                        if(errorHandler) {
//                            errorHandler.call(this, e, isa)
//                        } else {
//                            throw e
//                        }
//                    }
//                    this[name] = value
//                    return this
//                }
//            } else {
//                func = function setter (value) {
//                    this[name] = value
//                    return this
//                }
//            }
//            
//            return func
//        },
//        
//
//        handleHandles: function (classObject) {
//            var meta  = classObject.meta
//            var name  = this.getName()
//            var props = this.getProps()
//            
//            var handles = props.handles
//            var isa     = props.isa
//            
//            if(handles) {
//                if(handles == "*") {
//                    if(!isa) {
//                        throw "I need an isa property in order to handle a class"
//                    }
//                    
//                    // receives the name and should return a closure
//                    var optionalHandlerMaker = props.handleWith
//                    
//                    //XXX decorate appears before Joose.Decorator
//                    meta.decorate(isa, name, optionalHandlerMaker)
//                } 
//                else {
//                    throw "Unsupported value for handles: "+handles
//                }
//                
//            }
//        }
//        
//    }
//    
//});
Joose.Managed.PropertySet.Namespace = new Joose.Proto.Class('Joose.Managed.PropertySet.Namespace', {
    
	isa : Joose.Managed.PropertySet.Containable,
    
    propertyMetaClass : null,
    
    
    computeContainer : function(props){
        this.container = this.targetMeta.c
    },
    
    
    apply : function(target){
        this.each(function(property, name){
        	this.container[name] = property
        }, this)
    },
    
    
    unapply : function(){
        this.each(function(property, name){
	        try {
	            delete this.container[name]
	        } catch(e) {
	            this.container[name] = undefined
	        }
        }, this)
    },
    
    
    
    prepareApply : function(){
    },
    
    
    addProperty : function (name, value) {
        if (value && value.meta && value.meta.meta.hasAttribute('ns')) value.meta.parent = this.targetMeta.ns
        
        return this.container[name] = this.properties[name] = value
    },
    

    haveOwnProperty : function(name) {
        return this.haveProperty(name);// && this.container.hasOwnProperty(name)
    },
    
    
    addPropertyObject : function (object) {
    }
    
    
}).c
;
Joose.Managed.Attribute.Builder = new Joose.Managed.Role('Joose.Managed.Attribute.Builder', {
    
    
    have : {
    	defaultAttributeClass : Joose.Managed.Attribute
    },
    
    builder : {
    	
    	methods : {
			has : function (targetClassMeta, info) {
		        Joose.O.eachSafe(info, function(props, name) {
		        	if (typeof props != 'object' || props == null) props = { init : props }
		        	
		        	props.meta = props.meta || targetClassMeta.defaultAttributeClass
		        	
		            targetClassMeta.addAttribute(name, props.init, props)
		        }, this)
			},
			
			
		    hasnot : function(targetClassMeta, info) {
		        this.havenot(targetClassMeta, info)
		    },
		    
		    
		    hasnt : function(targetClassMeta, info) {
		        this.hasnot(targetClassMeta, info)
		    }
    	}
    		
    }
    
}).c



//Joose.Meta.Class.meta.extend({
//    does                        : [ Joose.Managed.Attribute.Builder ]
//})
//
//
//Joose.Meta.Role.meta.extend({
//    does                        : [ Joose.Managed.Attribute.Builder ]
//})
;
//XXX
//currently symbiont's metaclass is the same as metaclass of hoster, thus metaclasses cant have symbionts for now
//this can be fixed by reducing the metaclass on 1 level down (to this.meta.superClass) if this.constructor == this.superClass

Joose.Managed.My = new Joose.Managed.Role('Joose.Managed.My', {
    
    have : {
        myClass                         : null
    },
    
    
    methods : {
	    createMy : function (extend) {
	        var thisMeta = this.meta
	        var isRole = this instanceof Joose.Managed.Role
	        
	        var myExtend = extend.my || {}; 
	        delete extend.my
	        
	        var myClass = this.myClass = isRole ? new this.constructor(null, myExtend).c : this.subClassOf(this.superClass.meta.myClass || thisMeta.defaultSuperClass.meta.myClass || thisMeta.defaultSuperClass, myExtend)
	        
	        this.c.my = isRole ? myClass : new myClass({ targetMeta : this })
	    }
    },
    
    
    override : {
        extend : function(props) {
            if (!this.myClass && this.superClass.meta.myClass) this.createMy(props)
            
            if (props.my)
            	if (!this.myClass) 
            		this.createMy(props)
            	else {
	                this.myClass.meta.extend(props.my)
	                delete props.my
            	}
            
            this.SUPER(props)
        }
    },
    
    
    before : {
        addRole : function() {
        	if (!this.myClass) return
        	
            var myStem = this.myClass.meta.stem
            myStem.open()
            
            Joose.A.each(arguments, function(arg){
                var role = (arg.meta instanceof Joose.Managed.Role) ? arg : arg.role
                
                if (role.meta.meta.hasAttribute('myClass') && role.meta.myClass) myStem.addComposeInfo(role.my.meta.stem)
            }, this)
            
            myStem.close()
        },
        
        
        removeRole : function(){
        	if (!this.myClass) return
        	
            var myStem = this.myClass.meta.stem
            myStem.open()
            
            Joose.A.each(arguments, function(role){
                if (role.meta.meta.hasAttribute('myClass') && role.meta.myClass) myStem.removeComposeInfo(role.my.meta.stem)
            }, this)
            
            myStem.close()
        }
        
    }
    
}).c


//Joose.Meta.Class.meta.extend({
//    does                        : [ Joose.Managed.My ]
//})
//
//
//Joose.Meta.Role.meta.extend({
//    does                        : [ Joose.Managed.My ]
//});
Joose.Namespace = function(){ throw "Modules may not be instantiated." }

Joose.Namespace.Able = new Joose.Meta.Role('Joose.Namespace.Able', {

    have : {
        parent                  : null,
        
        localName               : null,
        
        ns                      : null
    },
    
    
    after: {
        //at this point targetMeta will contain 'c' which is a container for namespace
        extractConstructor: function (extend) {
            this.localName = (this.name || '').split('.').pop()
            
            this.ns = new Joose.Managed.PropertySet.Namespace(this.name, { targetMeta : this })
        }
    },
    
    
    methods : {
        copyNamespaceState : function(targetClass) {
        	var targetMeta = targetClass.meta
        	
        	if (!targetMeta.meta.hasAttribute('ns')) throw "No ns"
        	
        	this.ns.unapply()
        	
            targetMeta.parent               = this.parent
            targetMeta.localName            = this.localName
            
            targetMeta.ns                   = this.ns
            targetMeta.ns.targetMeta		= targetMeta
            targetMeta.ns.computeContainer()
            
            targetMeta.ns.apply()
        }
    },
    
    
    builder : {
    	
    	override : {
    		//executing body last
    		_extend : function(props) {
		        var targetMeta = this.targetMeta
		        
		        this._buildStart(targetMeta, props)
		        
		        props = props || {}
	            var body = props.body
	            delete props.body
	            
	            this.SUPER(props)
	            
	            this.body(targetMeta, body)
		        
		        
		        this._buildComplete(targetMeta, props)
    		}
    	},
    	
    	
    	methods : {
    		
	        body: function (meta, bodyFunc) {
	            if (bodyFunc) Joose.Namespace.Manager.my.executeIn(meta.c, bodyFunc, meta.ns.container, [meta.c])
	        },
	        
	
	        version: function () {
	            throw "Probably you need to include Depended Role into your deployment"
	        },
	        
	        
	        use: function () {
	            throw "Probably you need to include Depended Role into your deployment"
	        }
    		
    	}
    }
    
}).c


Joose.Meta.Class.meta.extend({
    does                        : [ Joose.Managed.My, Joose.Managed.Attribute.Builder, Joose.Namespace.Able ]
})


Joose.Meta.Role.meta.extend({
    does                        : [ Joose.Managed.My, Joose.Managed.Attribute.Builder, Joose.Namespace.Able ]
})
;
Joose.Namespace.Keeper = new Joose.Meta.Class('Joose.Namespace.Keeper', {
    
    isa : Joose.Meta.Class,
    
    have : {
        externalConstructor: null
    },
    
    
    methods: {
        
        defaultConstructor: function (){
            return function(){
                if (this.meta instanceof Joose.Namespace.Keeper) throw new Error("Module [" + this.constructor + "] may not be instantiated.")
                
                if (typeof this.meta.externalConstructor == 'function') {
                    this.meta.externalConstructor.apply(this, arguments)
                    return
                }
                
                throw new Error("NamespaceKeeper was planted incorrectly.")
            }
        },
        
        
        //withClass should be not constructed yet on this stage (see Joose.Proto.Class.construct)
        plant: function (withClass) {
            var keeper = this.c
            
            keeper.meta = withClass.meta
            delete withClass.meta
            
            keeper.meta.c = keeper
            keeper.meta.externalConstructor = withClass
            
            this.copyNamespaceState(keeper)
        }
        
    }
    
}).c


;
Joose.Namespace.Manager = new Joose.Meta.Class('Joose.Namespace.Manager', {
    
    my : {
        
        have : {
            global : null
        },
        
        
        methods : {
            
            initialize : function(){
                var global = this.global = new Joose.Namespace.Keeper().c
                
                global.meta.ns.container = Joose.top
                global.meta.parent = global
                
                global.meta.ns.addProperty('__global__', global.meta.ns)
                __global__.addProperty('Joose', new Joose.Namespace.Keeper("Joose", { constructor : Joose }).c)
                Joose.meta.ns.addProperty('Namespace', new Joose.Namespace.Keeper("Joose.Namespace", { constructor : Joose.Namespace }).c)
            },
            
            
            getCurrent: function (){
                var limit = 50
                var msg = "getCurrent() failed with limit=" + limit
                var cur = arguments.callee.caller
                
                while (cur && limit) {
                    if (cur.__JOOSE_MODULE__) return cur.__JOOSE_MODULE__
                    
                    //sometimes throws an exception (seems when called from DOM event callback)
                    try {
                        cur = cur.caller
                    } catch (e) {
                        cur = null
                    }
                    limit--
                }
                
                //cur == null - we have reached the outer space )
                if (limit) return this.global
                
                throw msg
            },
            
            
            executeIn : function (ns, func, scope, argsArray) {
                var namespaceKeeper = function (func, ns) {
                    namespaceKeeper.__JOOSE_MODULE__ = ns
                    return func.apply(scope || this, argsArray || [])
                }
                
                return namespaceKeeper(func, ns)
            },
            
            
            earlyCreate : function (name, metaClass, props) {
            	var earlyProps = {
                    constructorOnly : true
                }
            	
            	if (props && props.hasOwnProperty('constructor')) {
                    earlyProps.constructor = props.constructor
                    delete props.constructor
                }
            	
            	return new metaClass(name, earlyProps).c
            },
            
            
            //this function establishing the full "namespace chain" (including the last element)
            create : function (nsName, metaClass, extend, currentNs) {
            	props = extend || {}
            	
                var parts   = Joose.S.saneSplit(nsName, '.')
                if (!parts.length) throw "Cant prepare namespace with empty name = [" + nsName + "]"; 
                
                var object  = currentNs || this.getCurrent()
                var soFar   = Joose.S.saneSplit(object.meta.name, '.')
                
                for(var i = 0; i < parts.length; i++) {
                    var part = parts[i]
                    var isLast = i == parts.length - 1
                    
                    if (part == "meta" || part == "my" || !part) throw "Module name [" + nsName + "] may not include a part called 'meta' or 'my' or empty part."
                    
                    var cur = (object == this.global ? this.global.meta.ns.container : object)[part]//object.meta.ns.getProperty(part)
                    
                    soFar.push(part)
                    var soFarName = soFar.join(".")
                    var needFinalize = false
                    var nsKeeper
                    
                    if (typeof cur == "undefined") {
                    	if (isLast) {
                    		nsKeeper = this.earlyCreate(soFarName, metaClass, props)
                    		needFinalize = true
                    	} else
                    		nsKeeper = new Joose.Namespace.Keeper(soFarName).c
                    	
                        if (object.meta) 
                        	object.meta.ns.addProperty(nsKeeper.meta.localName, nsKeeper)
                    	else
                    		object[nsKeeper.meta.localName] = nsKeeper
                        
                        cur = nsKeeper
                    } else if (isLast && cur && cur.meta) {
                    	//XXX needs cleanup and sanitizing
                    	if (cur.meta.constructor == metaClass && extend)
                    		cur.meta.extend(props)
                    	else if (cur.meta instanceof Joose.Namespace.Keeper && metaClass != Joose.Namespace.Keeper) { 
                    		cur.meta.plant(this.earlyCreate(soFarName, metaClass, props))
                    		needFinalize = true
                    	} 
                    	else if (metaClass != Joose.Namespace.Keeper)
                    		throw "Re-declaration of class " + soFarName + "with different meta is not allowed";                    		
                    	
                    } else 
                    	if (isLast && !(cur && cur.meta && cur.meta.meta && cur.meta.meta.hasAttribute('ns'))) throw "Trying to setup module " + soFarName + " failed. There is already something: " + cur
                    
                    if (needFinalize) cur.meta.construct(props)
                        
                    object = cur
                }
                
                return object
            }
            
        }
    }
    
}).c;
Joose.Helper = new Joose.Meta.Class('Joose.Helper', {
	
	my : {
		
		methods : {
			
			registerHelper : function (name, helperMeta, func) {
				
				if (!func) func = function (name, props) {
				    var metaClass
				    
				    if (props && props.meta) {
				        metaClass = props.meta
				        delete props.meta
				    }	
					
					Joose.Namespace.Manager.my.create(name, metaClass || helperMeta, props, Joose.Namespace.Manager.my.getCurrent())
				}
				
				__global__.addProperty(name, func)
			}
			
		}
		
	}

}).c



Joose.Helper.my.registerHelper('Class', Joose.Meta.Class, function (name, props) {
    var metaClass
    
    if (props && props.meta) {
        metaClass = props.meta
        delete props.meta
    } else if (props && typeof props.isa == 'function')
        metaClass = props.isa.meta.constructor
    else
        metaClass   = Joose.Meta.Class
    
    return Joose.Namespace.Manager.my.create(name, metaClass, props, Joose.Namespace.Manager.my.getCurrent()); 
})


Joose.Helper.my.registerHelper('Role', Joose.Meta.Role)


Joose.Helper.my.registerHelper('Module', Joose.Namespace.Keeper, function (name, props) {
	if (typeof props == 'function') props = { body : props }
	
    return Joose.Namespace.Manager.my.create(name, Joose.Namespace.Keeper, props, Joose.Namespace.Manager.my.getCurrent()); 
})
;