import ResourceUtils from "../ResourceUtils" ; import { EditDialogData } from "./Sling" ; interface ResourceEntry { depth : number ; data : any ; } /**
 * This cache is used to store server side data and pass it to the client.
 */ export default class Cache { constructor ( ) { this . resources = { } ; this . scripts = { } ; this . included = { } ; this . serviceCalls = { } ; } private resources : { [ path ] : ResourceEntry ; } ; private scripts : { [ path ] : EditDialogData ; } ; private included : { [ path ] : string ; } ; private serviceCalls : { [ path ] : any ; } ; public generateServiceCacheKey ( service , method , args ) { let cacheKey = service + "." + method + "(" ; for ( let i = 0 ; i < args . length ; i ++ ) { cacheKey += args [ i ] + "" ; if ( i < args . length - 1 ) { cacheKey += "," ; } } cacheKey += ")" ; return cacheKey ; } public wrapServiceCall < T > ( cacheKey , callback ) { let result = this . getServiceCall ( cacheKey ) ; if ( typeof result === "undefined" ) { result = callback ( ) ; this . putServiceCall ( cacheKey , result ) ; } return result ; } public mergeCache ( cache ) { if ( cache ) { [ "resources" , "included" , "scripts" , "serviceCalls" ] . forEach ( ( key ) => { this . merge ( ( this as any ) [ key ] , cache [ key ] ) ; } ) ; } } public put ( path , resource , depth ? ) { if ( resource === null || typeof resource === "undefined" ) { delete this . resources [ path ] ; } else { this . resources [ path ] = { data : resource , depth : this . normalizeDepth ( depth ) } ; } } public get ( path , depth ? ) { let normalizedDepth = this . normalizeDepth ( depth ) ; let subPath = [ ] ; let resource = this . resources [ path ] ; while ( ! resource && path != null ) { let result = ResourceUtils . findAncestor ( path , 1 ) ; if ( result !== null ) { path = result . path ; subPath . splice ( 0 , 0 , result . subPath [ 0 ] ) ; resource = this . resources [ result . path ] ; } else { break ; } } if ( typeof resource === "undefined" || resource === null ) { return null ; } else if ( resource . depth < 0 ) { return this . getProperty ( resource . data , subPath ) ; } else if ( normalizedDepth < 0 ) { return null ; } else if ( subPath . length + normalizedDepth - 1 <= resource . depth ) { return this . getProperty ( resource . data , subPath ) ; } else { return null ; } } public putServiceCall ( key , serviceCall ) { this . serviceCalls [ key ] = serviceCall ; } public getServiceCall ( key ) { return this . serviceCalls [ key ] ; } public putScript ( path , script ) { this . scripts [ path ] = script ; } public getScript ( path ) { return this . scripts [ path ] ; } public putIncluded ( path , included ) { this . included [ path ] = included ; } public getIncluded ( path ) { return this . included [ path ] ; } public getFullState ( ) { return { resources : this . resources , scripts : this . scripts , included : this . included , serviceCalls : this . serviceCalls } ; } public clear ( ) { this . resources = { } ; this . scripts = { } ; this . included = { } ; this . serviceCalls = { } ; } private merge ( target , source ) { if ( source ) { Object . keys ( source ) . forEach ( ( key ) => { target [ key ] = source [ key ] ; } ) ; } } private normalizeDepth ( depth ? ) { if ( depth < 0 || depth === null || typeof depth === "undefined" ) { return - 1 ; } return depth ; } private getProperty ( data , path ) { let subData = ResourceUtils . getProperty ( data , path ) ; if ( typeof subData === "undefined" || subData === null ) { return { } ; } else { return subData ; } } }