/* - Ċ Ġ* Ġ================================================= ======== Begin License Ċ Ġ* ĠS auc y Ċ Ġ* Ġ. Ċ Ġ* Ġ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 . sa uc y Ċ Ċ import Ġcom . google . common . collect . ArrayList Multimap Ċ import Ġcom . google . common . collect . Multimap Ċ import Ġcom . hip . sa uc y . utils . log Ċ import Ġorg . f unktion ale . either . Either Ċ import Ġorg . f unktion ale . either . merge Ċ import Ġreactor . core . publisher . Flux Ċ import Ġreactor . core . publisher . Mono Ċ import Ġjava . lang . reflect . Method Ċ import Ġkotlin . reflect . K Type Ċ import Ġkotlin . reflect . full . find Annotation Ċ import Ġkotlin . reflect . full . is Subtype Of Ċ import Ġkotlin . reflect . full . member Functions Ċ import Ġkotlin . reflect . full . star Project ed Type Ċ import Ġkotlin . reflect . jvm . java Method Ċ Ċ class ĠEvent Router Ġinternal Ġconstructor ( ĊĠĠ Ġprivate Ġval Ġhandlers : ĠMult imap < Class <* >, ĠEventHandler Invoker >, ĊĠĠ Ġval Ġevent Store : ĠEvent Store , ĊĠĠ Ġreplay On Startup : ĠBoolean Ġ= Ġfalse Ċ ) Ġ: ĠMessage Gateway Ġ{ ĊĊĠĠ Ġprivate Ġvar Ġis Replay ing Ġ= Ġfalse ĊĠĠ Ġprivate Ġval Ġevent Factory Ġ= ĠEvent Factory () ĊĊĠĠ Ġprivate Ġvar Ġhas Dis patched Ġ= Ġfalse ĊĊĠĠ Ġinit Ġ{ ĊĠĠĠĠĠ Ġif Ġ( replay On Startup ) ĊĠĠĠĠĠĠĠĠ Ġreplay () ĊĠĠ Ġ} ĊĊĠĠ Ġ/** ĊĠĠĠ Ġ* ĠRe play s Ġthe Ġmessages Ġstored Ġin Ġthe Ġevent Ġstore . ĊĠĠĠ Ġ* ĠIn Ġorder Ġto Ġpreserve Ġintegrity , Ġreplay ing Ġis Ġonly ĊĠĠĠ Ġ* Ġallowed Ġonce , Ġand Ġonly Ġprior Ġto Ġdispatch ing Ġother Ġevents , ĊĠĠĠ Ġ* Ġso Ġshould Ġbe Ġcalled Ġon Ġstartup ĊĠĠĠ Ġ*/ ĊĠĠ Ġfun Ġreplay () Ġ{ ĊĠĠĠĠĠ Ġif Ġ( has Dis patched ) Ġerror (" Cannot Ġreplay Ġonce Ġa Ġmessage Ġhas Ġbeen Ġdis patched ") ĊĊĠĠĠĠĠ Ġis Replay ing Ġ= Ġtrue ĊĠĠĠĠĠ Ġlog (). info (" Starting Ġto Ġreplay Ġevent Ġstore ") ĊĠĠĠĠĠ Ġevent Store . replay () ĊĠĠĠĠĠĠĠĠ Ġ. subscribe Ġ{ Ġevent Ġ-> Ġdispatch ( event ). subscribe () Ġ} ĊĠĠĠĠĠ Ġlog (). info (" Replay Ġcomplete ") ĊĠĠĠĠĠ Ġis Replay ing Ġ= Ġfalse ĊĠĠ Ġ} ĊĊĠĠ Ġprivate Ġfun ĠK Type . matches Instance ( instance : ĠAny ): ĠBoolean Ġ{ ĊĠĠĠĠĠ Ġreturn Ġinstance :: class . star Project ed Type Ġ== Ġthis ĊĠĠ Ġ} ĊĊĠĠ Ġprivate Ġfun ĠIterable < K Type >. matches Instance ( instance : ĠAny ): ĠBoolean Ġ{ ĊĠĠĠĠĠ Ġreturn Ġthis . any Ġ{ Ġit . matches Instance ( instance ) Ġ} ĊĠĠ Ġ} ĊĊĠĠ Ġoverride Ġfun Ġ< T Failure , ĠT Success > Ġdispatch Command Event ( command Event : ĠCommand Event < T Failure , ĠT Success >): ĠMono < Either < T Failure , ĠT Success >> Ġ{ ĊĠĠĠĠĠ Ġval Ġcommand EventType Ġ= Ġcommand Event :: class ĊĠĠĠĠĠĠĠĠ Ġ. sup ert ypes ĊĠĠĠĠĠĠĠĠ Ġ. first Ġ{ Ġit . is Subtype Of ( Command Event :: class . star Project ed Type ) Ġ} ĊĊĊĠĠĠĠĠ Ġval Ġfailure Type Ġ= Ġcommand EventType . arguments [ 0 ]. type !! ĊĠĠĠĠĠ Ġval Ġsuccess Type Ġ= Ġcommand EventType . arguments [ 1 ]. type !! ĊĊĠĠĠĠĠ Ġ// ĠDispatch Ġthe Ġcommand Ġmessage , Ġand Ġwatch Ġthe Ġsubsequent ĊĠĠĠĠĠ Ġ// Ġevent Ġstream . ĊĠĠĠĠĠ Ġ// ĠWe 're Ġlooking Ġfor Ġan Ġevent Ġthat Ġis Ġeither Ġour Ġsuccess , Ġor Ġour ĊĠĠĠĠĠ Ġ// Ġfailure Ġmessage . ĊĠĠĠĠĠ Ġ// ĠNote Ġ- Ġit Ġcould Ġbe Ġpresented Ġas ĠT Success , ĠT Failure Ġ* or * ĠEither < T Failure , T Success > ĊĠĠĠĠĠ Ġ// ĠThe Ġfirst Ġtime Ġthat Ġoccurs , Ġwe Ġcapture Ġit Ġand Ġreturn Ġit Ġout ĊĠĠĠĠĠ Ġ// Ġof Ġthe ĠMono Ġas Ġthe Ġresult Ġof Ġthe Ġcommand . ĊĠĠĠĠĠ Ġreturn Ġthis . dispatch ( command Event ) ĊĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġis Success Or Failure Message ( failure Type , Ġsuccess Type , Ġit ) Ġ} ĊĠĠĠĠĠĠĠĠ Ġ. collect List () ĊĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġmessages Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmessage Ġ= Ġextract First Message ( messages ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrap Message In Either < T Failure , ĠT Success >( failure Type , Ġsuccess Type , Ġmessage ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠHandle Ġany Ġerrors Ġthat Ġwere Ġthrown ĊĠĠĠĠĠĠĠĠ Ġ}. do OnError Ġ{ Ġwrap Error In Either < T Failure >( failure Type , Ġit ) Ġ} ĊĠĠ Ġ} ĊĊĠĠ Ġprivate Ġfun Ġ< T Failure , ĠT Success > Ġwrap Message In Either ( failure Type : ĠK Type , Ġsuccess Type : ĠK Type , Ġmessage : ĠAny ): ĠEither < T Failure , ĠT Success > Ġ{ ĊĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠ Ġfailure Type . matches Instance ( message ) Ġ-> ĠEither . left ( message Ġas ĠT Failure ) ĊĠĠĠĠĠĠĠĠ Ġsuccess Type . matches Instance ( message ) Ġ-> ĠEither . right ( message Ġas ĠT Success ) ĊĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠIllegalStateException (" The Ġmessage Ġwas Ġneither ĠT Success Ġnor ĠT Failure , Ġdespite Ġprevious Ġfilter Ġpassing . Ġ ĠShould n 't Ġhappen ") ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} ĊĊĠĠ Ġprivate Ġfun Ġ< T Failure > Ġwrap Error In Either ( failure Type : ĠK Type , Ġerror : ĠThrowable ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( failure Type . matches Instance ( error )) Ġ{ ĊĠĠĠĠĠĠĠĠ ĠEither . left ( error Ġas ĠT Failure ) ĊĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠ Ġthrow Ġerror ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} ĊĊĠĠ Ġprivate Ġfun Ġextract First Message ( messages : ĠMutable List < Any >): ĠAny Ġ{ ĊĠĠĠĠĠ Ġreturn Ġmessages . first (). let Ġ{ Ġfirst Ġ-> ĊĠĠĠĠĠĠĠĠ Ġwhen Ġ( first ) Ġ{ ĊĠĠĠĠĠĠĠĠ Ġ// ĠIf Ġwe Ġgot Ġan Ġeither , Ġget Ġthe Ġen closing Ġtype Ġ( left Ġor Ġright ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠEither < *, Ġ*> Ġ-> Ġfirst . merge () !! ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġfirst ĊĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} ĊĊĠĠ Ġprivate Ġfun Ġis Success Or Failure Message ( failure Type : ĠK Type , Ġsuccess Type : ĠK Type , Ġmess as ge : ĠAny ): ĠBoolean Ġ{ ĊĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠ ĠlistOf ( failure Type , Ġsuccess Type ). matches Instance ( mess as ge ) Ġ-> Ġtrue ĊĠĠĠĠĠĠĠĠ Ġmess as ge Ġis ĠEither < *, Ġ*> Ġ-> ĠlistOf ( failure Type , Ġsuccess Type ). matches Instance ( mess as ge . merge () Ġ?: ĠUnit ) ĊĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġfalse ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} ĊĊĊĠĠ Ġoverride Ġfun Ġ< T Ġ: ĠDispatch able > Ġsubmit ( dispatch able : ĠT ): ĠPair < Mono < Event < T >>, ĠFlux < Any >> Ġ{ ĊĠĠĠĠĠ Ġ// ĠIf Ġthe Ġpayload Ġwe 've Ġbeen Ġgiven Ġisn 't Ġan Ġactual Ġevent , Ġwrap ĊĠĠĠĠĠ Ġ// Ġit Ġto Ġmake Ġit Ġone ĊĠĠĠĠĠ Ġval Ġevent Ġ= Ġwrap To Event ( dispatch able ) ĊĠĠĠĠĠ Ġval Ġfuture Commit ted Event Ġ= Ġwrite Event ( event ) ĊĠĠĠĠĠ Ġval Ġflux Ġ= ĠFlux . create < Any > Ġ{ Ġsink Ġ-> ĊĊĠĠĠĠĠĠĠĠ Ġfuture Commit ted Event . subscribe Ġ{ Ġcommitted Event Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog (). debug (" Publishing Ġevent Ġfor Ġ${ committed Event . simple Name }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠNote : Ġthe Ġpayload Ġmay Ġbe Ġthe Ġoriginal Ġpayload Ġwe Ġwere Ġprovided , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġor Ġthe Ġun wrapped Ġvalue Ġif Ġit 's Ġbeen Ġwrapped . ĊĠĠĠĠĠĠĠĠĠĠĠ ĠgetMessage Types ( committed Event . payload :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. flatMap Ġ{ Ġmessage Type Ġ-> Ġhandlers [ message Type ] Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. distinct () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġhandler Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (). debug (" Message Ġ${ dispatch able :: class . java . simple Name } Ġmatched Ġhandler Ġ${ handler . name }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġhandler . invoke ( committed Event . payload ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (). debug (" Message Ġ${ dispatch able :: class . java . simple Name } Ġreturned Ġresponse Ġof Ġ${ result :: class . java } Ġfrom Ġ${ handler . name } Ġ-- Ġrouting ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsink . next ( result ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsink . complete () ĊĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠ Ġ// ĠCall Ġcache Ġso Ġthat Ġas Ġnew Ġsubscribers Ġjoin , Ġthey Ġare ĊĠĠĠĠĠĠĠĠ Ġ// Ġreplay ed Ġprevious Ġevents , Ġrather Ġthan Ġtriggering Ġthe Ġflux Ġto Ġrestart ĊĠĠĠĠĠ Ġ}. cache () ĊĊĊĠĠĠĠĠ Ġif Ġ(! is Replay ing ) Ġ{ Ċ // ĠĠĠĠĠĠ ĠResponse s Ġare Ġre - dis patched ĊĠĠĠĠĠĠĠĠ Ġflux . subscribe Ġ{ Ġnext Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( next ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠNull Or Void Response Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ// ĠDo Ġnothing ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠFlux < *> Ġ-> Ġnext . subscribe Ġ{ Ġre dispatchEvent Members ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠMono < *> Ġ-> Ġnext . subscribe Ġ{ Ġre dispatchEvent Members ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠIterable < *> Ġ-> Ġnext . filter NotNull (). forEach Ġ{ Ġre dispatchEvent Members ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠDispatch able Ġ-> Ġdispatch ( next ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġlog (). warn (" Ign oring Ġresponse Ġof Ġtype Ġ${ next . java Class } Ġas Ġit 's Ġnot ĠDispatch able ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġhas Dis patched Ġ= Ġtrue ĊĠĠĠĠĠ Ġreturn Ġfuture Commit ted Event Ġto Ġflux ĊĠĠ Ġ} ĊĊĠĠ Ġprivate Ġfun Ġ< T Ġ: ĠDispatch able > Ġwrap To Event ( dispatch able : ĠT ): ĠEvent < T > Ġ{ ĊĠĠĠĠĠ Ġreturn Ġif Ġ( dispatch able Ġis ĠEvent <* >) Ġ{ ĊĠĠĠĠĠĠĠĠ Ġdispatch able Ġas ĠEvent < T > ĊĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠ Ġevent Factory . event Of ( dispatch able ) ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} ĊĊĠĠ Ġprivate Ġfun Ġre dispatchEvent Members ( member : ĠAny ) Ġ{ ĊĠĠĠĠĠ Ġwhen Ġ( member ) Ġ{ ĊĠĠĠĠĠĠĠĠ Ġis ĠDispatch able Ġ-> Ġthis . dispatch ( member ) ĊĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġlog (). warn (" Ign oring Ġresponse Ġmember Ġof Ġtype Ġ${ member . java Class } Ġas Ġit 's Ġnot Ġan Ġevent ") ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} ĊĊĊĠĠ Ġprivate Ġfun Ġ< T Ġ: ĠAny > Ġwrite Event ( event : ĠEvent < T >): ĠMono < Event < out ĠT >> Ġ{ ĊĠĠĠĠĠ Ġreturn Ġif Ġ( is Replay ing ) Ġ{ ĊĠĠĠĠĠĠĠĠ ĠMono . just ( event ) ĊĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠ Ġevent Store . store ( event ) ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} ĊĊĠĠ Ġprivate Ġfun ĠgetMessage Types ( clazz : ĠClass < *> ): ĠList < Class <* >> Ġ{ ĊĠĠĠĠĠ Ġ// ĠNull Or Void Response Ġis Ġa Ġspecial Ġtype , Ġwhich Ġcannot Ġmatch Ġany Ġmessages ĊĠĠĠĠĠ Ġif Ġ( clazz Ġ== ĠNull Or Void Response :: class . java ) Ġreturn Ġempty List () ĊĊĠĠĠĠĠ Ġval Ġresult Ġ= Ġmutable ListOf < Class <* >>() ĊĠĠĠĠĠ Ġresult . add ( clazz ) ĊĠĠĠĠĠ Ġresult . addAll ( clazz . interfaces ) ĊĠĠĠĠĠ Ġif Ġ( clazz . super class Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠ Ġresult . addAll ( getMessage Types ( clazz . super class )) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġreturn Ġresult ĊĠĠ Ġ} ĊĊĊĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠ Ġfun Ġwith Members ( var arg Ġtypes Or Instances : ĠAny ): ĠEvent Router Builder Ġ{ ĊĠĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= ĠEvent Router Builder () ĊĠĠĠĠĠĠĠĠ Ġtypes Or Instances . forEach Ġ{ Ġinstance Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( instance ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠClass < *> Ġ-> Ġbuilder . add Participant Type ( instance Ġas ĠClass < Any >) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġbuilder . add Participant ( instance ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠ Ġreturn Ġbuilder ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} Ċ } Ċ Ċ class ĠEvent Router Builder Ġ{ ĊĊĠĠ Ġprivate Ġvar Ġevent Store : ĠEvent Store Ġ= ĠMemory Event Store () ĊĠĠ Ġprivate Ġval Ġparticipants Ġ= Ġmutable ListOf < Pair < Class <* >, ĠEventHandler Invoker >>() ĊĠĠ Ġprivate Ġvar Ġreplay On Startup Ġ= Ġfalse ĊĠĠ Ġfun Ġadd Participant Type ( type : ĠClass < Any >): ĠEvent Router Builder Ġ{ ĊĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠ Ġreturn Ġadd Participant ( type . newInstance ()) ĊĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠInstanti ation Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠ Ġerror (" Cannot Ġinstantiate Ġreceiver Ġinstance Ġ- Ġit Ġmust Ġhave Ġa Ġzero - arg Ġconstructor . Ġ ĠConsider Ġinstanti ating Ġit , Ġand Ġpassing Ġme Ġthe Ġbuilt Ġinstance .") ĊĠĠĠĠĠ Ġ} ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġadd Participant ( receiver : ĠAny ): ĠEvent Router Builder Ġ{ ĊĠĠĠĠĠ Ġif Ġ( receiver Ġis ĠClass <* >) Ġerror (" Don 't Ġpass Ġa Ġclass Ġ- Ġcall Ġadd Participant Type () Ġinstead ") ĊĠĠĠĠĠ Ġval Ġreceiver Type Ġ= Ġreceiver :: class ĊĊĠĠĠĠĠ Ġparticipants . addAll ( receiver Type . member Functions . filter Ġ{ Ġit . find Annotation < MessageHandler >() Ġ!= Ġnull Ġ} ĊĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . java Method Ġ?: ĠTODO (" K Functions Ġthat Ġdon 't Ġcontain Ġa ĠJava Method Ġaren 't Ġcurrently Ġsupported ") Ġ} ĊĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġmethod Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparams Ġ= Ġmethod . parameter Types ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( params . size Ġ!= Ġ 1 ) Ġerror (" Only Ġsingle - arg Ġmethods Ġare Ġsupported Ġcurrently ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmessage Type Ġ= Ġparams [ 0 ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog (). debug (" Added Ġhandler Ġfor Ġmessage Ġtype Ġ${ message Type . typeName } Ġat Ġ${ method . name }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Type Ġto ĠEventHandler Invoker ( receiver , Ġmethod ) ĊĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ) ĊĠĠĠĠĠ Ġreturn Ġthis ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġwith Event Store ( event Store : ĠEvent Store ): ĠEvent Router Builder Ġ{ ĊĠĠĠĠĠ Ġthis . event Store Ġ= Ġevent Store ĊĠĠĠĠĠ Ġreturn Ġthis ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġwith Pass Through Event Store (): ĠEvent Router Builder Ġ{ ĊĠĠĠĠĠ Ġthis . event Store Ġ= ĠPass Through Event Store () ĊĠĠĠĠĠ Ġreturn Ġthis ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġreplay On Startup (): ĠEvent Router Builder Ġ{ ĊĠĠĠĠĠ Ġthis . replay On Startup Ġ= Ġtrue ĊĠĠĠĠĠ Ġreturn Ġthis ĊĠĠ Ġ} ĊĊĠĠ Ġfun Ġbuild (): ĠEvent Router Ġ{ ĊĠĠĠĠĠ Ġval Ġmap Ġ= ĠArrayList Multimap . create < Class <* >, ĠEventHandler Invoker >() ĊĠĠĠĠĠ Ġparticipants . forEach Ġ{ Ġmap . put ( it . first , Ġit . second ) Ġ} ĊĠĠĠĠĠ Ġreturn ĠEvent Router ( map , Ġevent Store , Ġreplay On Startup ) ĊĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠMarker Ġtype Ġfor Ġwhen Ġa Ġmethod Ġinvocation Ċ Ġ* Ġreturns Ġeither Ġnull Ġor Ġvoid . Ċ Ġ* ĠAllows Ġfor Ġdownstream Ġmapping Ġ& Ġfiltering Ċ Ġ*/ Ċ object ĠNull Or Void Response Ċ Ċ internal Ġclass ĠEventHandler Invoker ( val Ġinstance : ĠAny , Ġval Ġmethod : ĠMethod ) Ġ{ ĊĠĠ Ġfun Ġinvoke ( message : ĠAny ): ĠAny Ġ{ ĊĠĠĠĠĠ Ġreturn Ġmethod . invoke ( instance , Ġmessage ) Ġ?: ĠNull Or Void Response ĊĠĠ Ġ} ĊĊĠĠ Ġval Ġname : ĠString Ġ= Ġ"${ instance . java Class . name } :: ${ method . name }" Ċ } Ċ