/* Ċ Ġ* ĠCopyright Ġ 2 0 0 0 - 2 0 1 5 ĠJetBrains Ġs . r . o . Ċ Ġ* Ċ Ġ* Ġ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 . intellij . configuration Store Ċ Ċ import Ġcom . intellij . openapi . Disposable Ċ import Ġcom . intellij . openapi . application . Application Ċ import Ġcom . intellij . openapi . application . Application Manager Ċ import Ġcom . intellij . openapi . components .* Ċ import Ġcom . intellij . openapi . components . State Storage . Save Session Ċ import Ġcom . intellij . openapi . components . State Storage Chooser Ex . Resolution Ċ import Ġcom . intellij . openapi . components . impl . stores . State Storage Manager Ċ import Ġcom . intellij . openapi . util . Dis poser Ċ import Ġcom . intellij . openapi . util . io . File Util Rt Ċ import Ġcom . intellij . openapi . util . text . StringUtil Ċ import Ġcom . intellij . openapi . vfs . new vfs . events . V File Event Ċ import Ġcom . intellij . util . Path Util Rt Ċ import Ġcom . intellij . util . Reflection Util Ċ import Ġcom . intellij . util . Smart List Ċ import Ġcom . intellij . util . Three State Ċ import Ġcom . intellij . util . containers . Container Util Ċ import Ġg nu . tro ve . TH ash Map Ċ import Ġorg . j dom . Element Ċ import Ġorg . jetbrains . annotations . Test Only Ċ import Ġjava . io . File Ċ import Ġjava . io . IOException Ċ import Ġjava . nio . file . Path Ċ import Ġjava . nio . file . Paths Ċ import Ġjava . util .* Ċ import Ġjava . util . concurrent . locks . Re entrant Lock Ċ import Ġjava . util . regex . Pattern Ċ import Ġkotlin . concurrent . with Lock Ċ Ċ private Ġval ĠMAC RO _ PATTERN Ġ= ĠPattern . compile ("( \\ $ [^ \\ $ ]* \\ $ )") Ċ Ċ /** Ċ Ġ* ĠIf Ġcomponent Manager Ġnot Ġspecified , Ġstorage Ġwill Ġnot Ġadd Ġfile Ġtracker Ġ( see ĠVirtual File Tracker ) Ċ Ġ*/ Ċ open Ġclass ĠState Storage ManagerImpl ( private Ġval Ġroot TagName : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġpath Macro Subst it utor : ĠTracking Path Macro Subst it utor ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcomponent Manager : ĠComponent Manager ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġval Ġvirtual File Tracker : ĠStorage Virtual File Tracker ? Ġ= ĠState Storage ManagerImpl . create Default Virtual Tracker ( component Manager ) Ġ) Ġ: ĠState Storage Manager Ġ{ ĊĠ Ġprivate Ġval Ġmacros : ĠMutable List < Macro > Ġ= ĠContainer Util . create Lock Free Copy On Write List () ĊĠ Ġprivate Ġval Ġstorage Lock Ġ= ĠRe entrant Lock () ĊĠ Ġprivate Ġval Ġstorage s Ġ= ĠT HashMap < String , ĠState Storage >() ĊĊĠ Ġvar Ġstream Provider : ĠStream Provider ? Ġ= Ġnull ĊĊĠ Ġ// Ġaccess Ġunder Ġstorage Lock ĊĠ Ġprivate Ġvar Ġis Use V fs Listener Ġ= Ġif Ġ( component Manager Ġ== Ġnull ) ĠThree State . NO Ġelse ĠThree State . UN S URE Ġ// Ġunsure Ġbecause Ġdepends Ġon Ġstream Ġprovider Ġstate ĊĊĠ Ġprotected Ġopen Ġval Ġis Use Xml Pro log : ĠBoolean ĊĠĠĠ Ġget () Ġ= Ġtrue ĊĊĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġprivate Ġfun Ġcreate Default Virtual Tracker ( component Manager : ĠComponent Manager ?) Ġ= Ġwhen Ġ( component Manager ) Ġ{ ĊĠĠĠĠĠ Ġnull Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġis ĠApplication Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ ĠStorage Virtual File Tracker ( component Manager . message Bus ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtracker Ġ= Ġ( Application Manager . getApplication (). state Store . state Storage Manager Ġas ? ĠState Storage ManagerImpl )?. virtual File Tracker ĊĠĠĠĠĠĠĠ Ġif Ġ( tracker Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠDis poser . register ( component Manager , ĠDis posable Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtracker . remove Ġ{ Ġit . storage Manager . component Manager Ġ== Ġcomponent Manager Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġtracker ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġoverride Ġfinal Ġfun Ġget Macro Subst it utor () Ġ= Ġpath Macro Subst it utor ĊĊĠ Ġprivate Ġdata Ġclass ĠMacro ( val Ġkey : ĠString , Ġvar Ġvalue : ĠString ) ĊĊĠ Ġ@ Test Only Ġfun Ġget Virtual File Tracker () Ġ= Ġvirtual File Tracker ĊĊĠ Ġ/** ĊĠĠ Ġ* Ġ@ param Ġexpansion ĠSystem - independent . ĊĠĠ Ġ*/ ĊĠ Ġfun Ġadd Macro ( key : ĠString , Ġexpansion : ĠString ): Boolean Ġ{ ĊĠĠĠ Ġassert (! key . isEmpty ()) ĊĊĠĠĠ Ġval Ġvalue : ĠString ĊĠĠĠ Ġif Ġ( expansion . contains ("\ \" )) Ġ{ ĊĠĠĠĠĠ Ġval Ġmessage Ġ= Ġ" Macro Ġ$ key Ġset Ġto Ġsystem - dependent Ġexpansion Ġ$ expansion " ĊĠĠĠĠĠ Ġif Ġ( Application Manager . getApplication (). is UnitTest Mode ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException ( message ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠ ĠLOG . warn ( message ) ĊĠĠĠĠĠĠĠ Ġvalue Ġ= ĠFile Util Rt . to System In dependent Name ( expansion ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠ Ġvalue Ġ= Ġexpansion ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Ġyou Ġmust Ġnot Ġadd Ġduplicated Ġmacro , Ġbut Ġour ĠModule Impl . set Module FilePath Ġdoes Ġit Ġ( it Ġwill Ġbe Ġfixed Ġlater ) ĊĠĠĠ Ġfor Ġ( macro Ġin Ġmacros ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( key . equals ( macro . key )) Ġ{ ĊĠĠĠĠĠĠĠ Ġmacro . value Ġ= Ġvalue ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġmacros . add ( Macro ( key , Ġvalue )) ĊĠĠĠ Ġreturn Ġtrue ĊĠ Ġ} ĊĊĠ Ġ// Ġsystem - independent Ġpaths ĊĠ Ġopen Ġfun Ġpath Rename d ( old Path : ĠString , Ġnew Path : ĠString , Ġevent : ĠV File Event ?) Ġ{ ĊĠĠĠ Ġfor Ġ( macro Ġin Ġmacros ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( old Path . equals ( macro . value )) Ġ{ ĊĠĠĠĠĠĠĠ Ġmacro . value Ġ= Ġnew Path ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġoverride Ġfinal Ġfun ĠgetState Storage ( storage Spec : ĠStorage ) Ġ= Ġget OrCreate Storage ( storage Spec . path , Ġstorage Spec . ro aming Type , ĊĠĠĠĠĠĠĠĠĠ ĠJava Annotation Helper For Kotlin . get Storage Class ( storage Spec ), ĠJava Annotation Helper For Kotlin . getState Splitter Class ( storage Spec )) ĊĊĠ Ġprotected Ġopen Ġfun Ġnormalize File Spec ( file Spec : ĠString ): ĠString Ġ{ ĊĠĠĠ Ġval Ġpath Ġ= ĠFile Util Rt . to System In dependent Name ( file Spec ) ĊĠĠĠ Ġ// Ġfile Spec Ġfor Ġdirectory Ġbased Ġstorage Ġcould Ġbe Ġerr one ously Ġspecified Ġas Ġ" name /" ĊĠĠĠ Ġreturn Ġif Ġ( path . endsWith ('/ ')) Ġpath . substring ( 0 , Ġpath . length Ġ- Ġ 1 ) Ġelse Ġpath ĊĠ Ġ} ĊĊĠ Ġfun Ġget OrCreate Storage ( collapsed Path : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġro aming Type : ĠRo aming Type Ġ= ĠRo aming Type . DEFAULT , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstorage Class : ĠClass < out ĠState Storage > Ġ= ĠState Storage :: class . java , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Suppress (" DE PREC ATION ") Ġstate Splitter : ĠClass < out ĠState Splitter > Ġ= ĠState Splitter Ex :: class . java ): ĠState Storage Ġ{ ĊĠĠĠ Ġval Ġnormalized Collapsed Path Ġ= Ġnormalize File Spec ( collapsed Path ) ĊĠĠĠ Ġval Ġkey Ġ= Ġif Ġ( storage Class Ġ== ĠState Storage :: class . java ) Ġnormalized Collapsed Path Ġelse Ġstorage Class . name ĊĠĠĠ Ġstorage Lock . with Lock Ġ{ ĊĠĠĠĠĠ Ġvar Ġstorage Ġ= Ġstorage s [ key ] ĊĠĠĠĠĠ Ġif Ġ( storage Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġstorage Ġ= ĠcreateState Storage ( storage Class , Ġnormalized Collapsed Path , Ġro aming Type , Ġstate Splitter ) ĊĠĠĠĠĠĠĠ Ġstorage s . put ( key , Ġstorage ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġreturn Ġstorage ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġget Cached File Storage s ( changed : ĠCollection < String >, Ġdeleted : ĠCollection < String >, Ġpath Normalizer : Ġ(( String ) Ġ-> ĠString )? Ġ= Ġnull ) Ġ= Ġstorage Lock . with Lock Ġ{ ĊĠĠĠ ĠPair ( get Cached File Storage s ( changed , Ġpath Normalizer ), Ġget Cached File Storage s ( deleted , Ġpath Normalizer )) ĊĠ Ġ} ĊĊĠ Ġfun Ġget Cached File Storage s ( file Specs : ĠCollection < String >, Ġpath Normalizer : Ġ(( String ) Ġ-> ĠString )? Ġ= Ġnull ): ĠCollection < File Based Storage > Ġ{ ĊĠĠĠ Ġif Ġ( file Specs . isEmpty ()) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġempty List () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġstorage Lock . with Lock Ġ{ ĊĠĠĠĠĠ Ġvar Ġresult : ĠMutable List < File Based Storage >? Ġ= Ġnull ĊĠĠĠĠĠ Ġfor Ġ( file Spec Ġin Ġfile Specs ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġpath Ġ= Ġnormalize File Spec ( path Normalizer ?. invoke ( file Spec ) Ġ?: Ġfile Spec ) ĊĠĠĠĠĠĠĠ Ġval Ġstorage Ġ= Ġstorage s . get ( path ) ĊĠĠĠĠĠĠĠ Ġif Ġ( storage Ġis ĠFile Based Storage ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( result Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult Ġ= ĠSmart List < File Based Storage >() ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġresult . add ( storage ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġreturn Ġresult Ġ?: Ġempty List () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ// Ġoverridden Ġin Ġup source ĊĠ Ġprotected Ġopen Ġfun ĠcreateState Storage ( storage Class : ĠClass < out ĠState Storage >, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcollapsed Path : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġro aming Type : ĠRo aming Type , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Suppress (" DE PREC ATION ") Ġstate Splitter : ĠClass < out ĠState Splitter >): ĠState Storage Ġ{ ĊĠĠĠ Ġif Ġ( storage Class Ġ!= ĠState Storage :: class . java ) Ġ{ ĊĠĠĠĠĠ Ġval Ġconstructor Ġ= Ġstorage Class . construct ors [ 0 ] !! ĊĠĠĠĠĠ Ġconstructor . is Accessible Ġ= Ġtrue ĊĠĠĠĠĠ Ġreturn Ġconstructor . newInstance ( component Manager !! , Ġthis ) Ġas ĠState Storage ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ( is Use V fs Listener Ġ== ĠThree State . UN S URE ) Ġ{ ĊĠĠĠĠĠ Ġis Use V fs Listener Ġ= ĠThree State . from Boolean ( stream Provider Ġ== Ġnull Ġ|| Ġ! stream Provider !!. enabled ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval ĠfilePath Ġ= Ġexpand Macros ( collapsed Path ) ĊĠĠĠ Ġ@ Suppress (" DE PREC ATION ") ĊĠĠĠ Ġif Ġ( state Splitter Ġ!= ĠState Splitter :: class . java Ġ&& Ġstate Splitter Ġ!= ĠState Splitter Ex :: class . java ) Ġ{ ĊĠĠĠĠĠ Ġval Ġstorage Ġ= Ġcreate Directory Based Storage ( filePath , Ġcollapsed Path , ĠReflection Util . newInstance ( state Splitter )) ĊĠĠĠĠĠ Ġif Ġ( storage Ġis ĠStorage Virtual File Tracker . Tracked Storage ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvirtual File Tracker ?. put ( filePath , Ġstorage ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġreturn Ġstorage ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ(! Application Manager . getApplication (). is Head less Environment Ġ&& ĠPath Util Rt . get FileName ( filePath ). lastIndexOf ('.') Ġ< Ġ 0 ) Ġ{ ĊĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" Extension Ġis Ġmissing Ġfor Ġstorage Ġfile : Ġ$ filePath ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġeffective Roaming Type Ġ= Ġif Ġ( ro aming Type Ġ== ĠRo aming Type . DEFAULT Ġ&& Ġcollapsed Path Ġ== ĠStorage Path Macros . WORK SPACE _ FILE ) ĠRo aming Type . DISABLED Ġelse Ġro aming Type ĊĠĠĠ Ġval Ġstorage Ġ= Ġcreate File Based Storage ( filePath , Ġcollapsed Path , Ġeffective Roaming Type ) ĊĠĠĠ Ġif Ġ( is Use V fs Listener Ġ== ĠThree State . YES Ġ&& Ġstorage Ġis ĠStorage Virtual File Tracker . Tracked Storage ) Ġ{ ĊĠĠĠĠĠ Ġvirtual File Tracker ?. put ( filePath , Ġstorage ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġstorage ĊĠ Ġ} ĊĊĠ Ġprotected Ġopen Ġfun Ġcreate File Based Storage ( path : ĠString , Ġcollapsed Path : ĠString , Ġro aming Type : ĠRo aming Type ): ĠState Storage ĊĠĠĠĠĠ Ġ= ĠMy File Storage ( this , ĠFile ( path ), Ġcollapsed Path , Ġroot TagName , Ġro aming Type , Ġget Macro Subst it utor ( collapsed Path ), Ġstream Provider ) ĊĊĠ Ġprotected Ġopen Ġfun Ġcreate Directory Based Storage ( path : ĠString , Ġcollapsed Path : ĠString , Ġ@ Suppress (" DE PREC ATION ") Ġsplit ter : ĠState Splitter ): ĠState Storage ĊĠĠĠĠĠ Ġ= ĠMy Directory Storage ( this , ĠPaths . get ( path ), Ġsplit ter ) ĊĊĠ Ġprivate Ġclass ĠMy Directory Storage ( override Ġval Ġstorage Manager : ĠState Storage ManagerImpl , Ġfile : ĠPath , Ġ@ Suppress (" DE PREC ATION ") Ġsplit ter : ĠState Splitter ) Ġ: ĊĠĠĠ ĠDirectory Based Storage ( file , Ġsplit ter , Ġstorage Manager . path Macro Subst it utor ), ĠStorage Virtual File Tracker . Tracked Storage ĊĊĠ Ġprivate Ġclass ĠMy File Storage ( override Ġval Ġstorage Manager : ĠState Storage ManagerImpl , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfile : ĠFile , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfile Spec : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġroot ElementName : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġro aming Type : ĠRo aming Type , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath Macro Manager : ĠTracking Path Macro Subst it utor ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprovider : ĠStream Provider ? Ġ= Ġnull ) Ġ: ĠFile Based Storage ( file , Ġfile Spec , Ġroot ElementName , Ġpath Macro Manager , Ġro aming Type , Ġprovider ), ĠStorage Virtual File Tracker . Tracked Storage Ġ{ ĊĠĠĠ Ġoverride Ġval Ġis Use Xml Pro log : ĠBoolean ĊĠĠĠĠĠ Ġget () Ġ= Ġstorage Manager . is Use Xml Pro log ĊĊĠĠĠ Ġoverride Ġfun Ġbefore Element Saved ( element : ĠElement ) Ġ{ ĊĠĠĠĠĠ Ġstorage Manager . before Element Saved ( element ) ĊĠĠĠĠĠ Ġsuper . before Element Saved ( element ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġbefore Element Loaded ( element : ĠElement ) Ġ{ ĊĠĠĠĠĠ Ġstorage Manager . before Element Loaded ( element ) ĊĠĠĠĠĠ Ġsuper . before Element Loaded ( element ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġdata Loaded From Provider ( element : ĠElement ?) Ġ{ ĊĠĠĠĠĠ Ġstorage Manager . data Loaded From Provider ( this , Ġelement ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprotected Ġopen Ġfun Ġbefore Element Saved ( element : ĠElement ) Ġ{ ĊĠ Ġ} ĊĊĠ Ġprotected Ġopen Ġfun Ġbefore Element Loaded ( element : ĠElement ) Ġ{ ĊĠ Ġ} ĊĊĠ Ġprotected Ġopen Ġfun Ġdata Loaded From Provider ( storage : ĠFile Based Storage , Ġelement : ĠElement ?) Ġ{ ĊĠ Ġ} ĊĊĠ Ġoverride Ġfinal Ġfun Ġrename ( path : ĠString , ĠnewName : ĠString ) Ġ{ ĊĠĠĠ Ġstorage Lock . with Lock Ġ{ ĊĠĠĠĠĠ Ġval Ġstorage Ġ= Ġget OrCreate Storage ( collapse Macros ( path ), ĠRo aming Type . DEFAULT ) Ġas ĠFile Based Storage ĊĊĠĠĠĠĠ Ġval Ġfile Ġ= Ġstorage . get Virtual File () ĊĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( file Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġfile . rename ( storage , ĠnewName ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġif Ġ( storage . file . name Ġ!= ĠnewName ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġ// Ġold Ġfile Ġdidn 't Ġexist Ġor Ġrenaming Ġfailed ĊĠĠĠĠĠĠĠĠĠ Ġval Ġexpanded Path Ġ= Ġexpand Macros ( path ) ĊĠĠĠĠĠĠĠĠĠ Ġval Ġparent Path Ġ= ĠPath Util Rt . getParent Path ( expanded Path ) ĊĠĠĠĠĠĠĠĠĠ Ġstorage . set File ( null , ĠFile ( parent Path , ĠnewName )) ĊĠĠĠĠĠĠĠĠĠ Ġpath Rename d ( expanded Path , Ġ"$ parent Path /$ new Name ", Ġnull ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠ ĠLOG . debug ( e ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġclear Storage s () Ġ{ ĊĠĠĠ Ġstorage Lock . with Lock Ġ{ ĊĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( virtual File Tracker Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġstorage s . forEach Entry ({ Ġcollapsed Path , Ġstorage Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvirtual File Tracker . remove ( expand Macros ( collapsed Path )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġfinally Ġ{ ĊĠĠĠĠĠĠĠ Ġstorage s . clear () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprotected Ġopen Ġfun Ġget Macro Subst it utor ( file Spec : ĠString ): ĠTracking Path Macro Subst it utor ? Ġ= Ġpath Macro Subst it utor ĊĊĠ Ġoverride Ġfun Ġexpand Macros ( path : ĠString ): ĠString Ġ{ ĊĠĠĠ Ġ// Ġreplacement Ġcan Ġcontains Ġ$ Ġ( php Ġtests ), Ġso , Ġthis Ġcheck Ġmust Ġbe Ġperformed Ġbefore Ġexpand ĊĠĠĠ Ġval Ġmatcher Ġ= ĠMAC RO _ PATTERN . matcher ( path ) ĊĠĠĠ Ġmatcher Loop @ ĊĠĠĠ Ġwhile Ġ( matcher . find ()) Ġ{ ĊĠĠĠĠĠ Ġval Ġm Ġ= Ġmatcher . group ( 1 ) ĊĠĠĠĠĠ Ġfor Ġ( macro Ġin Ġmacros ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( macro . key Ġ== Ġm ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġcontinue @ matcher Loop ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" Unknown Ġmacro : Ġ$ m Ġin Ġstorage Ġfile Ġspec : Ġ$ path ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġvar Ġexpanded Ġ= Ġpath ĊĠĠĠ Ġfor Ġ(( key , Ġvalue ) Ġin Ġmacros ) Ġ{ ĊĠĠĠĠĠ Ġexpanded Ġ= ĠString Util . replace ( expanded , Ġkey , Ġvalue ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġexpanded ĊĠ Ġ} ĊĊĠ Ġfun Ġexpand Macro ( macro : ĠString ): ĠString Ġ{ ĊĠĠĠ Ġfor Ġ(( key , Ġvalue ) Ġin Ġmacros ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( key Ġ== Ġmacro ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġvalue ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġthrow ĠIllegalArgumentException (" Unknown Ġmacro Ġ$ macro ") ĊĠ Ġ} ĊĊĠ Ġfun Ġcollapse Macros ( path : ĠString ): ĠString Ġ{ ĊĠĠĠ Ġvar Ġresult Ġ= Ġpath ĊĠĠĠ Ġfor Ġ(( key , Ġvalue ) Ġin Ġmacros ) Ġ{ ĊĠĠĠĠĠ Ġresult Ġ= Ġresult . replace ( value , Ġkey ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġnormalize File Spec ( result ) ĊĠ Ġ} ĊĊĠ Ġoverride Ġfinal Ġfun Ġstart External ization () Ġ= Ġobject Ġ: ĠState Storage Manager . External ization Session Ġ{ ĊĠĠĠ Ġprivate Ġval Ġsessions Ġ= ĠLinkedHashMap < State Storage , ĠState Storage . External ization Session >() ĊĊĠĠĠ Ġoverride Ġfun ĠsetState ( storage Specs : ĠArray < Storage >, Ġcomponent : ĠAny , Ġcomponent Name : ĠString , Ġstate : ĠAny ) Ġ{ ĊĠĠĠĠĠ Ġval Ġstate Storage Chooser Ġ= Ġcomponent Ġas ? ĠState Storage Chooser Ex ĊĠĠĠĠĠ Ġfor Ġ( storage Spec Ġin Ġstorage Specs ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresolution Ġ= Ġif Ġ( state Storage Chooser Ġ== Ġnull ) ĠResolution . DO Ġelse Ġstate Storage Chooser . get Resolution ( storage Spec , ĠState Storage Operation . WRITE ) ĊĠĠĠĠĠĠĠ Ġif Ġ( resolution Ġ== ĠResolution . SKIP ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġget External ization Session ( getState Storage ( storage Spec )) ?. setState ( component , Ġcomponent Name , Ġif Ġ( storage Spec . deprecated Ġ|| Ġresolution Ġ== ĠResolution . CLEAR ) ĠElement (" empty ") Ġelse Ġstate ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠsetState In Old Storage ( component : ĠAny , Ġcomponent Name : ĠString , Ġstate : ĠAny ) Ġ{ ĊĠĠĠĠĠ Ġget Old Storage ( component , Ġcomponent Name , ĠState Storage Operation . WRITE )?. let Ġ{ ĊĠĠĠĠĠĠĠ Ġget External ization Session ( it )?. setState ( component , Ġcomponent Name , Ġstate ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget External ization Session ( storage : ĠState Storage ): ĠState Storage . External ization Session ? Ġ{ ĊĠĠĠĠĠ Ġvar Ġsession Ġ= Ġsessions . get ( storage ) ĊĠĠĠĠĠ Ġif Ġ( session Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġsession Ġ= Ġstorage . start External ization () ĊĠĠĠĠĠĠĠ Ġif Ġ( session Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġsessions . put ( storage , Ġsession ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġreturn Ġsession ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġcreate Save Sessions (): ĠList < Save Session > Ġ{ ĊĠĠĠĠĠ Ġif Ġ( sessions . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġempty List () ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġvar Ġsave Sessions : ĠMutable List < Save Session >? Ġ= Ġnull ĊĠĠĠĠĠ Ġval Ġexternal ization Sessions Ġ= Ġsessions . values ĊĠĠĠĠĠ Ġfor Ġ( session Ġin Ġexternal ization Sessions ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsave Session Ġ= Ġsession . create Save Session () ĊĠĠĠĠĠĠĠ Ġif Ġ( save Session Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( save Sessions Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( external ization Sessions . size Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠlistOf ( save Session ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave Sessions Ġ= ĠSmart List < Save Session >() ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġsave Sessions . add ( save Session ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġreturn Ġsave Sessions Ġ?: Ġempty List () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġoverride Ġfinal Ġfun Ġget Old Storage ( component : ĠAny , Ġcomponent Name : ĠString , Ġoperation : ĠState Storage Operation ): ĠState Storage ? Ġ{ ĊĠĠĠ Ġval Ġold Storage Spec Ġ= Ġget Old Storage Spec ( component , Ġcomponent Name , Ġoperation ) Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġ@ Suppress (" DE PREC ATION ") ĊĠĠĠ Ġreturn Ġget OrCreate Storage ( old Storage Spec , Ġif Ġ( component Ġis Ġcom . intellij . openapi . util . Roaming Type Disabled ) ĠRo aming Type . DISABLED Ġelse ĠRo aming Type . DEFAULT ) ĊĠ Ġ} ĊĊĠ Ġprotected Ġopen Ġfun Ġget Old Storage Spec ( component : ĠAny , Ġcomponent Name : ĠString , Ġoperation : ĠState Storage Operation ): ĠString ? Ġ= Ġnull Ċ } Ċ Ċ private Ġfun ĠString . startsWith Macro ( macro : ĠString ): ĠBoolean Ġ{ ĊĠ Ġval Ġi Ġ= Ġmacro . length ĊĠ Ġreturn Ġlength Ġ> Ġi Ġ&& Ġthis [ i ] Ġ== Ġ'/' Ġ&& Ġstart sWith ( macro ) Ċ } Ċ Ċ fun Ġremove Macro If StartsWith ( path : ĠString , Ġmacro : ĠString ) Ġ= Ġif Ġ( path . startsWith Macro ( macro )) Ġpath . substring ( macro . length Ġ+ Ġ 1 ) Ġelse Ġpath Ċ Ċ @ Suppress (" DE PREC ATION ") Ċ internal Ġval ĠStorage . path : ĠString ĊĠ Ġget () Ġ= Ġif Ġ( value . isNull OrEmpty ()) Ġfile Ġelse Ġvalue