/* Ċ Ġ* ĠCopyright Ġ 2 0 2 0 ĠNet flix , ĠInc . Ċ Ġ* Ċ Ġ* Ġ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 . Ċ Ġ* Ċ Ġ*/ Ċ package Ġcom . netflix . spin n aker . or ca Ċ Ċ import Ġcom . netflix . spin n aker . k ork . dynamic config . Dynamic Config Service Ċ import Ġcom . netflix . spin n aker . k ork . exceptions . System Exception Ċ import Ġcom . netflix . spin n aker . or ca . api . pipeline . graph . Stage Definition Builder Ċ import Ġjava . util . concurrent . Concurrent HashMap Ċ import Ġorg . slf 4 j . LoggerFactory Ċ import Ġorg . springframework . beans . factory . Object Provider Ċ Ċ /** Ċ Ġ* ĠAllows Ġfor Ġmultiple Ġstages Ġto Ġbe Ġw ired Ġup Ġwith Ġthe Ġsame Ġalias , Ġusing Ġdynamic Ġconfig Ġto Ġdict ate Ġwhich Ġto Ġuse . Ċ Ġ* Ċ Ġ* ĠThis Ġclass Ġmakes Ġmigr ating Ġstages Ġoriginally Ġwritten Ġdirectly Ġinto ĠO rc a Ġto Ġa Ġplugin Ġmodel Ġeasier . ĠTo Ġprevent Ġstage Ċ Ġ* Ġ" d ow nt ime ", Ġa Ġstage Ġwill Ġbe Ġincluded Ġin ĠO rc a Ġas Ġwell Ġas Ġby Ġa Ġplugin , Ġboth Ġof Ġwhich Ġwill Ġshare Ġone Ġor Ġmore Ġaliases . Ċ Ġ* ĠDuplicate Ġsafety Ġchecks Ġare Ġstill Ġperformed : ĠIf Ġa Ġconfig Ġdoes Ġnot Ġexist Ġfor Ġa Ġ[ Stage Definition Builder . getType ] Ġor Ċ Ġ* Ġits Ġalias , Ġexceptions Ġwill Ġbe Ġthrown , Ġwhich Ġwill Ġcause Ġthe Ġapplication Ġto Ġnot Ġstart . Ċ Ġ* Ċ Ġ* ĠThis Ġresolver Ġis Ġmore Ġexpensive Ġthan Ġ[ Default Stage Resolver ], Ġso Ġunless Ġyou Ġare Ġmigr ating Ġstages , Ġusage Ġof Ġthis Ċ Ġ* Ġ[ Stage Resolver ] Ġis Ġnot Ġrecommended . Ċ Ġ* Ċ Ġ* ĠThe Ġconfig Ġvalues Ġfollow Ġa Ġconvention Ġof Ġ` dynamic - stage - resolver .${ stage Definition Builder Alias }`, Ġwhere Ġthe Ġvalue Ċ Ġ* Ġshould Ġbe Ġthe Ġcanonical Ġclass Ġname Ġof Ġthe Ġdesired Ġ[ Stage Definition Builder ]. ĠHaving Ġtwo Ġbuild ers Ġwith Ġthe Ġsame Ġalias Ċ Ġ* Ġand Ġcanonical Ġclass Ġname Ġis Ġnever Ġallowed . Ċ Ġ*/ Ċ class ĠDynamic Stage Resolver ( ĊĠ Ġprivate Ġval Ġdynamic Config Service : ĠDynamic Config Service , ĊĠ Ġprivate Ġval Ġstage Definition Builders Provider : ĠObject Provider < Collection < Stage Definition Builder >> Ċ ) Ġ: ĠStage Resolver Ġ{ ĊĊĠ Ġprivate Ġval Ġlog Ġby Ġlazy Ġ{ ĠLoggerFactory . getLogger ( java Class ) Ġ} ĊĊĠ Ġprivate Ġval Ġstage Definition Builders By Alias : ĠConcurrent HashMap < String , ĠMutable List < Stage Definition Builder >> Ġ= ĠConcurrent HashMap () ĊĠ Ġprivate Ġval Ġfallback Preferences : ĠConcurrent HashMap < String , ĠString > Ġ= ĠConcurrent HashMap () ĊĊĠ Ġinit Ġ{ Ġcompute Stage Definition Builders () Ġ} ĊĊĠ Ġoverride Ġfun Ġget Stage Definition Builder ( type : ĠString , Ġtype Alias : ĠString ?): ĠStage Definition Builder Ġ{ ĊĠĠĠ Ġvar Ġbuilder Ġ= Ġstage Definition Builder ( type , Ġtype Alias ) ĊĊĠĠĠ Ġif Ġ( builder Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġlog . debug (" Stage Ġdefinition Ġbuilder Ġfor Ġ$ type Ġnot Ġfound Ġin Ġinitial Ġstage Ġdefinition Ġbuilder Ġcache , Ġre - computing ...") ĊĠĠĠĠĠ Ġcompute Stage Definition Builders () ĊĠĠĠĠĠ Ġbuilder Ġ= Ġstage Definition Builder ( type , Ġtype Alias ) ĊĊĠĠĠĠĠ Ġif Ġ( builder Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠStage Resolver . NoSuch Stage Definition Builder Exception ( type , Ġtype Alias , Ġstage Definition Builders By Alias . keys ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġbuilder ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġstage Definition Builder ( type : ĠString , Ġtype Alias : ĠString ?): ĠStage Definition Builder ? Ġ{ ĊĠĠĠ Ġvar Ġbuilder : ĠStage Definition Builder ? Ġ= Ġnull ĊĊĠĠĠ Ġval Ġbuilder ForType Ġ= Ġstage Definition Builders By Alias [ type ] ĊĠĠĠ Ġif Ġ( builder ForType Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġbuilder Ġ= Ġbuilder ForType . resolve By Preference ( type ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ( builder Ġ== Ġnull Ġ&& Ġtype Alias Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġbuilder Ġ= Ġstage Definition Builders By Alias [ type Alias ]?. resolve By Preference ( type Alias ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġbuilder ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* Ġ ĠCompute Ġa Ġcache Ġof Ġstage Ġdefinition Ġbuild ers . Ġ ĠA Ġlocal Ġmap Ġis Ġfirst Ġbuilt Ġand Ġvalidated Ġfor ĊĠĠ Ġ* Ġ Ġduplicate Ġstages Ġand Ġconflicting Ġdynamic Ġconfig Ġstage Ġpreferences Ġand Ġthen Ġcopied Ġto Ġthe ĊĠĠ Ġ* Ġ Ġthread Ġsafe Ġcache . ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ ĠThis Ġallows Ġus Ġto Ġre - compute Ġthe Ġstage Ġdefinition Ġbuilder Ġcache Ġif Ġnecessary Ġ( on Ġa Ġcache Ġmiss ĊĠĠ Ġ* Ġ Ġfor Ġexample ) Ġand Ġensures Ġthe Ġvalidation Ġalways Ġruns Ġcorrectly Ġagainst Ġthe Ġlatest Ġset Ġof ĊĠĠ Ġ* Ġ Ġ[ Stage Definition Builder ] Ġclasses . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġcompute Stage Definition Builders () Ġ{ ĊĠĠĠ Ġval Ġlocal Stage Definition Builders By Alias : ĠMutable Map < String , ĠMutable List < Stage Definition Builder >> Ġ= ĊĠĠĠĠĠ Ġmutable Map Of () ĊĠĠĠ Ġstage Definition Builders Provider . get If Available Ġ{ ĠArrayList () Ġ} ĊĠĠĠĠĠ Ġ. forEach Ġ{ Ġbuilder Ġ-> ĊĠĠĠĠĠĠĠ Ġlocal Stage Definition Builders By Alias . put Or Add ( builder . type , Ġbuilder ) ĊĠĠĠĠĠĠĠ Ġbuilder . aliases (). forEach Ġ{ Ġalias Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġlocal Stage Definition Builders By Alias . put Or Add ( alias , Ġbuilder ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġlocal Stage Definition Builders By Alias . filter Ġ{ Ġit . value . size Ġ> Ġ 1 Ġ}. also Ġ{ ĊĠĠĠĠĠ Ġvalidate Preferences ( it ) ĊĠĠĠĠĠ Ġvalidate ClassNames ( it ) ĊĠĠĠĠĠ Ġcache Preferences ( it ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġstage Definition Builders By Alias . put All ( local Stage Definition Builders By Alias ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun ĠMutable Map < String , ĠMutable List < Stage Definition Builder >> . put Or Add ( key : ĠString , Ġstage Definition Builder : ĠStage Definition Builder ) Ġ{ ĊĠĠĠ Ġthis . compute If Absent ( key ) Ġ{ Ġmutable ListOf () Ġ}. add ( stage Definition Builder ) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠEns ures Ġthat Ġany Ġconflicting Ġ[ Stage Definition Builder ] Ġkeys Ġhave Ġconfig Ġset Ġto Ġresolve Ġthe Ġpreferred Ġinstance . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġvalidate Preferences ( duplicates : ĠMap < String , ĠMutable List < Stage Definition Builder >>) Ġ{ ĊĠĠĠ Ġduplicates . forEach Ġ{ Ġduplicate Ġ-> ĊĠĠĠĠĠ Ġval Ġpref Ġ= Ġget Preference ( duplicate . key ) ĊĊĠĠĠĠĠ Ġif Ġ( pref Ġ== ĠNO _ PREFER ENCE ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠNo Preference Config Present Exception ( duplicate . key ) ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġ// ĠEnsure Ġthe Ġpreference Ġis Ġactually Ġvalid : ĠIs Ġthere Ġa ĠStage Definition Builder Ġwith Ġa Ġmatching Ġcanonical Ġname ? ĊĠĠĠĠĠ Ġduplicate . value . map Ġ{ Ġit . extension Class . canonical Name Ġ}. let Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! it . contains ( pref )) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġthrow ĠInvalid Stage Definition Builder Preference ( duplicate . key , Ġpref , Ġit ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠEns ures Ġthat Ġno Ġconflicting Ġ[ Stage Definition Builder ] s Ġhave Ġthe Ġsame Ġcanonical Ġclass Ġname . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġvalidate ClassNames ( duplicates : ĠMap < String , ĠMutable List < Stage Definition Builder >>) Ġ{ ĊĠĠĠ Ġduplicates ĊĠĠĠĠĠ Ġ. filter Ġ{ Ġentry Ġ-> ĊĠĠĠĠĠĠĠ Ġentry . value . map Ġ{ Ġit . extension Class . canonical Name Ġ}. distinct (). size Ġ!= Ġentry . value . size ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ. also Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( it . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġthrow ĠConflict ing ClassNames Exception ( it . keys ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠCache s Ġall Ġpreferences Ġfor Ġfallback Ġif Ġa Ġspecific Ġdynamic Ġconfig Ġbecomes Ġinvalid Ġlater . ĠIt Ġis Ġprefer able Ġto Ġuse ĊĠĠ Ġ* Ġan Ġold Ġvalue Ġrather Ġthan Ġthrowing Ġa Ġruntime Ġexception Ġbecause Ġno Ġ[ Stage Definition Builder ] Ġcould Ġbe Ġlocated . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġcache Preferences ( duplicates : ĠMap < String , ĠMutable List < Stage Definition Builder >>) Ġ{ ĊĠĠĠ Ġduplicates . forEach Ġ{ ĊĠĠĠĠĠ Ġfallback Preferences [ it . key ] Ġ= Ġget Preference ( it . key ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠLoc ates Ġthe Ġ[ Stage Definition Builder ] Ġfor Ġa Ġgiven Ġ[ type ], Ġfalling Ġback Ġto Ġthe Ġoriginal Ġdefaults Ġif Ġthe Ġconfig Ġhas ĊĠĠ Ġ* Ġchanged Ġto Ġan Ġinvalid Ġvalue . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun ĠList < Stage Definition Builder >. resolve By Preference ( type : ĠString ): ĠStage Definition Builder ? Ġ{ ĊĠĠĠ Ġif Ġ( isEmpty ()) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ( size Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġfirst () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġpref Ġ= Ġget Preference ( type ) ĊĠĠĠ Ġval Ġbuilder Ġ= Ġfirst OrNull Ġ{ Ġit . extension Class . canonical Name Ġ== Ġpref Ġ} ĊĠĠĠ Ġif Ġ( builder Ġ== Ġnull Ġ&& Ġfallback Preferences . containsKey ( type )) Ġ{ ĊĠĠĠĠĠ Ġlog . warn (" Preference Ġfor Ġ'$ type ' Ġ($ pref ) Ġis Ġinvalid , Ġfalling Ġback Ġto Ġ'${ fallback Preferences [ type ]} '") ĊĠĠĠĠĠ Ġreturn Ġfirst OrNull Ġ{ Ġit . extension Class . canonical Name Ġ== Ġfallback Preferences [ type ] Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġbuilder ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġget Preference ( type : ĠString ): ĠString Ġ= ĊĠĠĠ Ġdynamic Config Service . getConfig ( ĊĠĠĠĠĠ ĠString :: class . java , ĊĠĠĠĠĠ Ġ" dynamic - stage - resolver .$ type ", ĊĠĠĠĠĠ ĠNO _ PREFER ENCE ĊĠĠĠ Ġ) ĊĊĠ Ġinternal Ġinner Ġclass ĠNo Preference Config Present Exception ( key : ĠString ) Ġ: ĠSystem Exception ( ĊĠĠĠ Ġ" No ĠDynamic Stage Resolver Ġpreference Ġconfig Ġset Ġfor Ġconflicting ĠStage Definition Builder Ġof Ġtype Ġ'$ key '" ĊĠ Ġ) ĊĊĠ Ġinternal Ġinner Ġclass ĠConflict ing ClassNames Exception ( keys : ĠSet < String >) Ġ: ĠSystem Exception ( ĊĠĠĠ Ġ" Conflict ing ĠStage Definition Builder Ġclass Ġnames Ġfor Ġkeys : Ġ${ keys . join ToString () }" ĊĠ Ġ) ĊĊĠ Ġinternal Ġinner Ġclass ĠInvalid Stage Definition Builder Preference ( ĊĠĠĠ Ġkey : ĠString , ĊĠĠĠ Ġpref : ĠString , ĊĠĠĠ Ġcandidates : ĠList < String > ĊĠ Ġ) Ġ: ĠSystem Exception ( ĊĠĠĠ Ġ" Preference Ġfor Ġ'$ key ' ĠStage Definition Builder Ġof Ġ'$ pref ' Ġis Ġinvalid . Ġ" Ġ+ ĊĠĠĠĠĠ Ġ" Valid Ġcanonical Ġnames Ġare : Ġ${ candidates . join ToString () }" ĊĠ Ġ) ĊĊĠ Ġprivate Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġconst Ġval ĠNO _ PREFER ENCE Ġ= Ġ" no - preference - config - defined " ĊĠ Ġ} Ċ } Ċ