import { MultiMap } from "./MultiMap" ; export class TwoKeyMultiMap < K1 extends Object , K2 extends Object , V > { private _allowDuplicates : boolean ; readonly [ Symbol . toStringTag ] = "TwoKeyMultiMap" ; private store : Map < K1 , MultiMap < K2 , V > > ; private _sizeOfValues : number ; private _sizeOfKeys : number ; param allowDuplicates constructor ( allowDuplicates = true ) { this . _allowDuplicates = allowDuplicates ; this . store = new Map < K1 , MultiMap < K2 , V > > ( ) ; this . _sizeOfKeys = 0 ; this . _sizeOfValues = 0 ; } get allowDuplicates ( ) : boolean { return this . _allowDuplicates ; } /** Alias for `sizeOfKeys()`. */ get size ( ) : number { return this . sizeOfKeys ; } get sizeOfKeys ( ) : number { return this . _sizeOfKeys ; } get sizeOfValues ( ) : number { return this . _sizeOfValues ; } returns get ( key1 , key2 ) { let secondaryKeys = this . store . get ( key1 ) ; if ( secondaryKeys === undefined ) { return [ ] ; } return secondaryKeys . get ( key2 ) ; } set ( key1 , key2 , ... values ) { if ( values . length === 0 ) return this ; let secondaryMap = this . store . get ( key1 ) ; if ( ! secondaryMap ) { this . _sizeOfKeys ++ ; secondaryMap = new MultiMap < K2 , V > ( this . allowDuplicates ) ; this . store . set ( key1 , secondaryMap ) ; } let originalValueSize = secondaryMap . sizeOfValues ; secondaryMap . set ( key2 , ... values ) ; this . _sizeOfValues += secondaryMap . sizeOfValues - originalValueSize ; return this ; } /**
     * set all values from a TwoKeyMultiMap of the same type into this TwoKeyMultiMap.
     */ setAll ( other ) { for ( let [ key1 , key2 , values ] of other . entries ( ) ) { this . set ( key1 , key2 , ... values ) ; } } clear ( ) { this . store . clear ( ) ; this . _sizeOfKeys = 0 ; this . _sizeOfValues = 0 ; } /**
     * Deletes all values for the given keys.
     */ delete ( key1 , key2 ) { let secondaryKeys = this . store . get ( key1 ) ; if ( ! secondaryKeys ) return false ; let result = secondaryKeys . delete ( key2 ) ; if ( result ) { if ( secondaryKeys . size === 0 ) { this . store . delete ( key1 ) ; } } return true ; } returns deleteValue ( key1 , key2 , ... valuesToDelete ) { let secondaryKeys = this . store . get ( key1 ) ; if ( ! secondaryKeys ) return [ ] ; let originalValueSize = secondaryKeys . sizeOfValues ; let foundValues = secondaryKeys . deleteValue ( key2 , ... valuesToDelete ) ; this . _sizeOfValues += secondaryKeys . sizeOfValues - originalValueSize ; if ( foundValues . length > 0 && ! secondaryKeys . has ( key2 ) ) { this . _sizeOfKeys -- ; if ( secondaryKeys . size === 0 ) { this . store . delete ( key1 ) ; } } return foundValues ; } forEach ( callback , thisArg ? ) { this . store . forEach ( ( ( secondaryKeys , key1 ) => { secondaryKeys . forEach ( ( values , key2 ) => { callback . call ( thisArg , values , [ key1 , key2 ] , this ) ; } ) ; } ) ) ; } forEachValue ( callback , thisArg ? ) { this . store . forEach ( ( ( secondaryKeys , key1 ) => { secondaryKeys . forEach ( ( values , key2 ) => { for ( let value of values ) { callback . call ( thisArg , value , [ key1 , key2 ] , this ) ; } } ) ; } ) ) ; } /**
     * checks if the MultiMap has at least one value for the key.
     */ has ( key1 , key2 ) { let secondaryKeys = this . store . get ( key1 ) ; if ( secondaryKeys ) { return secondaryKeys . has ( key2 ) ; } else { return false ; } } /**
     * checks if the MultiMap has the specified value for the key.
     */ hasValue ( key1 , key2 , value ) { let secondaryKeys = this . store . get ( key1 ) ; if ( secondaryKeys ) { return secondaryKeys . hasValue ( key2 , value ) ; } else { return false ; } } /**
     *  iterate over all keys and values in this MultiMap.
     */ [ Symbol . iterator ] ( ) { return this . entries ( ) ; } * entries ( ) { for ( let entry of this . store . entries ( ) ) { for ( let subentry of entry [ 1 ] ) { yield [ entry [ 0 ] , subentry [ 0 ] , subentry [ 1 ] ] ; } } } /** iterates over each value of each key providing both key and value. */ * individualEntries ( ) { for ( let entry of this . store . entries ( ) ) { for ( let subentry of entry [ 1 ] ) { for ( let value of subentry [ 1 ] ) { yield [ entry [ 0 ] , subentry [ 0 ] , value ] ; } } } } * keys ( ) { for ( let [ key1 , subKeys ] of this . store . entries ( ) ) { for ( let key2 of subKeys . keys ( ) ) { yield [ key1 , key2 ] ; } } } primaryKeys ( ) { return this . store . keys ( ) ; } subKeys ( key ) { let map = this . store . get ( key ) ; if ( ! map ) { return ( new Set < K2 > ( ) ) . keys ( ) ; } return map . keys ( ) ; } /** iterates over each set of values that are stored in the MultiMap. */ * values ( ) { for ( let subKeys of this . store . values ( ) ) { for ( let values of subKeys . values ( ) ) { yield values ; } } } /** iterates over each value individually that stored in the MultiMap. */ * individualValues ( ) { for ( let subKeys of this . store . values ( ) ) { for ( let values of subKeys . values ( ) ) { for ( let value of values ) { yield value ; } } } } }