import { IClass , IType , IInjector , applyHooks , guardsApprove , instantiateUnmapped , ITypeFilter } from "@robotlegsjs/core" ; import { IMediatorMapping } from "../api/IMediatorMapping" ; import { MediatorManager } from "./MediatorManager" ; private export class MediatorFactory { private _mediators : Map < any , any > = new Map < any , any > ( ) ; private _injector : IInjector ; private _manager : MediatorManager ; private constructor ( injector , manager ? ) { this . _injector = injector ; this . _manager = manager || new MediatorManager ( this ) ; } private public getMediator ( item , mapping ) { return this . _mediators . get ( item ) ? this . _mediators . get ( item ) . get ( < any > mapping ) : null ; } private public createMediators ( item , type , mappings ) { let createdMediators = [ ] ; let mediator ; mappings . forEach ( ( mapping ) => { mediator = this . getMediator ( item , mapping ) ; if ( ! mediator ) { this . mapTypeForFilterBinding ( mapping . matcher , type , item ) ; mediator = this . createMediator ( item , mapping ) ; this . unmapTypeForFilterBinding ( mapping . matcher , type , item ) ; } if ( mediator ) { createdMediators . push ( mediator ) ; } } ) ; return createdMediators ; } private public removeMediators ( item ) { let mediators = this . _mediators . get ( item ) ; if ( ! mediators ) { return ; } mediators . forEach ( ( value , key ) => this . _manager . removeMediator ( value , item , key ) ) ; this . _mediators . delete ( item ) ; } private public removeAllMediators ( ) { this . _mediators . forEach ( ( value , key ) => this . removeMediators ( key ) ) ; } private createMediator ( item , mapping ) { let mediator = this . getMediator ( item , mapping ) ; if ( mediator ) { return mediator ; } if ( mapping . guards . length === 0 || guardsApprove ( mapping . guards , this . _injector ) ) { let mediatorClass = mapping . mediatorClass ; mediator = instantiateUnmapped ( this . _injector , mediatorClass ) ; if ( mapping . hooks . length > 0 ) { this . _injector . bind ( mediatorClass ) . toConstantValue ( mediator ) ; applyHooks ( mapping . hooks , this . _injector ) ; this . _injector . unbind ( mediatorClass ) ; } this . addMediator ( mediator , item , mapping ) ; } return mediator ; } private addMediator ( mediator , item , mapping ) { let mediatorMap = this . _mediators . get ( item ) || new Map < any , IMediatorMapping > ( ) ; this . _mediators . set ( item , mediatorMap ) ; mediatorMap . set ( < any > mapping , mediator ) ; this . _manager . addMediator ( mediator , item , mapping ) ; } private mapTypeForFilterBinding ( filter , type , item ) { let requiredTypes = this . requiredTypesFor ( filter , type ) ; requiredTypes . forEach ( ( requiredType ) => { this . _injector . bind ( requiredType ) . toConstantValue ( item ) ; } ) ; } private unmapTypeForFilterBinding ( filter , type , item ) { let requiredTypes = this . requiredTypesFor ( filter , type ) ; requiredTypes . forEach ( ( requiredType ) => { if ( this . _injector . isBound ( requiredType ) ) { this . _injector . unbind ( requiredType ) ; } } ) ; } private requiredTypesFor ( filter , type ) { let requiredTypes = filter . allOfTypes . concat ( filter . anyOfTypes ) ; if ( requiredTypes . indexOf ( type ) === - 1 ) { requiredTypes . push ( type ) ; } return requiredTypes ; } }