/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 8 ĠNu ĠEcho Ġ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 . n ue cho . mut agen . cli . commands . config . import . operation Ċ Ċ import Ġcom . genes ys lab . platform . application blocks . com . IC fg Object Ċ import Ġcom . n ue cho . mut agen . cli . Logging . info Ċ import Ġcom . n ue cho . mut agen . cli . commands . config . import . operation . Import Operation Type . CREATE Ċ import Ġcom . n ue cho . mut agen . cli . commands . config . import . operation . Import Operation Type . SKIP Ċ import Ġcom . n ue cho . mut agen . cli . commands . config . import . operation . Import Operation Type . UPDATE Ċ import Ġcom . n ue cho . mut agen . cli . models . configuration . Configuration Ċ import Ġcom . n ue cho . mut agen . cli . models . configuration . Configuration Builder Ċ import Ġcom . n ue cho . mut agen . cli . models . configuration . Configuration Object Ċ import Ġcom . n ue cho . mut agen . cli . services . Conf Service Ċ import Ġorg . j gr ap ht . Graph Ċ import Ġorg . j gr ap ht . alg . cycle . Cycle Detector Ċ import Ġorg . j gr ap ht . graph . Default Direct ed Graph Ċ import Ġorg . j gr ap ht . graph . Default Edge Ċ import Ġorg . j gr ap ht . traverse . Top ological Order Iterator Ċ Ċ val Ġtype To Color : ĠMap < Import Operation Type , ĠString > Ġ= Ġmap Of ( ĊĠĠĠ ĠCREATE Ġto Ġ" green ", ĊĠĠĠ ĠUPDATE Ġto Ġ" yellow ", ĊĠĠĠ ĠSKIP Ġto Ġ" white " Ċ ) Ċ Ċ class ĠImport Plan ( val Ġconfiguration : ĠConfiguration , Ġval Ġservice : ĠConf Service ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġordered Operations Ġ= Ġapply Operation Order ( service , Ġconfiguration ) ĊĊĠĠĠ Ġfun Ġprint () Ġ= Ġprint Plan ( ordered Operations ) ĊĊĠĠĠ Ġfun Ġapply (): ĠMap < Import Operation Type , ĠInt > Ġ{ ĊĠĠĠĠĠĠĠ Ġfor Ġ( operation Ġin Ġordered Operations ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġreference Ġ= Ġoperation . configuration Object . reference ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinfo Ġ{ Ġ" Processing Ġ${ reference . to Console String ()} ." Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoperation . apply ()?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġservice . configuration Object Repository [ reference ] Ġ= Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoperation . print ( false ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġcount Ġ= Ġmutable Map Of ( CREATE Ġto Ġ 0 , ĠSKIP Ġto Ġ 0 , ĠUPDATE Ġto Ġ 0 ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġordered Operations . fold ( count ) Ġ{ Ġaccumulator , Ġimport Operation Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġaccumulator . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( import Operation . type ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCREATE Ġ-> Ġaccumulator [ CREATE ] Ġ= Ġaccumulator [ CREATE ] !! Ġ+ Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSKIP Ġ-> Ġaccumulator [ SKIP ] Ġ= Ġaccumulator [ SKIP ] !! Ġ+ Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUPDATE Ġ-> Ġaccumulator [ UPDATE ] Ġ= Ġaccumulator [ UPDATE ] !! Ġ+ Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġinternal Ġfun Ġapply Operation Order ( service : ĠConf Service , Ġconfiguration : ĠConfiguration ): ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠList < Import Operation > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġoperations Ġ= Ġto Operations ( service , Ġconfiguration ). to Mutable List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġoperation Graph Ġ= Ġcreate Operation Graph ( operations ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( operation Graph . detect Cycles ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcy cl ing Nodes Ġ= Ġoperation Graph . find Cycles (). filter Ġ{ Ġit . configuration Object . clone B are () Ġ!= Ġnull Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoperations Ġ-= Ġcy cl ing Nodes ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcy cl ing Nodes ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . configuration Object Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġconfiguration Object Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoperations Ġ+= ĠCreate Operation ( configuration Object . clone B are () !! , Ġservice ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoperations Ġ+= ĠUpdate Reference Operation ( configuration Object , Ġservice ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoperation Graph Ġ= Ġcreate Operation Graph ( operations ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠS afety Ġnet : Ġcheck Ġfor Ġcycles Ġagain ... ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( operation Graph . detect Cycles ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" Could Ġnot Ġbreak Ġdependency Ġcycle ( s ). ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠTop ological Order Iterator ( operation Graph ). as Sequence (). toList () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġinternal Ġfun Ġprint Plan ( operations : ĠList < Import Operation >) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" The Ġfollowing Ġchanges Ġare Ġgoing Ġto Ġbe Ġapplied :") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoperations . forEach Ġ{ Ġit . print ( true ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġto Operations ( service : ĠConf Service , Ġconfiguration : ĠConfiguration ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconfiguration . as Map By Reference . values . map Ġ{ Ġto Operation ( service , Ġit ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġinternal Ġfun Ġto Operation ( service : ĠConf Service , Ġconfiguration Object : ĠConfiguration Object ): ĠImport Operation Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġremote Cfg Object Ġ= Ġservice . retrieve Object ( configuration Object . reference ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremote Cfg Object Ġ== Ġnull Ġ-> ĠCreate Operation ( configuration Object , Ġservice ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Ident ical After Update ( service , Ġconfiguration Object , Ġremote Cfg Object ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSkip Operation ( configuration Object , Ġservice ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠUpdate Operation ( configuration Object , Ġremote Cfg Object , Ġservice ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġis Ident ical After Update ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġservice : ĠConf Service , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconfiguration Object : ĠConfiguration Object , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremote Cfg Object : ĠI Cfg Object ĊĠĠĠĠĠĠĠ Ġ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIf Ġthere Ġis Ġany Ġobject Ġreferenced Ġby Ġ` configuration Object ` Ġthat Ġis Ġnot Ġexisting Ġon Ġthe Ġconfiguration ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġserver , Ġthat Ġmeans Ġthis Ġobject Ġwill Ġcertainly Ġnot Ġbe Ġidentical Ġafter Ġthe Ġupdate . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġneed Ġthis Ġto Ġprevent Ġnull Ġpointer Ġexceptions Ġlater Ġon . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( configuration Object . get References (). any Ġ{ Ġservice . retrieve Object ( it ) Ġ== Ġnull Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġremote Object Ġ= ĠConfiguration Builder . to Configuration Object ( remote Cfg Object ) !! ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠMakes Ġa Ġcopy Ġof Ġthe Ġremote Cfg Object Ġbecause Ġupdate Cfg Object Ġmut ates Ġit Ġ( which Ġs ucks ĠB TW ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġremote Cfg Object Copy Ġ= Ġremote Object . create Cfg Object ( service ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdated Cfg Object Ġ= Ġconfiguration Object . update Cfg Object ( service , Ġremote Cfg Object Copy ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdated Object Ġ= ĠConfiguration Builder . to Configuration Object ( updated Cfg Object ) !! ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġremote Object . toJson () Ġ== Ġupdated Object . toJson () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġcreate Operation Graph ( operations : ĠList < Import Operation >): ĠGraph < Import Operation , ĠDefault Edge > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġgraph : ĠGraph < Import Operation , ĠDefault Edge > Ġ= ĠDefault Direct ed Graph ( Default Edge :: class . java ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġneed Ġto Ġadd Ġgraph Ġvertex Ġbefore Ġwe Ġconnect Ġthem Ġtogether ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoperations . forEach Ġ{ Ġoperation Ġ-> Ġgraph . add Vertex ( operation ) Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġcare Ġonly Ġfor Ġdependencies Ġpart Ġof Ġthe Ġconfiguration Ġwe Ġare Ġtrying Ġto Ġimport ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġassuming Ġat Ġthis Ġstate Ġthat Ġremote Ġdependencies Ġexist . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( operation Ġin Ġoperations ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( reference Ġin Ġoperation . configuration Object . get References ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠC yc les Ġare Ġproblematic Ġonly Ġfor Ġobjects Ġwe Ġare ĠCRE ATING Ġ- Ġthus Ġthe Ġfilter Ġon Ġtype Ġ== ĠCREATE . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġde pen dee Ġ= Ġoperations ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . type Ġ== ĠCREATE Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first OrNull Ġ{ Ġit . configuration Object . reference Ġ== Ġreference Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( de pen dee Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgraph . add Edge ( de pen dee , Ġoperation ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġgraph ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun ĠGraph < *, Ġ* >. detect Cycles () Ġ= ĠCycle Detector ( this ). detect Cycles () ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġ< V , ĠE > ĠGraph < V , ĠE >. find Cycles () Ġ= ĠCycle Detector ( this ). find Cycles () ĊĠĠĠ Ġ} Ċ } Ċ Ċ enum Ġclass ĠImport Operation Type ( val Ġsymbol : ĠString ) Ġ{ ĊĠĠĠ ĠCREATE ("+ "), ĠUPDATE (" ~ "), ĠSKIP (" ="); ĊĊĠĠĠ Ġoverride Ġfun ĠtoString () Ġ= Ġsymbol Ċ } Ċ