import { IType } from "./IType" ; import { ITypeFilter } from "./ITypeFilter" ; import { ITypeMatcher } from "./ITypeMatcher" ; import { ITypeMatcherFactory } from "./ITypeMatcherFactory" ; import { TypeFilter } from "./TypeFilter" ; import { TypeMatcherError } from "./TypeMatcherError" ; /**
 * A Type Matcher matches objects that satisfy type matching rules
 */ export class TypeMatcher implements ITypeMatcher , ITypeMatcherFactory { protected _allOfTypes : IType < any > [ ] = [ ] ; protected _anyOfTypes : IType < any > [ ] = [ ] ; protected _noneOfTypes : IType < any > [ ] = [ ] ; protected _typeFilter : ITypeFilter = null ; /**
     * All types that an item must extend or implement
     */ public allOf ( type , ... types ) { if ( type instanceof Array ) { this . pushAddedTypesTo ( type . concat ( types ) , this . _allOfTypes ) ; } else { this . pushAddedTypesTo ( [ type ] . concat ( types ) , this . _allOfTypes ) ; } return this ; } /**
     * Any types that an item must extend or implement
     */ public anyOf ( type , ... types ) { if ( type instanceof Array ) { this . pushAddedTypesTo ( type . concat ( types ) , this . _anyOfTypes ) ; } else { this . pushAddedTypesTo ( [ type ] . concat ( types ) , this . _anyOfTypes ) ; } return this ; } /**
     * Types that an item must not extend or implement
     */ public noneOf ( type , ... types ) { if ( type instanceof Array ) { this . pushAddedTypesTo ( type . concat ( types ) , this . _noneOfTypes ) ; } else { this . pushAddedTypesTo ( [ type ] . concat ( types ) , this . _noneOfTypes ) ; } return this ; } inheritDoc public createTypeFilter ( ) { return ( this . _typeFilter = this . _typeFilter || this . buildTypeFilter ( ) ) ; } return public lock ( ) { this . createTypeFilter ( ) ; return this ; } inheritDoc public clone ( ) { return new TypeMatcher ( ) . allOf ( this . _allOfTypes ) . anyOf ( this . _anyOfTypes ) . noneOf ( this . _noneOfTypes ) ; } protected buildTypeFilter ( ) { if ( this . _allOfTypes . length === 0 && this . _anyOfTypes . length === 0 && this . _noneOfTypes . length === 0 ) { throw new TypeMatcherError ( TypeMatcherError . EMPTY_MATCHER ) ; } return new TypeFilter ( this . _allOfTypes , this . _anyOfTypes , this . _noneOfTypes ) ; } protected pushAddedTypesTo ( types , targetSet ) { if ( this . _typeFilter ) { this . throwSealedMatcherError ( ) ; } this . pushValuesToTargetSet ( types , targetSet ) ; } protected throwSealedMatcherError ( ) { throw new TypeMatcherError ( TypeMatcherError . SEALED_MATCHER ) ; } protected pushValuesToTargetSet ( values , targetSet ) { values . forEach ( ( type ) => { targetSet . push ( type ) ; } ) ; } }