package Ġorg . jetbrains . ex posed . dao Ċ Ċ import Ġorg . jetbrains . ex posed . dao . id . Entity ID Ċ import Ġorg . jetbrains . ex posed . dao . id . Id Table Ċ import Ġorg . jetbrains . ex posed . sql .* Ċ import Ġorg . jetbrains . ex posed . sql . transactions . transaction Scope Ċ import Ġjava . util .* Ċ Ċ val ĠTransaction . entity Cache : ĠEntity Cache Ġby Ġtransaction Scope Ġ{ ĠEntity Cache ( this ) Ġ} Ċ Ċ @ Suppress (" UN CHECK ED _ CAST ") Ċ class ĠEntity Cache ( private Ġval Ġtransaction : ĠTransaction ) Ġ{ ĊĠĠĠ Ġprivate Ġvar Ġflush ing Entities Ġ= Ġfalse ĊĠĠĠ Ġval Ġdata Ġ= ĠLinkedHashMap < Id Table <* >, ĠMutable Map < Any , ĠEntity <* >> >() ĊĠĠĠ Ġval Ġinserts Ġ= ĠLinkedHashMap < Id Table <* >, ĠMutable List < Entity <* >> >() ĊĠĠĠ Ġval Ġref err ers Ġ= ĠHashMap < Entity ID <* >, ĠMutable Map < Column <* >, ĠSized Iterable <* >> >() ĊĊĠĠĠ Ġprivate Ġfun Ġget Map ( f : ĠEntity Class < *, Ġ* >): ĠMutable Map < Any , ĠEntity <* >> Ġ= Ġget Map ( f . table ) ĊĊĠĠĠ Ġprivate Ġfun Ġget Map ( table : ĠId Table < *> ): ĠMutable Map < Any , ĠEntity <* >> Ġ= Ġdata . get Or Put ( table ) Ġ{ ĊĠĠĠĠĠĠĠ ĠLinkedHashMap () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġ< ID Ġ: ĠAny , ĠR Ġ: ĠEntity < ID >> Ġget Or Put Ref err ers ( source Id : ĠEntity ID <* >, Ġkey : ĠColumn <* >, Ġrefs : Ġ() Ġ-> ĠSized Iterable < R >): ĠSized Iterable < R > Ġ= ĊĠĠĠĠĠĠĠ Ġref err ers . get Or Put ( source Id ) Ġ{ ĠHashMap () Ġ}. get Or Put ( key ) Ġ{ ĠLazy Sized Collection ( refs ()) Ġ} Ġas ĠSized Iterable < R > ĊĊĠĠĠ Ġfun Ġ< ID Ġ: ĠComparable < ID >, ĠT Ġ: ĠEntity < ID >> Ġfind ( f : ĠEntity Class < ID , ĠT >, Ġid : ĠEntity ID < ID >): ĠT ? Ġ= Ġget Map ( f )[ id . value ] Ġas ĠT ? Ġ?: Ġinserts [ f . table ]?. first OrNull Ġ{ Ġit . id Ġ== Ġid Ġ} Ġas ? ĠT ĊĊĠĠĠ Ġfun Ġ< ID Ġ: ĠComparable < ID >, ĠT Ġ: ĠEntity < ID >> ĠfindAll ( f : ĠEntity Class < ID , ĠT >): ĠCollection < T > Ġ= Ġget Map ( f ). values Ġas ĠCollection < T > ĊĊĠĠĠ Ġfun Ġ< ID Ġ: ĠComparable < ID >, ĠT Ġ: ĠEntity < ID >> Ġstore ( f : ĠEntity Class < ID , ĠT >, Ġo : ĠT ) Ġ{ ĊĠĠĠĠĠĠĠ Ġget Map ( f )[ o . id . value ] Ġ= Ġo ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġstore ( o : ĠEntity <* >) Ġ{ ĊĠĠĠĠĠĠĠ Ġget Map ( o . klass . table )[ o . id . value ] Ġ= Ġo ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġ< ID Ġ: ĠComparable < ID >, ĠT Ġ: ĠEntity < ID >> Ġremove ( table : ĠId Table < ID >, Ġo : ĠT ) Ġ{ ĊĠĠĠĠĠĠĠ Ġget Map ( table ). remove ( o . id . value ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġ< ID Ġ: ĠComparable < ID >, ĠT Ġ: ĠEntity < ID >> Ġschedule Insert ( f : ĠEntity Class < ID , ĠT >, Ġo : ĠT ) Ġ{ ĊĠĠĠĠĠĠĠ Ġinserts . get Or Put ( f . table ) Ġ{ Ġarray ListOf () Ġ}. add ( o Ġas ĠEntity <* >) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġflush () Ġ{ ĊĠĠĠĠĠĠĠ Ġflush ( inser ts . keys Ġ+ Ġdata . keys ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Entities ( id Table : ĠId Table <* >) Ġ{ ĊĠĠĠĠĠĠĠ Ġdata [ id Table ]?. let Ġ{ Ġmap Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( map . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdated Entities Ġ= ĠHashSet < Entity <* >>() ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbatch Ġ= ĠEntity Batch Update ( map . values . first (). klass ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( _, Ġentity ) Ġin Ġmap ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( entity . flush ( batch )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( entity . klass Ġ! is ĠImmutable Entity Class < *, Ġ* >) Ġ{ Ġ" Update Ġon Ġimmutable Ġentity Ġ${ entity . java Class . simple Name } Ġ${ entity . id }" Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated Entities . add ( entity ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexecute As Part Of Entity Lifecycle Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbatch . execute ( transaction ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated Entities . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtransaction . register Change ( it . klass , Ġit . id , ĠEntity Change Type . Updated ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġflush ( tables : ĠIterable < Id Table <* >>) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( flush ing Entities ) Ġreturn ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġflush ing Entities Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinserted Tables Ġ= Ġinserts . keys ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdate Before Insert Ġ= ĠSchema Utils . sort Tables By References ( inserted Tables ). filter Is Instance < Id Table <* >>() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Before Insert . forEach (:: update Entities ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠSchema Utils . sort Tables By References ( tables ). filter Is Instance < Id Table <* >> (). forEach (:: flush Inser ts ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdate The Rest Tables Ġ= Ġtables Ġ- Ġupdate Before Insert ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( t Ġin Ġupdate The Rest Tables ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Entities ( t ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( inserted Tables . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremove Tables Ref err ers ( inserted Tables ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġflush ing Entities Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinternal Ġfun Ġremove Tables Ref err ers ( inserted Tables : ĠCollection < Table >) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġinserted Tables Set Ġ= Ġinserted Tables . toSet () ĊĠĠĠĠĠĠĠ Ġval Ġtables ToRemove : ĠList < Table > Ġ= Ġref err ers . values . flatMap To ( HashSet ()) Ġ{ Ġit . keys . map Ġ{ Ġit . table Ġ} Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġtable Ġ-> Ġtable . columns . any Ġ{ Ġc Ġ-> Ġc . ref ere e ?. table Ġin Ġinserted Tables Set Ġ} Ġ} Ġ+ Ġinserted Tables Set ĊĊĠĠĠĠĠĠĠ Ġref err ers . map NotNull Ġ{ Ġ( entityId , Ġentity Ref err ers ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentity Ref err ers . filter Keys Ġ{ Ġit . table Ġin Ġtables ToRemove Ġ}. keys . forEach Ġ{ Ġentity Ref err ers . remove ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentity Id . take If Ġ{ Ġentity Ref err ers . isEmpty () Ġ} ĊĠĠĠĠĠĠĠ Ġ}. forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġref err ers . remove ( it ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinternal Ġfun Ġflush Inser ts ( table : ĠId Table <* >) Ġ{ ĊĠĠĠĠĠĠĠ Ġinserts . remove ( table )?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġto Flush : ĠList < Entity <* >> Ġ= Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdo Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpartition Ġ= Ġto Flush . partition Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . write Values . none Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġ( key , Ġvalue ) Ġ= Ġit ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkey . ref ere e Ġ== Ġtable . id Ġ&& Ġvalue Ġis ĠEntity ID < *> Ġ&& Ġvalue ._ value Ġ== Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġto Flush Ġ= Ġpartition . first ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġids Ġ= Ġexecute As Part Of Entity Lifecycle Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtable . batch Insert ( to Flush ) Ġ{ Ġentry Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( c , Ġv ) Ġin Ġentry . write Values ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis [ c ] Ġ= Ġv ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( entry , Ġgen Values ) Ġin Ġto Flush . zip ( ids )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( entry . id ._ value Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġid Ġ= Ġgen Values [ table . id ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . id ._ value Ġ= Ġid ._ value ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . write Values [ entry . klass . table . id Ġas ĠColumn < Any ?> ] Ġ= Ġid ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgen Values . field Index . keys . forEach Ġ{ Ġkey Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . write Values [ key Ġas ĠColumn < Any ?> ] Ġ= Ġgen Values [ key ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . store Written Values () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstore ( entry ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtransaction . register Change ( entry . klass , Ġentry . id , ĠEntity Change Type . Created ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġto Flush Ġ= Ġpartition . second ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġwhile Ġ( to Flush . isNotEmpty ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġtransaction . alert Sub scribers () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġclear Ref err ers Cache () Ġ{ ĊĠĠĠĠĠĠĠ Ġref err ers . clear () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĊĠĠĠĠĠĠĠ Ġfun Ġinvalidate Global Caches ( created : ĠList < Entity <* >>) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcreated . as Sequence (). map NotNull Ġ{ Ġit . klass Ġas ? ĠImmutable Cached Entity Class < *, Ġ*> Ġ}. distinct (). forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . expire Cache () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun ĠTransaction . flush Cache (): ĠList < Entity <* >> Ġ{ ĊĠĠĠ Ġwith ( entity Cache ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnew Entities Ġ= Ġinserts . flatMap Ġ{ Ġit . value Ġ} ĊĠĠĠĠĠĠĠ Ġflush () ĊĠĠĠĠĠĠĠ Ġreturn Ġnew Entities ĊĠĠĠ Ġ} Ċ } Ċ