/* - Ċ Ġ* Ġ================================================= ======== Begin License Ċ Ġ* ĠProject or Ċ Ġ* Ġ. Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 8 ĠHi P ĠProperty Ċ Ġ* Ġ. Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* ĠĊ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* ĠĊ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ* Ġ================================================= ========== End License Ċ Ġ*/ Ċ package Ġcom . hip . project or Ċ Ċ import Ġorg . reactiv est ream s . Publisher Ċ import Ġreactor . core . publisher . Direct Processor Ċ import Ġreactor . core . publisher . Flux Ċ import Ġkotlin . reflect . K Class Ċ import Ġkotlin . reflect . full . is Super class Of Ċ import Ġkotlin . reflect . jvm . reflect ĊĊ Ċ /** Ċ Ġ* ĠDefines Ġa Ġset Ġof Ġevent Ġsources Ġwhich Ġwill Ġprovide Ġdata Ġto Ġa Ġproject or . Ċ Ġ* Ċ Ġ* ĠThe Ġintent Ġis Ġthat Ġproject Specs Ġare Ġshare able , Ġat Ġleast Ġas Ġbase Ġre cip ies , Ġwhich Ċ Ġ* Ġcan Ġthen Ġbe Ġfurther Ġcustomized Ġas Ġneeds Ġdict ate . Ċ Ġ*/ Ċ class ĠProject or Spec < TEntity , ĠID > Ġprivate Ġconstructor ( val Ġevent Sources : ĠList < EventSource < Any , ĠT Entity , ĠID >>) Ġ{ ĊĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠ Ġfun Ġ< TEntity , ĠID > Ġnew Spec (): ĠProject or Spec < TEntity , ĠID > Ġ= ĠProject or Spec ( emptyList ()) ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġ< T Event > Ġadd EventSource ( event Source : ĠFlux < T Event >, Ġkey Extractor : ĠKey Extractor < T Event , ĠID >, Ġmut ator : ĠMut ator < TEntity , ĠT Event >): ĠProject or Spec < TEntity , ĠID > Ġ{ ĊĠĠĠĠĠ Ġreturn Ġadd EventSource ( EventSource ( event Source , Ġkey Extractor , Ġmut ator )) ĊĠĠ Ġ} ĊĊĠĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") ĊĠĠ Ġfun Ġ< E > Ġadd EventSource ( event Source : ĠEvent Source < E , ĠT Entity , ĠID >): ĠProject or Spec < TEntity , ĠID > Ġ{ ĊĠĠĠĠĠ Ġreturn ĠProject or Spec (( event Sources Ġ+ Ġevent Source ) Ġas ĠList < EventSource < Any , ĠT Entity , ĠID >>) ĊĠĠ Ġ} ĊĊĠĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") ĊĠĠ Ġfun Ġ< E Ġ: ĠAny > Ġfilter ( k Class : ĠK Class < E >, Ġpredicate : Ġ( E ) Ġ-> ĠBoolean ): ĠProject or Spec < TEntity , ĠID > Ġ{ ĊĠĠĠĠĠ Ġval Ġupdated Event Sources Ġ= Ġthis . event Sources . map Ġ{ ĊĊĠĠĠĠĠĠĠĠ Ġval Ġclassifier Ġ= Ġit . key Extractor . reflect () !!. parameters [ 0 ]. type . classifier Ġas ĠK Class < *> ĊĊĠĠĠĠĠĠĠĠ Ġif Ġ( k Class . is Super class Of ( classifier )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ( it Ġas ĠEvent Source < E , ĠT Entity , ĠID >). filter ( predicate ) ĊĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit ĊĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} Ġas ĠList < EventSource < Any , ĠT Entity , ĠID >> ĊĠĠĠĠĠ Ġreturn ĠProject or Spec ( updated Event Sources ) ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġproject or (): ĠProject or < TEntity , ĠID > Ġ= ĠProject or ( this ) Ċ } Ċ Ċ data Ġclass ĠProject ed Mutation Event < TEntity , ĠID >( ĊĠĠ Ġval Ġid : ĠID , ĊĠĠ Ġval Ġprevious State : ĠT Entity ?, ĊĠĠ Ġval Ġcurrent State : ĠT Entity ?, ĊĠĠ Ġval Ġtrigger : ĠAny ? Ċ ) Ġ{ ĊĠĠ Ġenum Ġclass ĠOperation Ġ{ ĊĠĠĠĠĠ ĠAD DED , RE MOVED , UPDATED ĊĠĠ Ġ} ĊĠĠ Ġval Ġco ale sc ed State : ĠT Entity Ġ= Ġcurrent State Ġ?: Ġprevious State Ġ?: ĊĠĠĠĠĠ Ġerror (" Ne ither Ġcurrent Ġstate Ġor Ġprevious Ġstate Ġis Ġpopulated Ġ- Ġthis Ġsh oul nd 't Ġhappen ") ĊĠĠ Ġval Ġoperation : Operation Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠ Ġprevious State Ġ== Ġnull Ġ&& Ġcurrent State Ġ!= Ġnull Ġ-> ĠOperation . AD DED ĊĠĠĠĠĠ Ġprevious State Ġ!= Ġnull Ġ&& Ġcurrent State Ġ== Ġnull Ġ-> ĠOperation . RE MOVED ĊĠĠĠĠĠ Ġprevious State Ġ!= Ġnull Ġ&& Ġcurrent State Ġ!= Ġnull Ġ-> ĠOperation . UPDATED ĊĠĠĠĠĠ Ġelse Ġ-> Ġerror (" Unhandled , Ġbut Ġthis Ġshouldn 't Ġhappen ") ĊĠĠ Ġ} Ċ Ċ } Ċ Ċ object ĠState Of The World Marker Ċ Ċ /** Ċ Ġ* ĠG ives Ġa Ġrepository Ġtype Ġapi Ġto Ġa Ġstream Ġof Ġdata . Ċ Ġ* ĠUses Ġa ĠProject or Spec Ġto Ġdefine Ġhow Ġmaterial ized Ġviews Ġare Ġconstructed . Ċ Ġ* ĠProject ors Ġthemselves Ġmay Ġalso Ġbe Ġinputs Ġinto Ġother Ġproject ors Ċ Ġ*/ Ċ open Ġclass ĠProject or < TEntity , ĠID >( spec : ĠProject or Spec < TEntity , ĠID >) Ġ{ ĊĠĠ Ġprivate Ġval Ġdata Table Ġ= Ġmutable Map Of < ID , ĠT Entity >() ĊĠĠ Ġprivate Ġval Ġevent Stream Processor : ĠDirect Processor < Project ed Mutation Event < TEntity , ĠID >> Ġ= ĠDirect Processor . create () ĊĠĠ Ġprivate Ġval Ġevent Stream Sink Ġ= Ġevent Stream Processor . sink () ĊĊĠĠ Ġval Ġevent Stream : ĠFlux < Project ed Mutation Event < TEntity , ĠID >> ĊĠĠĠĠĠ Ġget () Ġ= Ġevent Stream Processor ĊĊĊĠĠ Ġinit Ġ{ ĊĠĠĠĠĠ Ġspec . event Sources . map Ġ{ Ġ( event Source , Ġkey Extractor , Ġmut ator ) Ġ-> ĊĠĠĠĠĠĠĠĠ Ġevent Source . subscribe Ġ{ Ġevent Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( event Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġkey Ġ= Ġkey Extractor ( event ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġoriginal State Ġ= Ġdata Table [ key ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdated State Ġ= Ġmut ator ( original State , Ġevent ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( updated State Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . dataTable [ key ] Ġ= Ġupdated State ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . dataTable . remove ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( original State Ġ!= Ġnull Ġ|| Ġupdated State Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġevent Stream Sink . next ( Project ed Mutation Event ( key , Ġoriginal State , Ġupdated State , Ġevent )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} ĊĊĊĠĠ Ġfun Ġget ( id : ĠID ): ĠT Entity Ġ{ ĊĠĠĠĠĠ Ġreturn Ġdata Table [ id ] Ġ?: Ġthrow ĠNoSuch ElementException (" No Ġentity Ġwith Ġid Ġof Ġ$ id ") ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġobserve ( predicate : Ġ( TEntity ) Ġ-> ĠBoolean ): ĠFlux < QueryResult < TEntity >> Ġ{ ĊĠĠĠĠĠ Ġreturn Ġevent Stream ĊĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġmutation Event Ġ-> Ġmutation Event . currentState Ġ!= Ġnull Ġ&& Ġpredicate ( mutation Event . currentState ) Ġ} ĊĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġmutation Event Ġ-> ĠQuery Result ( mutation Event . currentState !! , Ġmutation Event . trigger !! ) Ġ} ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġquery And Ob serve ( predicate : Ġ( TEntity ) Ġ-> ĠBoolean ): ĠFlux < QueryResult < TEntity >> Ġ{ ĊĠĠĠĠĠ Ġreturn ĠFlux . from Iterable ( query ( predicate )) ĊĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġentity Ġ-> ĠQuery Result ( entity , ĠState Of The World Marker ) Ġ} ĊĠĠĠĠĠĠĠĠ Ġ. concat With ( observe ( predicate )) ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġquery ( predicate : Ġ( TEntity ) Ġ-> ĠBoolean ): ĠList < TEntity > Ġ{ ĊĠĠĠĠĠ Ġreturn Ġthis . getAll (). filter ( predicate ) ĊĠĠ Ġ} ĊĊĠĠ Ġfun ĠgetAll (): ĠList < TEntity > Ġ{ ĊĠĠĠĠĠ Ġreturn Ġdata Table . values . toList () ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġkeys (): ĠSet < ID > Ġ{ ĊĠĠĠĠĠ Ġreturn Ġdata Table . keys . toSet () ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġcontains ( entityId : ĠID ): ĠBoolean Ġ{ ĊĠĠĠĠĠ Ġreturn Ġdata Table . keys . contains ( entityId ) ĊĠĠ Ġ} ĊĊĊĠĠ Ġval Ġsize : ĠInt ĊĠĠĠĠĠ Ġget () Ġ= Ġdata Table . size ĊĊĠĠ Ġval ĠisEmpty ĊĠĠĠĠĠ Ġget () Ġ= Ġdata Table . isEmpty () ĊĊĠĠ Ġval Ġis NotEmpty ĊĠĠĠĠĠ Ġget () Ġ= Ġdata Table . isNotEmpty () ĊĊ Ċ } ĊĊ Ċ /** Ċ Ġ* ĠA Ġfunction Ġwhich Ġreceives Ġan Ġexisting Ġstate Ġof Ġan Ġentity Ċ Ġ* Ġ( if Ġpresent ) Ġand Ġa Ġmut ating Ġevent , Ġand Ġreturns Ġthe Ġnew Ġupdated Ġstate Ġ( or Ġnull , Ċ Ġ* Ġto Ġindicate Ġthe Ġentity Ġshould Ġbe Ġdeleted ) Ċ Ġ*/ Ċ type alias ĠMut ator < TEntity , ĠT Event > Ġ= Ġ( TEntity ?, ĠT Event ) Ġ-> ĠT Entity ? Ċ Ċ /** Ċ Ġ* ĠA Ġfunction Ġwhich Ġreceives Ġan Ġevent , Ġand Ġreturns Ġthe Ġentity Ġid Ġthat Ċ Ġ* Ġthe Ġevent Ġrel ates Ġto Ċ Ġ*/ Ċ type alias ĠKey Extractor < T Event , ĠID > Ġ= Ġ( T Event ) Ġ-> ĠID Ċ Ċ /** Ċ Ġ* ĠProvides Ġan Ġinput Ġof Ġevents , Ġalong Ġwith Ġinstructions Ġfor Ġhow Ġthe Ġproject or Ġshould Ċ Ġ* Ġdecide Ġwhich Ġentity Ġthe Ġevent Ġrel ates Ġto Ġ( the ĠKey Extractor ), Ġand Ġhow Ġthe Ġevent Ġshould Ċ Ġ* Ġchange Ġthe Ġstate Ġof Ġthe Ġentity Ġ( the Ġmut ator ) Ċ Ġ*/ Ċ data Ġclass ĠEvent Source < T Event , ĠT Entity , ĠID >( val Ġsource : ĠFlux < T Event >, Ġval Ġkey Extractor : ĠKey Extractor < T Event , ĠID >, Ġval Ġmut ator : ĠMut ator < TEntity , ĠT Event >) Ġ: ĠPublisher < T Event > Ġby Ġsource Ġ{ ĊĠĠ Ġfun Ġfilter ( predicate : Ġ( T Event ) Ġ-> ĠBoolean ): ĠEvent Source < T Event , ĠT Entity , ĠID > Ġ{ ĊĠĠĠĠĠ Ġreturn ĠEvent Source ( source . filter ( predicate ), Ġkey Extractor , Ġmut ator ) ĊĠĠ Ġ} Ċ } Ċ Ċ data Ġclass ĠQuery Result < out ĠT Entity >( val Ġentity : ĠT Entity , Ġval Ġtrigger : ĠAny ) ĊĊ Ċ fun Ġ< TEntity , ĠID > ĠFlux < Project ed Mutation Event < TEntity , ĠID >> . event Source (): ĠEvent Source < Project ed Mutation Event < TEntity , ĠID >, ĠT Entity , ĠID > Ġ{ ĊĠĠ Ġreturn ĠEvent Source ( source Ġ= Ġthis , ĊĠĠĠĠĠ Ġkey Extractor Ġ= Ġ{ Ġmutation Event Ġ-> Ġmutation Event . id Ġ}, ĊĠĠĠĠĠ Ġmut ator Ġ= Ġ{ Ġ_, Ġevent Ġ-> Ġevent . currentState Ġ} ĊĠĠ Ġ) Ċ } Ċ Ċ fun Ġ< TEntity , ĠID > ĠFlux < Project ed Mutation Event < TEntity , ĠID >> . project or (): ĠProject or < TEntity , ĠID > Ġ{ ĊĠĠ Ġreturn ĠProject or ( Project or Spec . new Spec < TEntity , ĠID >() ĊĠĠĠĠĠ Ġ. add EventSource ( this . event Source ())) Ċ } ĊĊ Ċ fun Ġ< T Event , ĠT Entity , ĠT Id > ĠFlux < T Event >. to EventSource ( key Extractor : ĠKey Extractor < T Event , ĠT Id >, Ġmut ator : ĠMut ator < TEntity , ĠT Event >): ĠEvent Source < T Event , ĠT Entity , ĠT Id > Ġ{ ĊĠĠ Ġreturn ĠEvent Source ( this , Ġkey Extractor , Ġmut ator ) Ċ } Ċ Ċ fun Ġ< T Event , ĠT Entity , ĠT Id > ĠEvent Source < T Event , ĠT Entity , ĠT Id >. to Project or Spec (): ĠProject or Spec < TEntity , ĠT Id > Ġ{ ĊĠĠ Ġreturn ĠProject or Spec . new Spec < TEntity , ĠT Id >() ĊĠĠĠĠĠ Ġ. add EventSource ( this ) Ċ } Ċ