package Ġde . fl ap do od le . photos ync . paths Ċ Ċ import Ġjava . nio . file . Path Ċ Ċ object ĠMeta Ġ{ ĊĊĠ Ġfun Ġis Meta ( path : ĠPath , ĠbasePath : ĠPath ): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn ĠPath Matcher . same Parent ĊĠĠĠĠĠĠĠ Ġ. and Then ( Meta FileName ) Ċ // ĠĠĠĠĠĠĠ Ġ. and Then ( Path Matcher . not Same FileName ) ĊĠĠĠĠĠĠĠ Ġ. match ( path , ĠbasePath ) ĊĠ Ġ} ĊĊĠ Ġfun Ġgroup By BasePath ( paths : ĠCollection < Path >): ĠMap < Path , ĠList < Path >> Ġ{ ĊĠĠĠ Ġval Ġbase Files Ġ= Ġpaths . filter Ġ{ Ġthis Path Ġ-> Ġpaths . none Ġ{ Ġis Meta ( this Path , Ġit ) Ġ} Ġ} ĊĠĠĠ Ġval Ġmeta Files Ġ= Ġpaths . filter Ġ{ Ġ! base Files . contains ( it ) Ġ} ĊĊĠĠĠ Ġreturn Ġbase Files . map Ġ{ ĊĠĠĠĠĠ Ġit Ġto Ġempty List < Path >() ĊĠĠĠ Ġ}. toMap () Ġ+ Ġmeta Files . groupBy Ġ{ Ġthis Path Ġ-> ĊĠĠĠĠĠ Ġbase Files . find Ġ{ ĠMeta . is Meta ( this Path , Ġit ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠIllegalArgumentException (" basePath Ġnot Ġfound : Ġ$ this Path Ġ- Ġ$ paths ") ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġreplace Base ( path : ĠPath , Ġbase : ĠPath , Ġnew Base : ĠPath ): ĠPath Ġ{ ĊĠĠĠ Ġrequire ( is Meta ( path , Ġbase )) Ġ{ Ġ"$ this Ġmust Ġstart Ġwith Ġ$ base " Ġ} ĊĊĠĠĠ Ġval ĠfileName Ġ= Ġpath . fileName . toString () ĊĠĠĠ Ġval Ġbase FileName Ġ= Ġbase . fileName . toString () ĊĠĠĠ Ġval Ġappend Ġ= ĠfileName . substring ( base FileName . length ) ĊĊĠĠĠ Ġreturn Ġnew Base . parent . resolve ( new Base . fileName . toString () Ġ+ Ġappend ) ĊĠ Ġ} ĊĊĠ Ġobject ĠMeta FileName Ġ: ĠPath Matcher Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġmatch ( first : ĠPath , Ġsecond : ĠPath ): ĠBoolean Ġ{ ĊĠĠĠĠĠ Ġreturn ĠFilename . parse ( first . fileName . toString ()). is Meta ( Filename . parse ( second . fileName . toString ())) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġdata Ġclass ĠFilename ( ĊĠĠĠĠĠ Ġval Ġname : ĠString , ĊĠĠĠĠĠ Ġval Ġextension : ĠString ? ĊĠ Ġ) Ġ{ ĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠ Ġrequire (! name . contains ('. ')) Ġ{ Ġ" name Ġpart Ġcontains Ġ. : Ġ$ name " Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġis Meta ( base : ĠFilename ): ĠBoolean Ġ{ ĊĠĠĠĠĠ Ġreturn Ġif Ġ( this Ġ!= Ġbase Ġ&& Ġextension Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( base . extension Ġ== Ġnull Ġ|| Ġextension . startsWith ( base . extension )) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġname Matches Base Name With Optional Counter ( name , Ġbase . name ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠ Ġprivate Ġval Ġcounter Pattern Ġ= Ġ" (_ [ 0 - 9 ][ 0 - 9 ]) ". to Regex () ĊĊĠĠĠĠĠ Ġprivate Ġfun Ġname Matches Base Name With Optional Counter ( name : ĠString , Ġbase Name : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġname Ġ== Ġbase Name Ġ-> Ġtrue ĊĠĠĠĠĠĠĠĠĠ Ġname . startsWith ( base Name ) Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcounter Pattern . matches ( name . substring ( base Name . length )) ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġfun Ġparse ( filename : ĠString ): ĠFilename Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġidx Ġ= Ġfilename . indexOf ('.') ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( idx ! =- 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠFilename ( filename . substring ( 0 , idx ), Ġfilename . substring ( idx + 1 )) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠFilename ( filename , Ġnull ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ }