/** Ċ Ġ* ĠĠĠĠĠ ĠRed in Ġ- ĠDependency Ġinjection Ġbuilt Ġon Ġtop Ġof ĠK ores Ċ Ġ* Ċ Ġ* ĠĠĠĠĠĠĠĠ ĠThe ĠMIT ĠLicense Ġ( MIT ) Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ ĠCopyright Ġ( c ) Ġ 2 0 2 1 ĠJon athan xD Ġ< https :// github . com / Jon athan xD / Red in > Ċ Ġ* ĠĠĠĠĠ ĠCopyright Ġ( c ) Ġcontributors Ċ Ġ* Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ ĠPermission Ġis Ġhereby Ġgranted , Ġfree Ġof Ġcharge , Ġto Ġany Ġperson Ġobtaining Ġa Ġcopy Ċ Ġ* ĠĠĠĠĠ Ġof Ġthis Ġsoftware Ġand Ġassociated Ġdocumentation Ġfiles Ġ( the Ġ" Software "), Ġto Ġdeal Ċ Ġ* ĠĠĠĠĠ Ġin Ġthe ĠSoftware Ġwithout Ġrestriction , Ġincluding Ġwithout Ġlimitation Ġthe Ġrights Ċ Ġ* ĠĠĠĠĠ Ġto Ġuse , Ġcopy , Ġmodify , Ġmerge , Ġpublish , Ġdistribute , Ġsublicense , Ġand / or Ġsell Ċ Ġ* ĠĠĠĠĠ Ġcopies Ġof Ġthe ĠSoftware , Ġand Ġto Ġpermit Ġpersons Ġto Ġwhom Ġthe ĠSoftware Ġis Ċ Ġ* ĠĠĠĠĠ Ġfurnished Ġto Ġdo Ġso , Ġsubject Ġto Ġthe Ġfollowing Ġconditions : Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ ĠThe Ġabove Ġcopyright Ġnotice Ġand Ġthis Ġpermission Ġnotice Ġshall Ġbe Ġincluded Ġin Ċ Ġ* ĠĠĠĠĠ Ġall Ġcopies Ġor Ġsubstantial Ġportions Ġof Ġthe ĠSoftware . Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ ĠTHE ĠSOFTWARE ĠIS ĠPROVIDED Ġ" AS ĠIS ", ĠWITHOUT ĠWARRANTY ĠOF ĠANY ĠKIND , ĠEXPRESS ĠOR Ċ Ġ* ĠĠĠĠĠ ĠIMPLIED , ĠINCLUDING ĠBUT ĠNOT ĠLIMITED ĠTO ĠTHE ĠWARRANTIES ĠOF ĠMERCHANTABILITY , Ċ Ġ* ĠĠĠĠĠ ĠFITNESS ĠFOR ĠA ĠPARTICULAR ĠPURPOSE ĠAND ĠNONINFRINGEMENT . ĠIN ĠNO ĠEVENT ĠSHALL ĠTHE Ċ Ġ* ĠĠĠĠĠ ĠAUTHORS ĠOR ĠCOPYRIGHT ĠHOLDERS ĠBE ĠLIABLE ĠFOR ĠANY ĠCLAIM , ĠDAMAGES ĠOR ĠOTHER Ċ Ġ* ĠĠĠĠĠ ĠLIABILITY , ĠWHETHER ĠIN ĠAN ĠACTION ĠOF ĠCONTRACT , ĠTORT ĠOR ĠOTHERWISE , ĠARISING ĠFROM , Ċ Ġ* ĠĠĠĠĠ ĠOUT ĠOF ĠOR ĠIN ĠCONNECTION ĠWITH ĠTHE ĠSOFTWARE ĠOR ĠTHE ĠUSE ĠOR ĠOTHER ĠDEALINGS ĠIN Ċ Ġ* ĠĠĠĠĠ ĠTHE ĠSOFTWARE . Ċ Ġ*/ Ċ package Ġcom . github . jon athan xd . red in . test Ċ Ċ import Ġcom . github . jon athan xd . i utils .` object `. Late Init Ċ import Ġcom . github . jon athan xd . i utils . type . TypeInfo Ċ import Ġcom . github . jon athan xd . red in .* Ċ import Ġorg . junit . Test Ċ import Ġjava . util . logging . Logger Ċ import Ġjavax . inject . Named Ċ import Ġjavax . inject . Singleton Ċ Ċ class ĠDoc Ġ{ ĊĊĠĠĠ Ġdata Ġclass ĠAccount ( val Ġid : ĠLong ) ĊĊĠĠĠ Ġinterface ĠAccount Service Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġdeposit ( account : ĠAccount , Ġamount : ĠLong ) ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġclass ĠAccount ServiceImpl Ġ: ĠAccount Service Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġdeposit ( account : ĠAccount , Ġamount : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTODO (" Not Ġyet Ġimplemented ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġclass ĠBank Service Ġ@ Inject Ġconstructor ( val Ġaccount Service : ĠAccount Service ) ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġinject () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġinjector Ġ= ĠRed in Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Account Service >() Ġin Scope ĠS INGLE TON Ġto Implementation ( Account ServiceImpl :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Bank Service >() Ġin Scope ĠS INGLE TON Ġto Implementation ( Bank Service :: class . java ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġaccount Service Ġ= Ġinjector . provide < Account Service >( scope Ġ= ĠS INGLE TON ) ĊĠĠĠĠĠĠĠ Ġval Ġbank Service Ġ= Ġinjector . provide < Bank Service >( scope Ġ= ĠS INGLE TON ) ĊĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġinject 2 () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġinjector Ġ= ĠRed in Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Account Service >() Ġin Scope ĠS INGLE TON Ġto Implementation ( Account ServiceImpl :: class . java ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġaccount Service Ġ= Ġinjector . provide < Account Service >( scope Ġ= ĠS INGLE TON ) ĊĠĠĠĠĠĠĠ Ġinjector . bind Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Bank Service >() Ġin Scope ĠS INGLE TON Ġto Implementation ( Bank Service :: class . java ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġbank Service Ġ= Ġinjector . provide < Bank Service >( scope Ġ= ĠS INGLE TON ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġinject 3 () Ġ{ ĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠProject ( val Ġname : ĠString ) ĊĠĠĠĠĠĠĠ Ġabstract Ġclass ĠPlugin Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġabstract Ġfun Ġinit () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġclass ĠPlugin A Ġ@ Inject Ġconstructor ( val Ġlogger : ĠLogger , Ġval Ġproject : ĠProject , Ġval Ġinjector : ĠInject or ): ĠPlugin () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġinit () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info (" Plugin ĠA Ġinitialized Ġfor Ġproject ĠâĢĺ ${ this . project . name } âĢĻ !") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġclass ĠPlugin B Ġ@ Inject Ġconstructor ( val Ġlogger : ĠLogger , Ġval Ġproject : ĠProject , Ġval Ġinjector : ĠInject or ): ĠPlugin () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġinit () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info (" Plugin ĠB Ġinitialized Ġfor Ġproject ĠâĢĺ ${ this . project . name } âĢĻ !") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġinjector Ġ= ĠRed in Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Project >() Ġin Scope ĠS INGLE TON Ġto Value ĠProject (" Test ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġplugin Classes Ġ= ĠlistOf ( Plugin A :: class . java , ĠPlugin B :: class . java ) ĊĠĠĠĠĠĠĠ Ġval Ġplugin Instances Ġ= Ġmutable ListOf < Plugin >() ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( plugin Class Ġin Ġplugin Classes ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġplugin Injector Ġ= Ġinjector . child Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Logger >(). in Singleton Scope (). to Value ( Logger . getLogger ( plugin Class . name )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġplugin Instances . add ( plugin Injector [ plugin Class ]) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġplugin Instances . forEach ( Plugin :: init ) ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġinject 4 List () Ġ{ ĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠProject ( val Ġname : ĠString ) ĊĠĠĠĠĠĠĠ Ġabstract Ġclass ĠPlugin Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġabstract Ġval Ġid : ĠString ĊĠĠĠĠĠĠĠĠĠĠĠ Ġabstract Ġfun Ġinit () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġclass ĠPlugin A Ġ@ Inject Ġconstructor ( val Ġlogger : ĠLogger , Ġval Ġproject : ĠProject , Ġval Ġinjector : ĠInject or ): ĠPlugin () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġval Ġid : ĠString Ġ= Ġ" com . example . Plugin A " ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġinit () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info (" Plugin ĠA Ġinitialized Ġfor Ġproject ĠâĢĺ ${ this . project . name } âĢĻ !") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġclass ĠPlugin B Ġ@ Inject Ġconstructor ( val Ġlogger : ĠLogger , Ġval Ġproject : ĠProject , Ġval Ġinjector : ĠInject or ): ĠPlugin () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġval Ġid : ĠString Ġ= Ġ" com . example . Plugin B " ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġinit () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info (" Plugin ĠB Ġinitialized Ġfor Ġproject ĠâĢĺ ${ this . project . name } âĢĻ !") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġclass ĠPlugin C Ġ@ Inject Ġconstructor ( val Ġlogger : ĠLogger , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġproject : ĠProject , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Named (" com . example . Plugin B ") Ġval Ġplugin B : ĠPlugin , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinjector : ĠInject or ): ĠPlugin () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġval Ġid : ĠString Ġ= Ġ" com . example . Plugin C " ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġinit () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info (" Plugin ĠC Ġinitialized Ġfor Ġproject ĠâĢĺ ${ this . project . name } âĢĻ !") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġinjector Ġ= ĠRed in Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Project >() Ġin Scope ĠS INGLE TON Ġto Value ĠProject (" Test ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġplugin Classes Ġ= ĠlistOf ( Plugin A :: class . java , ĠPlugin B :: class . java , ĠPlugin C :: class . java ) ĊĠĠĠĠĠĠĠ Ġval Ġplugin Instances Ġ= Ġmutable ListOf < Plugin >() ĊĊĠĠĠĠĠĠĠ Ġinjector . bind Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbind Re ified < List < Plugin >> (). in Singleton Scope (). to Provider Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" called Ġprovider ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġplugin Instances ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbind ( TypeInfo . builder Of ( List :: class . java ). of ( Plugin :: class . java ). build Generic ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( plugin Class Ġin Ġplugin Classes ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġplugin Injector Ġ= Ġinjector . child Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Logger >(). in Singleton Scope (). to Value ( Logger . getLogger ( plugin Class . name )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġplugin Instance Ġ= Ġplugin Injector [ plugin Class ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġplugin Instances . add ( plugin Injector [ plugin Class ]) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġinjector . bind Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Plugin >(). in Singleton Scope (). qualified With ( Name ( plugin Instance . id )). to Value ( plugin Instance ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġplugin Instances . forEach ( Plugin :: init ) ĊĊĠĠĠĠĠĠĠ Ġclass ĠPlugin System Ġ@ Inject Ġconstructor (@ Singleton Ġval Ġplugins : ĠList < Plugin >) ĊĊĠĠĠĠĠĠĠ Ġinjector . bind Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbind < Plugin System >(). in Singleton Scope (). to Implementation < Plugin System >() ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġsystem Ġ= Ġinjector . provide < Plugin System >( scope Ġ= ĠS INGLE TON )() ĊĊĠĠĠ Ġ} ĊĊĊ Ċ }