import { EntityChangeEvent } from ".." ; import { FieldMetadata } from "../meta/impl/FieldMetadata" ; import { TypeMetadata } from "../meta/impl/TypeMetdata" ; import { VariableArgs } from "../state/impl/Args" ; import { compare } from "../state/impl/util" ; import { GraphObject , GraphType } from "../state/Monitor" ; import { EntityKey } from "./EntityEvent" ; import { EntityManager , Garbage } from "./EntityManager" ; import { Pagination } from "./QueryArgs" ; import { Record } from "./Record" ; import { RecordRef } from "./RecordRef" ; export class RecordManager { private superManager ? : RecordManager ; private recordMap = new Map < any , Record > ( ) ; constructor ( readonly entityManager , readonly type ) { } initializeOtherManagers ( ) { if ( this . type . superType !== undefined ) { this . superManager = this . entityManager . recordManager ( this . type . superType . name ) ; } } findRefById ( id ) { const record = this . recordMap . get ( id ) ; if ( record === undefined ) { return undefined ; } return record . isDeleted ? { } : { value : record } ; } saveId ( id , runtimeType ) { let record = this . recordMap . get ( id ) ; if ( record !== undefined ) { if ( record . runtimeType === runtimeType ) { if ( record . undelete ( ) ) { this . entityManager . modificationContext . insert ( record ) ; } return record ; } this . entityManager . delete ( record . runtimeType . name , record . id ) ; } record = this . insertId ( id , runtimeType ) ; this . entityManager . modificationContext . insert ( record ) ; return record ; } private insertId ( id , runtimeType , deleted = false ) { const superRecord = this . superManager ?. insertId ( id , runtimeType ) ; const record = new Record ( superRecord , this . type , runtimeType , id , deleted ) ; this . recordMap . set ( id , record ) ; return record ; } delete ( id ) { let record = this . recordMap . get ( id ) ; if ( record !== undefined ) { this . entityManager . modificationContext . delete ( record ) ; record . delete ( this . entityManager ) ; } else { this . insertId ( id , this . type , true ) ; } this . superManager ?. delete ( id ) ; } evict ( id , key ? ) { if ( key === undefined ) { this . evictObject ( id ) ; } else { const fieldName = typeof key === "string" ? key : key . name ; const variables = typeof key === "string" ? undefined : key . variables ; if ( ! this . evictField ( id , fieldName , variables ) ) { throw new Error ( `Illegal evicted field name "${ fieldName }"` ) ; } } } private evictObject ( id ) { const record = this . recordMap . get ( id ) ; if ( record !== undefined ) { this . entityManager . modificationContext . evict ( record ) ; this . recordMap . delete ( id ) ; record . dispose ( this . entityManager ) ; } this . superManager ?. evictObject ( id ) ; } private evictField ( id , fieldName , variables ? ) { const record = this . recordMap . get ( id ) ; if ( record === undefined ) { return true ; } const field = record . staticType . declaredFieldMap . get ( fieldName ) ; if ( field !== undefined ) { record . evict ( this . entityManager , field , VariableArgs . of ( variables ) ) ; return true ; } return this . superManager ?. evictField ( id , fieldName , variables ) === true ; } forEach ( visitor ) { for ( const [ , record ] of this . recordMap ) { if ( visitor ( record ) === false ) { break ; } } } set ( id , runtimeType , field , args , value , pagination ? ) { const record = this . saveId ( id , runtimeType ) ; record . set ( this . entityManager , field , args , value , pagination ) ; } refresh ( field , e ) { for ( const record of this . recordMap . values ( ) ) { if ( ! record . isDeleted ) { record . refreshByChangeEvent ( this . entityManager , field , e ) ; } } } collectGarbages ( output ) { for ( const record of this . recordMap . values ( ) ) { if ( record . staticType === record . runtimeType ) { record . collectGarbages ( output ) ; } } } monitor ( ) { const objects = [ ] ; for ( const record of this . recordMap . values ( ) ) { if ( ! record . isDeleted ) { objects . push ( record . monitor ( ) ) ; } } if ( objects . length === 0 ) { return undefined ; } objects . sort ( ( a , b ) => compare ( a , b , "id" ) ) ; const type = { name : this . type . name , objects } ; return type ; } }