package Ġorg . chron op ol is . replic ate . batch . rs ync Ċ Ċ import Ġokhttp 3 . ResponseBody Ċ import Ġorg . chron op ol is . replic ate . Replication Properties Ċ import Ġorg . chron op ol is . rest . api . File Service Ċ import Ġorg . chron op ol is . rest . models . Bag Ċ import Ġorg . slf 4 j . Logger Ċ import Ġorg . slf 4 j . LoggerFactory Ċ import Ġretrofit 2 . Call Ċ import Ġjava . io . Buffered Writer Ċ import Ġjava . io . IOException Ċ import Ġjava . nio . file . Files Ċ import Ġjava . nio . file . Path Ċ import Ġjava . nio . file . Paths Ċ import Ġjava . util . function . Supplier ĊĊ Ċ /** Ċ Ġ* ĠDownload Ġa Ġfile Ġlisting Ġfor Ġa Ġcollection Ġand Ġsave Ġit Ġinto Ġmultiple Ġchunk ed Ġfiles . Ċ Ġ* Ċ Ġ* ĠSo Ġat Ġthe Ġmoment Ġwe 're Ġusing Ġa Ġ[ Result ] Ġclass Ġwhich Ġprovides Ġus Ġwith Ġa Ġway Ġto Ġden ote ĠSuccess Ċ Ġ* Ġand ĠFailure Ġ( m uch Ġlike ĠTry Ġwould ). ĠHowever , Ġthe Ġfact Ġthat Ġwe 're Ġalso Ġusing Ġ[ Comp letableFuture ] s Ċ Ġ* Ġmeans Ġwe Ġ_ could _ Ġlet Ġ[ RuntimeException ] s Ġbubble Ġup Ġand Ġcatch Ġthem Ġwith Ġmethods Ġlike Ġwhen Complete Ċ Ġ* Ġand Ġexception ally . ĠID K Ġlots Ġto Ġthink Ġabout Ġand Ġpar alysis Ġprobably Ġisn 't Ġthe Ġbest Ġway Ġto Ġprogram . Ċ Ġ* Ċ Ġ* ĠLet 's Ġjustify Ġthe Ġuse Ġof Ġ[ Result ] Ġlike Ġthis Ġfor Ġnow : Ġit 's Ġa Ġsafe Ġway Ġto Ġhandle Ġfailure Ġand Ġdoes Ċ Ġ* Ġnot Ġin cur Ġas Ġmuch Ġof Ġa Ġcost Ġas Ġthrowing Ġan ĠException . Ċ Ġ* Ċ Ġ* Ġ@ param Ġbag Ġthe Ġ[ Bag ] Ġwhose Ġfile Ġlisting Ġto Ġdownload Ċ Ġ* Ġ@ param Ġapi Ġthe Ġ[ File Service ] Ġfor Ġinteracting Ġwith Ġthe ĠIn gest ĠServer Ċ Ġ* Ġ@ param Ġproperties Ġthe Ġ[ Replication Properties ] Ġcontaining Ġconfiguration Ġinformation Ċ Ġ* Ċ Ġ* Ġ@ author Ġsh ake Ċ Ġ*/ Ċ class ĠListing Downloader ( val Ġbag : ĠBag , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġapi : ĠFile Service , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġproperties : ĠRep lication Properties ) Ġ: ĠSupplier < Result < List < Path >>> Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġget (): ĠResult < List < Path >> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġpath Ġ= ĠPaths . get ( properties . work Directory , Ġbag . de positor , Ġbag . name ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠResult Ġ-> ĠSuccess ( paths : ĠList < Path >) ĊĠĠĠĠĠĠĠ Ġ// ĠĠĠĠĠĠĠ Ġ-> ĠError ( e : ĠException ) ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġexecute Request Ġ( execute Request ) ĊĠĠĠĠĠĠĠ Ġ// ĠĠ Ġwrite Files Ġ( write ResponseBody ) ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFiles . create Directories ( path ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecute Request ( path ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . error (" Error Ġcreating Ġdirectory , Ġcheck Ġwork Ġdirectory Ġproperty ", Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Error ( e ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġexecute Request ( path : ĠPath ): ĠResult < List < Path >> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcall : ĠCall < ResponseBody > Ġ= Ġapi . getFile List ( bag . id ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġcall . execute () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( response . is Successful Ġ&& Ġresponse . body () Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite ResponseBody ( path , Ġresponse . body () !! ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . error ("[ {}] ĠUnable Ġto Ġcomplete Ġrequest Ġto Ġingest Ġapi Ġ{} Ġ{}", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbag . name , Ġresponse . code (), Ġresponse . message ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Error ( IOException (" Unable Ġto Ġcomplete Ġrequest Ġsuccessfully ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . error ("[ {}] ĠError Ġcommunic ating Ġwith Ġingest Ġapi ", Ġbag . name , Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Error ( e ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrite Ġa Ġ[ ResponseBody ] Ġto Ġa Ġgiven Ġoutput Ġdirectory Ġin Ġchunks Ġ( currently Ġjust Ġby Ġmax Ġnumber Ġof ĊĠĠĠĠ Ġ* Ġlines Ġdefined Ġby Ġa Ġ[ Bag ] s Ġtotal Files Ġdivided Ġby Ġ 1 0 ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġwrite ResponseBody ( output : ĠPath , Ġbody : ĠResponse Body ): ĠResult < List < Path >> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmax Ġ= ĠMath . ceil ( bag . total Files . div ( 1 0 . 0 )). toInt () ĊĠĠĠĠĠĠĠ Ġval Ġwriter Ġ= ĠBody Writer ( output ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġbody . char Stream () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. buffered () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. line Sequence () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. chunk ed ( max ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Indexed ( writer :: write ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. as Result () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġclass ĠBody Writer ( private Ġval Ġoutput : ĠPath ) Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġwrite ( index : ĠInt , Ġlist : ĠList < String >): ĠResult < Path > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpath Ġ= Ġoutput . resolve (" chunk -$ index ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . debug (" Writing Ġchunk Ġ{}", Ġpath ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠFiles . new Buffered Writer ( path ). use Ġ{ Ġwriter Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlist . forEach Ġ{ Ġwriter . write Ln ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Success ( path ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . error (" Error Ġwriting Ġchunk ed Ġlisting Ġ{}", Ġpath , Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠResult . Error ( e ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠExtension Ġfunction Ġto Ġappend Ġa Ġnewline Ġto Ġeach Ġstring Ġthat Ġis Ġwritten ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġprivate Ġfun ĠBuffered Writer . write Ln ( str : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . write ( str ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . new Line () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlog : ĠLogger Ġ= ĠLoggerFactory . getLogger ( Listing Downloader :: class . java ) ĊĠĠĠ Ġ} Ċ } ĊĊ