package org.puremvc.as3.multicore.utilities.lazy.patterns.core { import flash.utils.Dictionary; import org.puremvc.as3.multicore.core.View; import org.puremvc.as3.multicore.interfaces.IMediator; import org.puremvc.as3.multicore.patterns.facade.Facade; import org.puremvc.as3.multicore.utilities.lazy.interfaces.IFacadeAdapter; import org.puremvc.as3.multicore.utilities.lazy.interfaces.ILazyAdapter; import org.puremvc.as3.multicore.utilities.lazy.interfaces.IViewAdapter; import org.puremvc.as3.multicore.utilities.lazy.interfaces.IViewFilters; public class LazyView extends View implements IViewAdapter, IViewFilters { public function LazyView(key:String) { super(key); } protected const mediatorClassMap:Dictionary = new Dictionary(); protected const packageFiltersMap:Dictionary = new Dictionary(); protected var lazyFacade:ILazyAdapter; protected function get facadeAdapter():IFacadeAdapter { return lazyFacade as IFacadeAdapter; } override protected function initializeView():void { super.initializeView(); lazyFacade = ILazyAdapter(Facade.getInstance(multitonKey)); registerPackageFilter('flash.*'); registerPackageFilter('mx.*'); } public function registerAutoMediatorClass(mediatorClass:Class, viewComponentClass:Class, invariant:Boolean=false):void { const variance:int = int(invariant); if (!(viewComponentClass in mediatorClassMap)) { mediatorClassMap[viewComponentClass] = []; } if (!(mediatorClassMap[viewComponentClass][variance])) { mediatorClassMap[viewComponentClass][variance] = mediatorClass; } if (!(mediatorClassMap[viewComponentClass][variance])) { mediatorClassMap[viewComponentClass][variance] = mediatorClass; } } public function hasAutoMediatorClass(viewComponentClass:Class, invariant:Boolean=false):Boolean { return viewComponentClass in mediatorClassMap && mediatorClassMap[viewComponentClass][int(invariant)]; } public function removeAutoMediatorClass(viewComponentClass:Class, invariant:Boolean=false):Class { if (!(hasAutoMediatorClass(viewComponentClass, invariant))) { return null; } const mediatorClass:Class = mediatorClassMap[viewComponentClass][int(invariant)]; if (mediatorClassMap[viewComponentClass][int(!invariant)]) { mediatorClassMap[viewComponentClass][int(invariant)] = null; } else { delete mediatorClassMap[viewComponentClass]; } return mediatorClass; } public function retrieveAutoMediators(viewComponent:Object):Array { if (!applyFilters(viewComponent)) { return []; } const mediatorTuple:Object = retrieveAutoMediatorTuple(viewComponent); const mediatorNames:Array = mediatorTuple.names; mediatorNames.push.apply(null, (mediatorTuple.types as Array).map(function(_:Class, ...rest):String { const mediator:IMediator = new _(mediatorNames[0], viewComponent); registerMediator(mediator); return mediator.getMediatorName(); })); if (!hasMediator(mediatorNames[0])) { mediatorNames.shift(); } return mediatorNames.map(function(_:String, ...rest):IMediator { return retrieveMediator(_); }); } public function removeAutoMediators(viewComponent:Object):Array { if (!applyFilters(viewComponent)) { return []; } const mediatorNames:Array = retrieveAutoMediatorTuple(viewComponent).names; if (!hasMediator(mediatorNames[0])) { mediatorNames.shift(); } return mediatorNames.map(function(_:String, ...rest):IMediator { return removeMediator(_); }); } public function registerPackageFilter(packageFilter:String):void { // e.g. "mx.controls.*" to /^mx\.controls\..+$/ packageFiltersMap[packageFilter] = new RegExp('^' + packageFilter.replace(/\./g, '\\$&').replace(/\*/g, '.+') + '$'); } public function removePackageFilter(packageFilter:String):void { delete packageFiltersMap[packageFilter]; } public function applyFilters(viewComponent:Object):Boolean { if (!facadeAdapter) { return true; } for each (var packageFilter:RegExp in packageFiltersMap) { if (packageFilter.test(facadeAdapter.getFQCN(viewComponent.constructor).uri)) { return false; } } return true; } protected function retrieveAutoMediatorTuple(viewComponent:Object):Object { const mediatorNames:Array = [ ('name' in viewComponent) ? viewComponent.name : null ]; const mediatorClasses:Array = retrieveAutoMediatorClasses(viewComponent); mediatorNames.push.apply(null, mediatorClasses.map(function(_:Class, ...rest):String { return lazyFacade.retrieveName(_, mediatorNames[0]); }).filter(function(_:String, i:int, a:Array):Boolean { if (hasMediator(_)) { mediatorClasses[i] = null; } return !mediatorClasses[i]; })); return { names: mediatorNames, types: mediatorClasses.filter(function(_:*, ...rest):Boolean { return _; }) }; } protected function retrieveAutoMediatorClasses(viewComponent:Object):Array { const mediatorClasses:Array = []; var viewComponentClass:* = viewComponent.constructor; if (hasAutoMediatorClass(viewComponentClass, true)) { mediatorClasses.push(mediatorClassMap[viewComponentClass][int(true)]); } for (viewComponentClass in mediatorClassMap) { if (viewComponent is viewComponentClass && hasAutoMediatorClass(viewComponentClass, false)) { mediatorClasses.push(mediatorClassMap[viewComponentClass][int(false)]); } } return mediatorClasses; } } }