Nickolay - KiokuJS-0.01

Documentation | Source
Class('KiokuJS.Linker', {
    
    trait   : 'JooseX.CPS',
    
    
    use     : 'KiokuJS.Linker.Expander',
    
    
    has : {
        scope           : { 
            required        : true,
            handles         : 'decodeEntries'
        },
        
        entries         : Joose.I.Object,
        
        nodes           : {
            lazy    : function () {
                return this.decodeEntries(this.entries)
            }
        }
    },
    

    methods : {
        
        BUILD : function (config) {
            var entries = config.entries
            
            if (entries instanceof Array) {
                var entriesByID = {}
                
                Joose.A.each(entries, function (entry) {
                    entriesByID[ entry.ID ] = entry
                })
                
                config.entries = entriesByID
            }
            
            return config
        },
        
        
        animateNodes : function () {
            var scope   = this.scope
            var nodes   = this.getNodes()
            
            KiokuJS.Linker.Expander.expandNodes(nodes, this.scope)
            
            Joose.O.each(nodes, function (node, id) {
                
                if (node.isFirstClass()) scope.pinNode(node)
            })
        }
    },
    
    
    continued : {
        
        methods : {
            
            materialize : function (ids, shallowLevel) {
                var me          = this
                var scope       = this.scope
                var backend     = scope.getBackend()
                
                var idsToFetch  = []
                
                Joose.A.each(ids, function (id) {
                    if (!scope.idPinned(id) || shallowLevel > 0) idsToFetch.push(id)
                })
                

                backend.get(idsToFetch, scope).andThen(function (entries) {
                    
                    var newEntries        = []
                    
                    // filter the entries returned from backend to only the new ones
                    // (which don't already have corresponding object in the scope)
                    // this should allow backends to pre-fetch references (potentially
                    // with extra entries)
                    Joose.A.each(entries, function (entry) {
                        
                        var entryID      = entry.ID
                        
                        // some entry was returned repeatedly
                        if (me.entries[ entryID ]) return
                        
                        if (!scope.idPinned(entryID) || shallowLevel > 0) {

                            me.entries[ entryID ] = entry
                            
                            newEntries.push(entry)
                        }
                    })
                    
                    var notFetchedIds   = []
                    
                    Joose.A.each(scope.gatherReferences(newEntries), function (refID) {
                        if (me.entries[ refID ]) return
                        
                        if (!scope.idPinned(refID) || shallowLevel == 2) notFetchedIds.push(refID)
                    })
                    
                    if (notFetchedIds.length)
                        me.materialize(notFetchedIds, shallowLevel == 2 ? 2 : 0).now()
                    else 
                        me.prefetchClasses(me.getNodes()).andThen(function () {
                            
                            me.animateNodes()
                            
                            this.CONTINUE()
                        })
                })
            },
            
            
            prefetchClasses : function (nodes) {
                // gathering classes of the nodes, which needs to be loaded
                var classDescriptors = []
                
                //XXX extract required classes from typemap instead of directly from node (node.getRequiredClasses())
                Joose.O.each(nodes, function (node, id) {
                    
                    var className = node.className
                    
                    if (className == 'Object' || className == 'Array') return
                    
                    if (node.classVersion) 
                        classDescriptors.push({ type : 'joose', token : className, version : node.classVersion })
                    else
                        classDescriptors.push(className)
                        
                    if (node.objTraits) classDescriptors.push.apply(classDescriptors, node.objTraits)
                })
                
                use(classDescriptors, this.getCONTINUE())
            },
            
            
            link : function (ids, shallowLevel) {
                // fetching resolver's classes (in case it has been mutated)
                this.scope.getResolver().fetchClasses().andThen(function () {
                    
                    this.materialize(ids, shallowLevel).now()
                    
                }, this)
            }
        }
    }
    

})