import { injectable } from "inversify" ; import { IBundle } from "../api/IBundle" ; import { IConfig } from "../api/IConfig" ; import { IContext } from "../api/IContext" ; import { IExtension } from "../api/IExtension" ; import { IInjector } from "../api/IInjector" ; import { ILogger } from "../api/ILogger" ; import { ILogTarget } from "../api/ILogTarget" ; import { IMatcher } from "../api/IMatcher" ; import { LifecycleEvent } from "../api/LifecycleEvent" ; import { ConfigManager } from "./ConfigManager" ; import { ExtensionInstaller } from "./ExtensionInstaller" ; import { Lifecycle } from "./Lifecycle" ; import { LogManager } from "./LogManager" ; import { Pin } from "./Pin" ; import { RobotlegsInjector } from "./RobotlegsInjector" ; import { UID } from "./UID" ; import { EventDispatcher } from "../../events/impl/EventDispatcher" ; import { IClass } from "../../extensions/matching/IClass" ; /**
 * The core Robotlegs Context implementation
 */ @ injectable ( ) export class Context extends EventDispatcher implements IContext { inheritDoc public get injector ( ) : IInjector { return this . _injector ; } inheritDoc public get logLevel ( ) : number { return this . _logManager . logLevel ; } inheritDoc public set logLevel ( value ) { this . _logManager . logLevel = value ; } inheritDoc public get state ( ) : string { return this . _lifecycle . state ; } inheritDoc public get uninitialized ( ) : boolean { return this . _lifecycle . uninitialized ; } inheritDoc public get initialized ( ) : boolean { return this . _lifecycle . initialized ; } inheritDoc public get active ( ) : boolean { return this . _lifecycle . active ; } inheritDoc public get suspended ( ) : boolean { return this . _lifecycle . suspended ; } inheritDoc public get destroyed ( ) : boolean { return this . _lifecycle . destroyed ; } private _uid : string = UID . create ( Context ) ; private _injector : IInjector ; private _logManager : LogManager ; private _children : IContext [ ] = [ ] ; private _pin : Pin ; private _lifecycle : Lifecycle ; private _configManager : ConfigManager ; private _extensionInstaller : ExtensionInstaller ; private _logger : ILogger ; /**
     * Creates a new Context
     */ constructor ( ) { super ( ) ; this . setup ( ) ; } inheritDoc public initialize ( callback ? ) { this . _lifecycle . initialize ( callback ) ; } inheritDoc public suspend ( callback ? ) { this . _lifecycle . suspend ( callback ) ; } inheritDoc public resume ( callback ? ) { this . _lifecycle . resume ( callback ) ; } inheritDoc public destroy ( callback ? ) { this . _lifecycle . destroy ( callback ) ; } inheritDoc public beforeInitializing ( handler ) { this . _lifecycle . beforeInitializing ( handler ) ; return this ; } inheritDoc public whenInitializing ( handler ) { this . _lifecycle . whenInitializing ( handler ) ; return this ; } inheritDoc public afterInitializing ( handler ) { this . _lifecycle . afterInitializing ( handler ) ; return this ; } inheritDoc public beforeSuspending ( handler ) { this . _lifecycle . beforeSuspending ( handler ) ; return this ; } inheritDoc public whenSuspending ( handler ) { this . _lifecycle . whenSuspending ( handler ) ; return this ; } inheritDoc public afterSuspending ( handler ) { this . _lifecycle . afterSuspending ( handler ) ; return this ; } inheritDoc public beforeResuming ( handler ) { this . _lifecycle . beforeResuming ( handler ) ; return this ; } inheritDoc public whenResuming ( handler ) { this . _lifecycle . whenResuming ( handler ) ; return this ; } inheritDoc public afterResuming ( handler ) { this . _lifecycle . afterResuming ( handler ) ; return this ; } inheritDoc public beforeDestroying ( handler ) { this . _lifecycle . beforeDestroying ( handler ) ; return this ; } inheritDoc public whenDestroying ( handler ) { this . _lifecycle . whenDestroying ( handler ) ; return this ; } inheritDoc public afterDestroying ( handler ) { this . _lifecycle . afterDestroying ( handler ) ; return this ; } inheritDoc public install ( ... extensions ) { extensions . forEach ( ( extension ) => { this . _extensionInstaller . install ( extension ) ; } ) ; return this ; } inheritDoc public configure ( ... configs ) { configs . forEach ( ( config ) => { this . _configManager . addConfig ( config ) ; } ) ; return this ; } inheritDoc public addChild ( child ) { if ( this . _children . indexOf ( child ) === - 1 ) { this . _logger . debug ( "Adding child context {0}" , [ child ] ) ; if ( ! child . uninitialized ) { this . _logger . warn ( "Child context {0} must be uninitialized" , [ child ] ) ; } if ( child . injector . parent ) { this . _logger . warn ( "Child context {0} must not have a parent Injector" , [ child ] ) ; } this . _children . push ( child ) ; child . injector . parent = this . injector ; child . addEventListener ( LifecycleEvent . POST_DESTROY , this . onChildDestroy , this ) ; } return this ; } inheritDoc public removeChild ( child ) { let childIndex = this . _children . indexOf ( child ) ; if ( childIndex > - 1 ) { this . _logger . debug ( "Removing child context {0}" , [ child ] ) ; this . _children . splice ( childIndex , 1 ) ; child . injector . parent = null ; child . removeEventListener ( LifecycleEvent . POST_DESTROY , this . onChildDestroy , this ) ; } else { this . _logger . warn ( "Child context {0} must be a child of {1}" , [ child , this ] ) ; } return this ; } inheritDoc public addConfigHandler ( matcher , handler ) { this . _configManager . addConfigHandler ( matcher , handler ) ; return this ; } inheritDoc public getLogger ( source ) { return this . _logManager . getLogger ( source ) ; } inheritDoc public addLogTarget ( target ) { this . _logManager . addLogTarget ( target ) ; return this ; } inheritDoc public detain ( ... instances ) { instances . forEach ( ( instance ) => { this . _pin . detain ( instance ) ; } ) ; return this ; } inheritDoc public release ( ... instances ) { instances . forEach ( ( instance ) => { this . _pin . release ( instance ) ; } ) ; return this ; } inheritDoc public toString ( ) { return this . _uid ; } /**
     * Configures mandatory context dependencies
     */ private setup ( ) { this . _logManager = new LogManager ( ) ; this . _injector = new RobotlegsInjector ( ) ; this . _injector . bind < IInjector > ( IInjector ) . toConstantValue ( this . _injector ) ; this . _injector . bind < IContext > ( IContext ) . toConstantValue ( this ) ; this . _logger = this . _logManager . getLogger ( this ) ; this . _pin = new Pin ( this ) ; this . _lifecycle = new Lifecycle ( this ) ; this . _configManager = new ConfigManager ( this ) ; this . _extensionInstaller = new ExtensionInstaller ( this ) ; this . beforeInitializing ( this . beforeInitializingCallback . bind ( this ) ) ; this . afterInitializing ( this . afterInitializingCallback . bind ( this ) ) ; this . beforeDestroying ( this . beforeDestroyingCallback . bind ( this ) ) ; this . afterDestroying ( this . afterDestroyingCallback . bind ( this ) ) ; } private beforeInitializingCallback ( ) { this . _logger . debug ( "Initializing..." ) ; } private afterInitializingCallback ( ) { this . _logger . debug ( "Initialize complete" ) ; } private beforeDestroyingCallback ( ) { this . _logger . debug ( "Destroying..." ) ; } private afterDestroyingCallback ( ) { this . _extensionInstaller . destroy ( ) ; this . _configManager . destroy ( ) ; this . _pin . releaseAll ( ) ; this . _injector . unbindAll ( ) ; this . removeChildren ( ) ; this . _logger . debug ( "Destroy complete" ) ; this . _logManager . removeAllTargets ( ) ; } private onChildDestroy ( event ) { this . removeChild ( < IContext > event . target ) ; } private removeChildren ( ) { while ( this . _children . length > 0 ) { this . removeChild ( this . _children [ this . _children . length - 1 ] ) ; } } }