fileoverview import _ from "lodash" ; const MSGS = { TYPE_MISMATCH : "Type does not match this collection type" , KEY_ALREADY_EXISTS : "Collection key already exists. " , KEY_DOES_NOT_EXIST : "Collection key does not exist in this collection." , MUST_GIVE_KEY : "Collection missing key." , MUST_GIVE_VALUE : "Collection missing value." , KEY_NOT_VALID : "Key must be of type String or Number" } ; export class Collection < T > { protected _items : { [ key ] : T ; } = { } ; protected _order : ( string | number ) [ ] = [ ] ; param _name param _type constructor ( protected _name = "Untitled Collection" , protected _type ? ) { } onAdd ( in_key , in_value ) { } onRemove ( in_key , in_value ) { } onClear ( in_items ) { } public get items ( ) { return this . _items ; } public get keys ( ) { return Object . keys ( this . _items ) ; } param in_key param in_value returns add ( in_key , in_value ) { this . _checkType ( in_value ) ; this . _checkIsNewKey ( in_key ) ; this . _items [ in_key ] = in_value ; this . _order . push ( in_key ) ; this . onAdd ( in_key , in_value ) ; return in_value ; } param in_value returns private _checkType ( in_value ) { if ( this . _type && ! ( in_value instanceof this . _type ) ) { throw new Error ( MSGS . TYPE_MISMATCH ) ; } else { return true ; } } param in_items returns bulkAdd ( in_items ) { _ . each ( in_items , ( item , key ) => { this . add ( key , item ) ; } ) ; return this ; } param in_items returns bulkRemove ( in_items ) { _ . each ( in_items , ( item , key ) => { this . remove ( key ) ; } ) ; return this ; } returns isEmpty ( ) { return _ . isEmpty ( this . _items ) ; } returns getFirstItem ( ) { const index = _ . first ( this . _order ) ; return index === undefined ? index : this . _items [ index ] ; } returns getLastItem ( ) { const index = _ . last ( this . _order ) ; return index === undefined ? index : this . _items [ index ] ; } returns getType ( ) { return this . _type ; } returns getName ( ) { return this . _name ; } param in_filterFunction returns filter ( in_filterFunction ) { const rtn = new Collection < T > ( ) ; const filterCb = function ( in_key , in_item ) { const keeper = in_filterFunction ( in_key , in_item ) ; if ( keeper ) { rtn . add ( in_key , in_item ) ; } } ; this . iterate ( filterCb ) ; return rtn ; } param in_filterKey returns filterByKey ( in_filterKey ) { const rtn = new Collection < T > ( ) ; let filterCb ; if ( _ . isArray ( in_filterKey ) ) { filterCb = function ( in_key , in_item ) { if ( in_filterKey . indexOf ( in_key ) >= 0 ) { rtn . add ( in_key , in_item ) ; } } ; } else { filterCb = function ( in_key , in_item ) { if ( in_key === in_filterKey ) { rtn . add ( in_key , in_item ) ; } } ; } this . iterate ( filterCb ) ; return rtn ; } param in_filterValue returns filterByValue ( in_filterValue ) { const rtn = new Collection < T > ( ) ; const filterCb = function ( in_key , in_item ) { if ( in_item === in_filterValue ) { rtn . add ( in_key , in_item ) ; } } ; this . iterate ( filterCb ) ; return rtn ; } param in_key returns remove ( in_key ) { if ( ! this . has ( in_key ) ) { return false ; } const remember = this . _items [ in_key ] ; delete this . _items [ in_key ] ; this . _order . splice ( this . _order . indexOf ( in_key ) , 1 ) ; this . onRemove ( in_key , remember ) ; return true ; } returns getCount ( ) { return this . _order . length ; } returns getAsArray ( ) { const rtnArr = new Array ( this . getCount ( ) ) ; for ( let i = 0 ; i < this . _order . length ; i ++ ) { rtnArr [ i ] = this . _items [ this . _order [ i ] ] ; } return rtnArr ; } param in_key returns has ( in_key ) { return Object . prototype . hasOwnProperty . call ( this . _items , in_key ) ; } param in_key returns item ( in_key ) { return this . _items [ in_key ] ; } param in_key returns private _checkIsNewKey ( in_key ) { if ( this . has ( in_key ) ) { throw new Error ( `${ MSGS . KEY_ALREADY_EXISTS } ${ in_key }` ) ; } return true ; } param in_key returns private _checkKeyExists ( in_key ) { if ( ! this . has ( in_key ) ) { throw new Error ( `${ MSGS . KEY_DOES_NOT_EXIST } ${ in_key }` ) ; } return true ; } param in_key param in_value returns set ( in_key , in_value ) { this . _checkKeyExists ( in_key ) ; this . _items [ in_key ] = in_value ; return in_value ; } param in_callback iterate ( in_callback ) { for ( const key of this . _order ) { const continu = in_callback ( key , this . _items [ key ] ) ; if ( continu === false ) { break ; } } } param in_callback iterateFromTail ( in_callback ) { let key ; let continu ; for ( let i = this . _order . length - 1 ; i >= 0 ; i -- ) { key = this . _order [ i ] ; continu = in_callback ( key , this . _items [ key ] ) ; if ( continu === false ) { break ; } } } returns getItems ( ) { const result = { } ; _ . each ( this . _items , function ( item , key ) { result [ key ] = item ; } ) ; return result ; } returns getKeys ( ) { return Object . keys ( this . _items ) ; } /**
     * Method used to get the first element in the collection along with its key.
     */ peak ( ) { return { item : this . _items [ this . _order [ 0 ] ] , key : this . _order [ 0 ] } ; } returns clear ( ) { if ( _ . isEmpty ( this . _items ) ) { return this ; } this . onClear ( this . _items ) ; _ . each ( this . getKeys ( ) , ( key ) => { this . remove ( key ) ; } ) ; return this ; } param in_collection returns clone ( ) { const newCol = new Collection < T > ( this . _name , this . _type ) ; newCol . bulkAdd ( this . _items ) ; return newCol ; } param in_collection copy ( in_collection ) { this . clear ( ) ; const its = in_collection . items ; _ . each ( its , ( item , key ) => { this . add ( key , item ) ; } ) ; } get values ( ) { return this . getAsArray ( ) ; } }