/* Ċ Ġ* ĠCopyright Ġ 2 0 1 8 ĠR ak uten Ġ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 . r ak uten . tech . mobile . manifest config . processor Ċ Ċ import Ġcom . google . auto . service . Auto Service Ċ import Ġcom . r ak uten . tech . mobile . manifest config . annotations . Manifest Config Ċ import Ġcom . r ak uten . tech . mobile . manifest config . annotations . MetaData Ċ import Ġcom . squareup . jav ap o et .* Ċ import Ġcom . sun . tools . javac . code . Type Ċ import Ġjavax . annotation . processing .* Ċ import Ġjavax . lang . model . Source Version Ċ import Ġjavax . lang . model . element . Element Ċ import Ġjavax . lang . model . element . Element Kind Ċ import Ġjavax . lang . model . element . Modifier Ċ import Ġjavax . lang . model . element . Type Element Ċ import Ġjavax . lang . model . util . Elements Ċ import Ġjavax . lang . model . util . Types Ċ import Ġjavax . tools . Diagnostic Ċ Ċ @ Suppress (" NO _ REF LECTION _ IN _ CLASS _ PATH ") Ċ @ Auto Service ( Processor :: class ) Ċ class ĠManifest Config Processor Ġ: ĠAbstract Processor () Ġ{ ĊĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġtype Utils : ĠTypes ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġcode Generator : ĠManifest Config Generator ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġmess ager : ĠMess ager ĊĠĠĠ Ġprivate Ġval Ġannotated Interfaces : ĠMutable List < Type Element > Ġ= Ġmutable ListOf () ĊĊĠĠĠ Ġoverride Ġfun Ġinit ( processing Env : ĠProcessing Environment ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . init ( processing Env ) ĊĠĠĠĠĠĠĠ Ġtype Utils Ġ= Ġprocessing Env !!. type Utils ĊĠĠĠĠĠĠĠ Ġcode Generator Ġ= ĠManifest Config Generator ( processing Env . element Utils , Ġprocessing Env . filer ) ĊĠĠĠĠĠĠĠ Ġmess ager Ġ= Ġprocessing Env . mess ager ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġprocess ( annotations : ĠSet < Type Element >, Ġround Env : ĠRound Environment ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġfor Ġ( elem Ġ Ġin Ġround Env . getElement s Annotated With ( Manifest Config :: class . java )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( elem . kind Ġ!= ĠElement Kind . INTERFACE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelem , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Only Ġinterfaces Ġcan Ġbe Ġannotated Ġwith Ġ@ % s ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠManifest Config :: class . simple Name !! ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġannotated Interfaces . add ( elem Ġas ĠType Element ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( config To Generate Ġin Ġannotated Interfaces ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcode Generator . generate Class ( config To Generate ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠManifest Config Generator Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror ( config To Generate , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġe . message Ġ?: ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Failed Ġto Ġgenerate Ġimplementation Ġfor Ġ${ config To Generate . simple Name }" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġannotated Interfaces . clear () ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Supported Source Version (): ĠSource Version Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠSource Version . latest Supported () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Supported Annotation Types (): ĠMutable Set < String > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġmutable Set Of ( Manifest Config :: class . java . name ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġerror ( e : ĠElement , Ġmsg : ĠString , Ġvar arg Ġargs : ĠAny ) Ġ{ ĊĠĠĠĠĠĠĠ Ġmess ager . print Message ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠDiagnostic . Kind . ERROR , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠString . format ( msg , Ġ* args ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġe ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ class ĠManifest Config Interface ( val Ġelement : ĠType Element ) Ċ Ċ val ĠCON TEXT : ĠClass Name Ġ= ĠClass Name . get (" android . content ", Ġ" Context ") Ċ val ĠPACK AGE _ MANAGER : ĠClass Name Ġ= ĠClass Name . get (" android . content . pm ", Ġ" PackageManager ") Ċ val ĠB UNDLE : ĠClass Name Ġ= ĠClass Name . get (" android . os ", Ġ" Bundle ") Ċ val ĠNAME _ NOT _ FOUND _ EXCEPTION : ĠClass Name Ġ= ĠClass Name . get (" android . content . pm ", Ġ" PackageManager . Name NotFoundException ") Ċ Ċ class ĠManifest Config Generator ( ĊĠĠĠ Ġprivate Ġval Ġelement Utils : ĠElements , ĊĠĠĠ Ġprivate Ġval Ġf iler : ĠF iler Ċ ) Ġ{ ĊĊĠĠĠ Ġfun Ġgenerate Class ( config : ĠType Element ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġconstructor Ġ= Ġconstructor () ĊĊĠĠĠĠĠĠĠ Ġval Ġclass Builder Ġ= ĠType Spec . class Builder ("${ config . simple Name } Manifest Config ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Super interface ( TypeName . get ( config . as Type ())) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Modifiers ( Modifier . PUBLIC , ĠModifier . FINAL ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addField ( B UNDLE , Ġ" metaData ", ĠModifier . PRIVATE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Method ( constructor ) ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( member Ġin Ġconfig . enc losed Elements ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( member . kind Ġ== ĠElement Kind . METHOD ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclass Builder . add Method ( config Method ( member )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġjava File Ġ= ĠJava File . builder ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelement Utils . get Package Of ( config ). qualified Name . toString (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclass Builder . build () ĊĠĠĠĠĠĠĠ Ġ). build () ĊĊĠĠĠĠĠĠĠ Ġjava File . writeTo ( filer ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġconfig Method ( member : ĠElement ): ĠMethod Spec Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġtype Ġ= Ġmember . as Type () Ġas ĠType . MethodType ĊĠĠĠĠĠĠĠ Ġval Ġconst Name Ġ= Ġconstant Name ( member ) ĊĠĠĠĠĠĠĠ Ġval ĠreturnType Ġ= ĠType Name . get ( type . returnType ) ĊĠĠĠĠĠĠĠ Ġval Ġreturn Fallback Value Ġ= Ġreturn Fallback Value ( returnType , Ġmember ) ĊĊĠĠĠĠĠĠĠ Ġreturn ĠMethod Spec . method Builder ( member . simple Name . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Annotation ( Override :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Modifiers ( Modifier . PUBLIC ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Statement ( read From Bundle ( returnType ), Ġ" metaData ", Ġconst Name , Ġreturn Fallback Value ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. returns ( returnType ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġconstant Name ( member : ĠElement ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠmethodName Ġ= Ġmember . simple Name . toString () ĊĠĠĠĠĠĠĠ Ġval Ġannotation Ġ= Ġmember . getAnnotation ( MetaData :: class . java ) ĊĠĠĠĠĠĠĠ Ġval Ġkey Ġ= Ġannotation ?. key ĊĠĠĠĠĠĠĠ Ġval Ġconstant Name Ġ= Ġif Ġ( key . isNull OrEmpty ()) ĠmethodName . capitalize () Ġelse Ġkey !! ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstant Name . isBlank () Ġ-> Ġthrow ĠInvalid Key Exception (" Cannot Ġuse Ġempty Ġmeta Ġkey ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconstant Name . any Ġ{ Ġit . is Whitespace () Ġ} Ġ-> Ġthrow ĠInvalid Key Exception (" Cannot Ġuse Ġwhitespace Ġin Ġmeta Ġkey ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġconstant Name ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġreturn Fallback Value ( returnType : ĠType Name , Ġmember : ĠElement ): ĠAny Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġannotation Ġ= Ġmember . getAnnotation ( MetaData :: class . java ) ĊĠĠĠĠĠĠĠ Ġval Ġvalue Ġ= Ġannotation ?. value ?. to Value ( returnType ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ( returnType . toString ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" int ", Ġ" java . lang . Integer " ĠĠĠĠ Ġ-> Ġvalue Ġ?: Ġ- 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" boolean ", Ġ" java . lang . Boolean " Ġ-> Ġvalue Ġ?: Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" float ", Ġ" java . lang . Float " ĠĠĠĠ Ġ-> Ġvalue Ġ?: Ġ- 1 f ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" java . lang . String " ĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> Ġvalue Ġ?: Ġ"" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠUnsupported Type Exception ( returnType ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġread From Bundle ( returnType : ĠType Name ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen ( returnType . toString ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" int ", Ġ" java . lang . Integer " ĠĠĠĠĠ Ġ-> Ġ" return Ġ\$ N . getInt (\ $ S , Ġ\$ L )" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" boolean ", Ġ" java . lang . Boolean " Ġ Ġ-> Ġ" return Ġ\$ N . getBoolean (\ $ S , Ġ\$ L )" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" float ", Ġ" java . lang . Float " ĠĠĠĠĠ Ġ-> Ġ" return Ġ\$ N . get Float (\ $ S , Ġ\$ Lf )" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" java . lang . String " ĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ-> Ġ" return Ġ\$ N . getString (\ $ S , Ġ\$ S )" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠUnsupported Type Exception ( returnType ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġconstructor (): ĠMethod Spec Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠMethod Spec . constructor Builder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Modifiers ( Modifier . PUBLIC ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Parameter ( CONTEXT , Ġ" context ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Statement (" this .\ $ N Ġ= Ġnew Ġ\$ T ()", Ġ" metaData ", ĠB UNDLE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. begin Control Flow (" try ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Statement ("\ $ T Ġ\$ N Ġ= Ġcontext . get PackageManager ()", ĠPACK AGE _ MANAGER , Ġ" pm ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Statement ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"\ $ T Ġ\$ N Ġ= Ġ\$ N . getApplication Info ( context . get PackageName (), ĠPackage Manager . GET _ META _ DATA ). metaData ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠB UNDLE , Ġ" app Meta ", Ġ" pm " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. begin Control Flow (" if Ġ(\ $ N Ġ!= Ġnull )", Ġ" app Meta ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Statement (" this .\ $ N Ġ= Ġ\$ N ", Ġ" metaData ", Ġ" app Meta ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. end Control Flow () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. next Control Flow (" catch Ġ(\ $ T Ġignored )", ĠNAME _ NOT _ FOUND _ EXCEPTION ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Comment (" if Ġwe Ġcan 't Ġget Ġmetadata Ġwe 'll Ġuse Ġdefault Ġconfig ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. end Control Flow () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠ Ġ} Ċ } Ċ Ċ open Ġclass ĠManifest Config Generator Exception ( msg : ĠString ) Ġ: ĠException ( msg ) Ċ Ċ class ĠUnsupported Type Exception ( ĊĠĠĠ Ġtype : ĠType Name Ċ ) Ġ: ĠManifest Config Generator Exception (" Type Ġ$ type Ġnot Ġsupported Ġas Ġmanifest Ġconfig Ġtype .") Ċ Ċ class ĠInvalid Value Exception ( ĊĠĠĠ Ġtype : ĠType Name , ĊĠĠĠ Ġvalue : ĠString Ċ ) Ġ: ĠManifest Config Generator Exception (" Cannot Ġconvert Ġ\"$ value \" Ġinto Ġtype Ġ$ type ") Ċ Ċ class ĠInvalid Key Exception ( msg : ĠString ) Ġ: ĠManifest Config Generator Exception ( msg ) Ċ Ċ fun ĠString . to Value ( type : ĠType Name ): ĠAny ? Ġ{ ĊĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġwhen Ġ( type . toString ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" int ", Ġ" java . lang . Integer " Ġ-> Ġif Ġ( isEmpty ()) Ġnull Ġelse Ġto Int () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" boolean ", Ġ" java . lang . Boolean " Ġ-> Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . equals (" true ", Ġignore Case Ġ= Ġtrue ) Ġ-> Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . equals (" false ", Ġignore Case Ġ= Ġtrue ) Ġ-> Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . isEmpty () Ġ-> Ġnull Ġ// Ġdefault Ġvalue Ġof Ġannotation Ġproperty ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠException () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġparse Ġb ooleans Ġstrictly , Ġonly Ġ" true " Ġor Ġ" false Ġallowed Ġ( ign oring Ġcase ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" float ", Ġ" java . lang . Float " Ġ-> Ġif Ġ( isEmpty ()) Ġnull Ġelse Ġto Float () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" java . lang . String " Ġ-> Ġthis ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠUnsupported Type Exception ( type ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow Ġe Ġas ? ĠManifest Config Generator Exception Ġ?: ĠInvalid Value Exception ( type , Ġthis ) ĊĠĠĠ Ġ} Ċ }