// ĠCopyright Ġ 2 0 0 0 - 2 0 1 8 ĠJetBrains Ġs . r . o . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe ĠLICENSE Ġfile . Ċ package Ġcom . intellij . internal . statistic . utils Ċ Ċ import Ġcom . intellij . ide . plugins .* Ċ import Ġcom . intellij . internal . statistic . beans . Usage Descriptor Ċ import Ġcom . intellij . internal . statistic . event Log . Event Log Configuration Ċ import Ġcom . intellij . internal . statistic . event Log . new Data Ċ import Ġcom . intellij . internal . statistic . service . f us . collect ors . F US Usage Context Ċ import Ġcom . intellij . openapi . application . Application Manager Ċ import Ġcom . intellij . openapi . application . ex . Application Info Ex Ċ import Ġcom . intellij . openapi . extensions . Plugin Descriptor Ċ import Ġcom . intellij . openapi . extensions . Plugin Id Ċ import Ġcom . intellij . openapi . project . Default Project Factory Ċ import Ġcom . intellij . openapi . project . Project Ċ import Ġcom . intellij . openapi . project . getProject Cache FileName Ċ import Ġcom . intellij . openapi . util . Comp aring Ċ import Ġcom . intellij . openapi . util . Modification Tracker Ċ import Ġcom . intellij . psi . util . Cached Value Provider Ċ import Ġcom . intellij . psi . util . Cached Values Manager Ċ import Ġcom . intellij . util . containers . Container Util Ċ import Ġcom . intellij . util . containers . Object Int HashMap Ċ import Ġg nu . tro ve . TH ash Set Ċ import Ġjava . io . IOException Ċ import Ġjava . util .* Ċ import Ġjava . util . concurrent . TimeUnit Ċ Ċ fun Ġget ProjectId ( project : ĠProject ): ĠString Ġ{ ĊĠ Ġreturn ĠEvent Log Configuration . anon ym ize ( project . getProject Cache FileName ()) Ċ } Ċ Ċ fun Ġcreate Data ( project : ĠProject ?, Ġcontext : ĠF US Usage Context ?): ĠMap < String , ĠAny > Ġ{ ĊĠ Ġreturn ĠnewData ( project , Ġcontext ) Ċ } Ċ Ċ fun Ġis Develop edBy Jet Brains ( plugin Id : ĠPlugin Id ?): ĠBoolean Ġ{ ĊĠ Ġval Ġplugin Ġ= ĠPlugin Manager . get Plugin ( plugin Id ) ĊĠ Ġreturn Ġplugin Ġ== Ġnull Ġ|| ĠPlugin Manager Main . is Develop edBy Jet Brains ( plugin . vendor ) Ċ } Ċ Ċ /** Ċ Ġ* ĠConstructs Ġa Ġproper ĠUsage Descriptor Ġfor Ġa Ġboolean Ġvalue , Ċ Ġ* Ġby Ġadding Ġ" enabled " Ġor Ġ" disabled " Ġsuffix Ġto Ġthe Ġgiven Ġkey , Ġdepending Ġon Ġthe Ġvalue . Ċ Ġ*/ Ċ fun Ġget Boolean Usage ( key : ĠString , Ġvalue : ĠBoolean ): ĠUsage Descriptor Ġ{ ĊĠ Ġreturn ĠUsage Descriptor ( key Ġ+ Ġif Ġ( value ) Ġ". enabled " Ġelse Ġ". disabled ", Ġ 1 ) Ċ } Ċ Ċ fun Ġget Enum Usage ( key : ĠString , Ġvalue : ĠEnum < *> ?): ĠUsage Descriptor Ġ{ ĊĠ Ġreturn ĠUsage Descriptor ( key Ġ+ Ġ"." Ġ+ Ġvalue ?. name ?. toLowerCase ( Locale . EN GL ISH ), Ġ 1 ) Ċ } Ċ Ċ /** Ċ Ġ* ĠConstructs Ġa Ġproper ĠUsage Descriptor Ġfor Ġa Ġcounting Ġvalue . Ċ Ġ* ĠIf Ġone Ġneeds Ġto Ġknow Ġa Ġnumber Ġof Ġsome Ġitems Ġin Ġthe Ġproject , Ġthere Ġis Ġno Ġdirect Ġway Ġto Ġreport Ġusage s Ġper - project . Ċ Ġ* ĠTherefore Ġthis Ġworkaround : Ġcreate Ġseveral Ġkeys Ġrepresenting Ġinteresting Ġranges , Ġand Ġreport Ġthat Ġkey Ġwhich Ġcorrespond Ġto Ġthe Ġrange Ċ Ġ* Ġwhich Ġthe Ġgiven Ġvalue Ġbelongs Ġto . Ċ Ġ* Ċ Ġ* ĠFor Ġexample , Ġto Ġreport Ġa Ġnumber Ġof Ġcommits Ġin ĠGit Ġrepository , Ġyou Ġcan Ġcall Ġthis Ġmethod Ġlike Ġthat : Ċ Ġ* Ġ``` Ċ Ġ* Ġval Ġusage Descriptor Ġ= Ġget Count ing Usage (" git . commit . count ", ĠlistOf ( 0 , Ġ 1 , Ġ 1 0 0 , Ġ 1 0 0 0 0 , Ġ 1 0 0 0 0 0 ), Ġreal Commit Count ) Ċ Ġ* Ġ``` Ċ Ġ* Ġand Ġif Ġthere Ġare Ġe . g . Ġ 5 0 0 0 0 Ġcommits Ġin Ġthe Ġrepository , Ġone Ġusage Ġof Ġthe Ġfollowing Ġkey Ġwill Ġbe Ġreported : Ġ` git . commit . count . 1 0 K + `. Ċ Ġ* Ċ Ġ* ĠNB : Ċ Ġ* Ġ( 1 ) Ġthe Ġlist Ġof Ġsteps Ġmust Ġbe Ġsorted Ġascending ly ; ĠIf Ġit Ġis Ġnot , Ġthe Ġresult Ġis Ġundefined . Ċ Ġ* Ġ( 2 ) Ġthe Ġvalue Ġshould Ġlay Ġsomewhere Ġinside Ġsteps Ġranges . ĠIf Ġit Ġis Ġbelow Ġthe Ġfirst Ġstep , Ġthe Ġfollowing Ġusage Ġwill Ġbe Ġreported : Ċ Ġ* Ġ` git . commit . count .< 1 `. Ċ Ġ* Ċ Ġ* Ġ@ key ĠĠ ĠThe Ġkey Ġprefix Ġwhich Ġwill Ġbe Ġappended Ġwith Ġ"." Ġand Ġrange Ġcode . Ċ Ġ* Ġ@ steps ĠLim its Ġof Ġthe Ġranges . ĠEach Ġvalue Ġrepresents Ġthe Ġstart Ġof Ġthe Ġnext Ġrange . ĠThe Ġlist Ġmust Ġbe Ġsorted Ġascending ly . Ċ Ġ* Ġ@ value ĠValue Ġto Ġbe Ġchecked Ġamong Ġthe Ġgiven Ġranges . Ċ Ġ*/ Ċ fun Ġget Count ing Usage ( key : ĠString , Ġvalue : ĠInt , Ġsteps : ĠList < Int >) Ġ: ĠUsage Descriptor Ġ{ ĊĠ Ġif Ġ( steps . isEmpty ()) Ġreturn ĠUsage Descriptor ("$ key .$ value ", Ġ 1 ) ĊĠ Ġif Ġ( value Ġ< Ġsteps [ 0 ]) Ġreturn ĠUsage Descriptor ("$ key .< ${ steps [ 0 ] }", Ġ 1 ) ĊĊĠ Ġvar Ġstep Index Ġ= Ġ 0 ĊĠ Ġwhile Ġ( step Index Ġ< Ġsteps . size Ġ- Ġ 1 ) Ġ{ ĊĠĠĠ Ġif Ġ( value Ġ< Ġsteps [ step Index Ġ+ Ġ 1 ]) Ġbreak ĊĠĠĠ Ġstep Index ++ ĊĠ Ġ} ĊĊĠ Ġval Ġstep Ġ= Ġsteps [ step Index ] ĊĠ Ġval Ġadd Plus Ġ= Ġstep Index Ġ== Ġsteps . size Ġ- Ġ 1 Ġ|| Ġsteps [ step Index Ġ+ Ġ 1 ] Ġ!= Ġstep Ġ+ Ġ 1 ĊĠ Ġval Ġstep Name Ġ= Ġhuman ize ( step ) Ġ+ Ġif Ġ( add Plus ) Ġ" +" Ġelse Ġ"" ĊĠ Ġreturn ĠUsage Descriptor ("$ key .$ step Name ", Ġ 1 ) Ċ } Ċ Ċ /** Ċ Ġ* Ġ[ getCount ing Usage ] Ġwith Ġsteps Ġ( 0 , Ġ 1 , Ġ 2 , Ġ 3 , Ġ 5 , Ġ 1 0 , Ġ 1 5 , Ġ 3 0 , Ġ 5 0 , Ġ 1 0 0 , Ġ 5 0 0 , Ġ 1 0 0 0 , Ġ 5 0 0 0 , Ġ 1 0 0 0 0 , Ġ...) Ċ Ġ*/ Ċ fun Ġget Count ing Usage ( key : ĠString , Ġvalue : ĠInt ): ĠUsage Descriptor Ġ{ ĊĠ Ġif Ġ( value Ġ> ĠInt . MAX _ VALUE Ġ/ Ġ 1 0 ) Ġreturn ĠUsage Descriptor ("$ key . MAN Y ", Ġ 1 ) ĊĠ Ġif Ġ( value Ġ< Ġ 0 ) Ġreturn ĠUsage Descriptor ("$ key .< 0 ", Ġ 1 ) ĊĠ Ġif Ġ( value Ġ< Ġ 3 ) Ġreturn ĠUsage Descriptor ("$ key .$ value ", Ġ 1 ) ĊĊĠ Ġval Ġfixed Steps Ġ= ĠlistOf ( 3 , Ġ 5 , Ġ 1 0 , Ġ 1 5 , Ġ 3 0 , Ġ 5 0 ) ĊĊĠ Ġvar Ġstep Ġ= Ġfixed Steps . last Ġ{ Ġit Ġ<= Ġvalue Ġ} ĊĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠ Ġif Ġ( value Ġ< Ġstep Ġ* Ġ 2 ) Ġbreak ĊĠĠĠ Ġstep Ġ*= Ġ 2 ĊĠĠĠ Ġif Ġ( value Ġ< Ġstep Ġ* Ġ 5 ) Ġbreak ĊĠĠĠ Ġstep Ġ*= Ġ 5 ĊĠ Ġ} ĊĊĠ Ġval Ġstep Name Ġ= Ġhuman ize ( step ) ĊĠ Ġreturn ĠUsage Descriptor ("$ key .$ step Name +", Ġ 1 ) Ċ } Ċ Ċ private Ġconst Ġval Ġk ilo Ġ= Ġ 1 0 0 0 Ċ private Ġval Ġme ga Ġ= Ġk ilo Ġ* Ġk ilo Ċ Ċ private Ġfun Ġhuman ize ( number : ĠInt ): ĠString Ġ{ ĊĠ Ġif Ġ( number Ġ== Ġ 0 ) Ġreturn Ġ" 0 " ĊĠ Ġval Ġm Ġ= Ġnumber Ġ/ Ġme ga ĊĠ Ġval Ġk Ġ= Ġ( number Ġ% Ġme ga ) Ġ/ Ġk ilo ĊĠ Ġval Ġr Ġ= Ġ( number Ġ% Ġk ilo ) ĊĠ Ġval Ġms Ġ= Ġif Ġ( m Ġ> Ġ 0 ) Ġ"${ m } M " Ġelse Ġ"" ĊĠ Ġval Ġks Ġ= Ġif Ġ( k Ġ> Ġ 0 ) Ġ"${ k } K " Ġelse Ġ"" ĊĠ Ġval Ġrs Ġ= Ġif Ġ( r Ġ> Ġ 0 ) Ġ"${ r }" Ġelse Ġ"" ĊĠ Ġreturn Ġms Ġ+ Ġks Ġ+ Ġrs Ċ } Ċ Ċ fun Ġ< T > Ġadd If Diff ers ( set : ĠMutable Set < in ĠUsage Descriptor >, Ġsettings Bean : ĠT , Ġdefault Settings Bean : ĠT , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvalue Function : Ġ( T ) Ġ-> ĠAny , Ġfeature Id Prefix : ĠString ) Ġ{ ĊĠ Ġadd If Diff ers ( set , Ġsettings Bean , Ġdefault Settings Bean , Ġvalue Function , Ġ{ Ġ"$ feature Id Prefix .$ it " Ġ}) Ċ } Ċ Ċ fun Ġ< T , ĠV > Ġadd If Diff ers ( set : ĠMutable Set < in ĠUsage Descriptor >, Ġsettings Bean : ĠT , Ġdefault Settings Bean : ĠT , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvalue Function : Ġ( T ) Ġ-> ĠV , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfeature Id Function : Ġ( V ) Ġ-> ĠString ) Ġ{ ĊĠ Ġval Ġvalue Ġ= Ġvalue Function ( settings Bean ) ĊĠ Ġval ĠdefaultValue Ġ= Ġvalue Function ( default Settings Bean ) ĊĠ Ġif Ġ(! Comp aring . equal ( value , ĠdefaultValue )) Ġ{ ĊĠĠĠ Ġset . add ( Usage Descriptor ( feature Id Function ( value ), Ġ 1 )) ĊĠ Ġ} Ċ } Ċ Ċ fun Ġto Usage Descriptors ( result : ĠObject Int HashMap < String >): ĠSet < Usage Descriptor > Ġ{ ĊĠ Ġif Ġ( result . isEmpty ) Ġ{ ĊĠĠĠ Ġreturn Ġempty Set () ĊĠ Ġ} ĊĠ Ġelse Ġ{ ĊĠĠĠ Ġval Ġdescriptors Ġ= ĠT HashSet < Usage Descriptor >( result . size ()) ĊĠĠĠ Ġresult . forEach Entry Ġ{ Ġkey , Ġvalue Ġ-> ĊĠĠĠĠĠ Ġdescriptors . add ( Usage Descriptor ( key , Ġvalue )) ĊĠĠĠĠĠ Ġtrue ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġdescriptors ĊĠ Ġ} Ċ } Ċ Ċ fun Ġmerge ( first : ĠSet < Usage Descriptor >, Ġsecond : ĠSet < Usage Descriptor >): ĠSet < Usage Descriptor > Ġ{ ĊĠ Ġif Ġ( first . isEmpty ()) Ġ{ ĊĠĠĠ Ġreturn Ġsecond ĊĠ Ġ} ĊĊĠ Ġif Ġ( second . isEmpty ()) Ġ{ ĊĠĠĠ Ġreturn Ġfirst ĊĠ Ġ} ĊĊĠ Ġval Ġmerged Ġ= ĠObject Int HashMap < String >() ĊĠ Ġadd All ( merged , Ġfirst ) ĊĠ Ġadd All ( merged , Ġsecond ) ĊĠ Ġreturn Ġto Usage Descriptors ( merged ) Ċ } Ċ Ċ private Ġfun Ġadd All ( result : ĠObject Int HashMap < String >, Ġusage s : ĠSet < Usage Descriptor >) Ġ{ ĊĠ Ġfor Ġ( usage Ġin Ġusage s ) Ġ{ ĊĠĠĠ Ġval Ġkey Ġ= Ġusage . key ĊĠĠĠ Ġresult . put ( key , Ġresult . get ( key , Ġ 0 ) Ġ+ Ġusage . value ) ĊĠ Ġ} Ċ } Ċ Ċ private Ġval Ġsafe To Report Plugin Ids : ĠSet < String > ĊĠ Ġget () Ġ{ ĊĠĠĠ Ġval Ġproject Ġ= ĠDefault Project Factory . getInstance (). default Project ĊĠĠĠ Ġreturn ĠCached Values Manager . getManager ( project ). get Cached Value ( project ) Ġ{ ĊĠĠĠĠĠ Ġval Ġplugins Ġ= Ġcollect Safe Plugin Descriptors () ĊĠĠĠĠĠ Ġval Ġids Ġ= Ġmutable Set Of < String >() ĊĠĠĠĠĠ Ġplugins . map NotNull To ( ids ) Ġ{ Ġdescriptor : ĠPlugin Descriptor Ġ-> Ġdescriptor . plugin Id ?. id String Ġ} ĊĠĠĠĠĠ ĠCached Value Provider . Result . create ( ids , ĠDelay Modification Tracker ( 1 , ĠTimeUnit . HOUR S )) ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ Ċ /** Ċ Ġ* ĠWe Ġare Ġsafe Ġto Ġreport Ġonly Ġplugins Ġwhich Ġare Ġdeveloped Ġby ĠJetBrains Ġor Ġin Ġour Ġofficial Ġplugin Ġrepository Ġdue Ġto ĠG DPR Ċ Ġ*/ Ċ private Ġfun Ġcollect Safe Plugin Descriptors (): ĠList < Ide a Plugin Descriptor > Ġ{ ĊĠ Ġ// Ġbefore Ġloading Ġdefault Ġrepository Ġplugins Ġlets Ġcheck Ġit 's Ġnot Ġchanged , Ġand Ġis Ġreally Ġofficial ĠJetBrains Ġrepository ĊĠ Ġif Ġ( Application Info Ex . getInstance Ex (). uses Jet Brains Plugin Repository ()) Ġ{ ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠ Ġval Ġcached Ġ= ĠRepository Helper . load Cached Plugins () ĊĠĠĠĠĠ Ġif Ġ( cached Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġplugins Ġ= ĠArrayList < Ide a Plugin Descriptor >() ĊĠĠĠĠĠĠĠ Ġplugins . addAll ( cached ) ĊĠĠĠĠĠĠĠ Ġplugins . addAll ( getB und led Jet Brains Plugin Descriptors ()) ĊĠĠĠĠĠĠĠ Ġreturn Ġplugins ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġschedule Ġplugins Ġloading , Ġwill Ġtake Ġthem Ġthe Ġnext Ġtime ĊĠĠĠĠĠĠĠ ĠApplication Manager . getApplication (). execute On P ooled Thread Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠRepository Helper . load Plugins ( null ) ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġcatch Ġ( ignored : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġempty List () Ġ// report Ġnothing Ġuntil Ġrepo Ġplugins Ġloaded ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġcatch Ġ( ignored : ĠIOException ) Ġ{ ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġreturn Ġget Bund led Jet Brains Plugin Descriptors () Ċ } Ċ Ċ /** Ċ Ġ* ĠNote Ġthat Ġthere Ġmay Ġbe Ġprivate Ġcustom ĠIDE Ġbuild Ġwith Ġbundled Ġcustom Ġplugins ; Ċ Ġ* Ġso Ġis Bund led Ġcheck Ġis Ġnot Ġenough Ċ Ġ*/ Ċ private Ġfun Ġget Bund led Jet Brains Plugin Descriptors (): ĠList < Ide a Plugin Descriptor > Ġ{ ĊĠ Ġreturn ĠPlugin Manager . get Plugins (). filter Ġ{ Ġit . is Bund led Ġ&& ĠPlugin Manager Main . is Develop edBy Jet Brains ( it ) Ġ}. toList () Ċ } Ċ Ċ /** Ċ Ġ* ĠChecks Ġthis Ġplugin Ġis Ġcreated Ġby ĠJetBrains Ġor Ġfrom Ġofficial Ġrepository , Ġso ĠAPI Ġfrom Ġit Ġmay Ġbe Ġreported Ċ Ġ*/ Ċ fun Ġis Safe To Report From ( descriptor : ĠIde a Plugin Descriptor ?): ĠBoolean Ġ{ ĊĠ Ġif Ġ( descriptor Ġ== Ġnull ) Ġ{ ĊĠĠĠ Ġreturn Ġfalse ĊĠ Ġ} ĊĠ Ġif Ġ( is Develop edBy Jet Brains ( descriptor . plugin Id )) Ġ{ ĊĠĠĠ Ġreturn Ġtrue ĊĠ Ġ} ĊĊĠ Ġ// Ġonly Ġplugins Ġinstalled Ġfrom Ġsome Ġrepository Ġ( not Ġbundled Ġand Ġnot Ġprovided Ġvia Ġclasspath Ġin Ġdevelopment ĠIDE Ġinstance Ġ- ĊĠ Ġ// Ġthey Ġare Ġalso Ġconsidered Ġbundled ) Ġwould Ġbe Ġreported ĊĠ Ġreturn Ġ! descriptor . is Bund led Ġ&& Ġis Safe To Report ( descriptor . plugin Id ?. id String ) Ċ } Ċ Ċ /** Ċ Ġ* ĠChecks Ġplugin Ġwith Ġsame Ġid Ġis Ġcreated Ġby ĠJetBrains Ġor Ġfrom Ġofficial Ġrepository , Ġso Ġplugin Id Ġmay Ġbe Ġreported . Ċ Ġ* Ċ Ġ* ĠOn Ġthe Ġvery Ġfirst Ġinvocation Ġmay Ġneed Ġto Ġload Ġcached Ġplugins Ġlater ; Ġin Ġthat Ġcase Ġno Ġplugins Ġare Ġconsidered Ġsafe Ċ Ġ*/ Ċ fun Ġis Safe To Report ( plugin Id : ĠString ?): ĠBoolean Ġ{ ĊĠ Ġreturn Ġplugin Id Ġ!= Ġnull Ġ&& Ġsafe To Report Plugin Ids . contains ( plugin Id ) Ċ } Ċ Ċ /** Ċ Ġ* ĠReturns Ġif Ġthis Ġcode Ġis Ġcoming Ġfrom ĠIntelliJ Ġplatform , Ġa Ġplugin Ġcreated Ġby ĠJetBrains Ġ( bund led Ġor Ġnot ) Ġor Ġfrom Ġofficial Ġrepository , Ċ Ġ* Ġso ĠAPI Ġfrom Ġit Ġmay Ġbe Ġreported Ċ Ġ*/ Ċ fun Ġget Plugin Type ( clazz : ĠClass < *> ): ĠPlugin Type Ġ{ ĊĠ Ġval Ġplugin Id Ġ= ĠPlugin Manager Core . get Plugin By ClassName ( clazz . name ) Ġ?: Ġreturn ĠPlugin Type . PLATFORM ĊĠ Ġval Ġplugin Ġ= ĠPlugin Manager . get Plugin ( plugin Id ) Ġ?: Ġreturn ĠPlugin Type . UNKNOWN ĊĊĠ Ġif Ġ( PluginManager Main . is Develop edBy Jet Brains ( plugin )) Ġ{ ĊĠĠĠ Ġreturn Ġif Ġ( plugin . is Bund led ) ĠPlugin Type . JB _ B UND LED Ġelse ĠPlugin Type . JB _ NOT _ B UND LED ĊĠ Ġ} ĊĊĠ Ġ// Ġonly Ġplugins Ġinstalled Ġfrom Ġsome Ġrepository Ġ( not Ġbundled Ġand Ġnot Ġprovided Ġvia Ġclasspath Ġin Ġdevelopment ĠIDE Ġinstance Ġ- ĊĠ Ġ// Ġthey Ġare Ġalso Ġconsidered Ġbundled ) Ġwould Ġbe Ġreported ĊĠ Ġval Ġlisted Ġ= Ġ! plugin . is Bund led Ġ&& Ġis Safe To Report ( plugin Id . id String ) ĊĠ Ġreturn Ġif Ġ( listed ) ĠPlugin Type . LIST ED Ġelse ĠPlugin Type . NOT _ LIST ED Ċ } Ċ Ċ private Ġclass ĠDelay Modification Tracker Ġinternal Ġconstructor ( delay : ĠLong , Ġunit : ĠTimeUnit ) Ġ: ĠMod ification Tracker Ġ{ ĊĊĠ Ġprivate Ġval Ġmy Stamp Ġ= ĠSystem . currentTimeMillis () ĊĠ Ġprivate Ġval Ġmy Delay : ĠLong Ġ= ĠTimeUnit . MILLISECONDS . convert ( delay , Ġunit ) ĊĊĠ Ġoverride Ġfun Ġget Modification Count (): ĠLong Ġ{ ĊĠĠĠ Ġval Ġdiff Ġ= ĠSystem . currentTimeMillis () Ġ- Ġ( my Stamp Ġ+ Ġmy Delay ) ĊĠĠĠ Ġreturn Ġif Ġ( diff Ġ> Ġ 0 ) Ġdiff Ġelse Ġ 0 ĊĠ Ġ} Ċ } Ċ