/* Ċ Ġ* ĠCopyright Ġ 2 0 2 0 ĠAnt on ĠNov ik au Ċ Ġ* Ċ Ġ* Ġ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 Ġb oring y uri . processor Ċ Ċ import Ġb oring y uri . api . DefaultValue Ċ import Ġb oring y uri . api . Param Ċ import Ġb oring y uri . api . Path Ċ import Ġb oring y uri . api . Uri Data Ċ import Ġb oring y uri . processor . base . Processing Session Ċ import Ġb oring y uri . processor . ext . create Field Spec Ċ import Ġb oring y uri . processor . ur ip art . Method Read Path Segment Ċ import Ġb oring y uri . processor . ur ip art . Method Read QueryParameter Ċ import Ġb oring y uri . processor . ur ip art . Read QueryParameter Ċ import Ġb oring y uri . processor . ur ip art . Template Path Segment Ċ import Ġb oring y uri . processor . util . Annotation Handler Ċ import Ġb oring y uri . processor . util . Processor Options Ċ import Ġcom . google . common . collect . Immutable Set Ċ import Ġcom . google . common . collect . Immutable Set Multimap Ċ import Ġcom . squareup . jav ap o et . ClassName Ċ import Ġcom . squareup . jav ap o et . Field Spec Ċ import Ġcom . squareup . jav ap o et . TypeName Ċ import Ġorg . apache . commons . lang 3 . StringUtils Ċ import Ġjavax . lang . model . element .* Ċ import Ġjavax . lang . model . util . Element Filter Ċ Ċ class ĠIndependent Uri Data Generator Step ( ĊĠĠĠ Ġsession : ĠProcessing Session , ĊĠĠĠ Ġannotation Handler : ĠAnnotation Handler Ċ ) Ġ: ĠUri Data Generator Step ( session , Ġannotation Handler ) Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġannotations (): ĠSet < String > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠImmutable Set . of ( Uri Data :: class . java . name ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġprocess ( ĊĠĠĠĠĠĠĠ Ġelements By Annotation : ĠImmutable Set Multimap < String , ĠElement > ĊĠĠĠ Ġ): ĠSet < Element > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġannotated Classes Ġ= ĠElement Filter . types In ( elements By Annotation [ Uri Data :: class . java . name ]) ĊĠĠĠĠĠĠĠ Ġval Ġdeferred Ġ= Ġhash Set Of < Element >() ĊĠĠĠĠĠĠĠ Ġfor Ġ( annotated Class Ġin Ġannotated Classes ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( annotated Class . kind Ġ!= ĠElement Kind . INTERFACE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġannotated Class , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"@ % s Ġcan Ġonly Ġbe Ġapplied Ġto Ġinterface ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUri Data :: class . java . simple Name ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmodifiers Ġ= Ġannotated Class . modifiers ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( modifiers . contains ( Modifier . PRIVATE )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġannotated Class , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"@ % s Ġcan Ġnot Ġbe Ġapplied Ġto Ġa Ġprivate Ġinterface ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUri Data :: class . simple Name ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuri Metadata Ġ= Ġobtain Uri Metadata ( annotated Class ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġgenerated Ġ= Ġgenerate Uri Data Class ( annotated Class , Ġuri Metadata ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! generated ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdeferred . add ( annotated Class ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġdeferred ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġobtain Uri Metadata ( source Element : ĠType Element ): ĠUri Metadata Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġuri Data Annotation : ĠUri Data Ġ= Ġsource Element . getAnnotation ( Uri Data :: class . java ) ĊĊĠĠĠĠĠĠĠ Ġval ĠbasePath Ġ= Ġuri Data Annotation . value ĊĠĠĠĠĠĠĠ Ġ// ĠBase Ġpath Ġmay Ġcontain Ġconstant Ġsegments , Ġwildcard Ġsegments Ġand Ġtemplates ĊĠĠĠĠĠĠĠ Ġ// Ġfor Ġmethod Ġparameters . ĠWe Ġwill Ġreplace Ġthe Ġtemplates Ġwith Ġthe Ġpath Ġparameters ĊĠĠĠĠĠĠĠ Ġ// Ġon Ġthe Ġnext Ġstep . ĠAll Ġconstants Ġand Ġwild cards Ġwill Ġbe Ġfiltered Ġout Ġon Ġobtaining ĊĠĠĠĠĠĠĠ Ġ// Ġthe Ġbase Ġpath Ġsegments . ĊĠĠĠĠĠĠĠ Ġval Ġsegments Ġ= Ġobtain BasePath Segments ( basePath , Ġsource Element ) ĊĠĠĠĠĠĠĠ Ġval Ġfield Specs Ġ= Ġarray ListOf < Field Spec >() ĊĠĠĠĠĠĠĠ Ġval ĠqueryParams Ġ= Ġarray ListOf < Read QueryParameter >() ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( element Ġin Ġsource Element . enc losed Elements ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmethod Ġ= Ġto Executable Element OrNull ( element ) Ġ?: Ġcontinue ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠmethodName Ġ= Ġmethod . simple Name . toString () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparam Name Ġ= ĠStringUtils . unc ap ital ize ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠGET TER _ PATTERN . find ( methodName )?. run Ġ{ Ġgroup Values [ 1 ] Ġ} Ġ?: ĠmethodName ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠdefaultValue Ġ= Ġmethod . getAnnotation ( DefaultValue :: class . java )?. value ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfield Ġ= Ġmethod . create Field Spec ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparam Name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠdefaultValue , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġannotation Handler ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ). also Ġ{ Ġfield Specs . add ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnullable Ġ= Ġannotation Handler . is Nullable ( method . returnType , Ġmethod ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpath Annotation : ĠPath ? Ġ= Ġmethod . getAnnotation ( Path :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( path Annotation Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( nullable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error ( method , Ġ" Return Ġtype Ġof Ġthe Ġpath Ġsegment Ġgetter Ġ'$ methodName () '" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Ġmust Ġbe Ġexplicitly Ġnon - null .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpath Name Ġ= Ġpath Annotation . value . if Empty Ġ{ Ġparam Name Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpath Segment Ġ= Ġsegments [ path Name ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsegment Index Ġ= Ġif Ġ( path Segment Ġis ĠTemplate Path Segment ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath Segment . segment Index ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠProcessor Options . warn Ordered Segments Usage ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsession , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath Name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbasePath , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUri Data :: class , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmethod ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġnon - named Ġpath Ġsegment Ġwill Ġbe Ġadded Ġto Ġthe Ġend Ġof Ġthe Ġmap ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsegments . size ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠPrevious ly Ġsaved ĠVariable Name Segment Ġhelps Ġto Ġpreserve ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthe Ġsegment Ġposition Ġof Ġthe Ġexpected ĠUri Ġpath . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsegments [ path Name ] Ġ= ĠMethod Read Path Segment ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsegment Index , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath Name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfield , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġuri Field , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠdefaultValue , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmethod ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparam Annotation : ĠParam Ġ= Ġmethod . getAnnotation ( Param :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġquery ParamName Ġ= Ġparam Annotation . value . if Empty Ġ{ Ġparam Name Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠqueryParams . add ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMethod Read QueryParameter ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġquery ParamName , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfield , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġuri Field , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnullable , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠdefaultValue , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmethod ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠUri Metadata ( field Specs , Ġsegments . values . toList (), ĠqueryParams ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġto Executable Element OrNull ( element : ĠElement ): ĠExec utable Element ? Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( Element Kind . METHOD Ġ!= Ġelement . kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull Ġ Ġ// Ġskip Ġnon - method Ġmembers ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġmodifiers Ġ= Ġelement . modifiers ĊĠĠĠĠĠĠĠ Ġif Ġ( modifiers . contains ( Modifier . STATIC ) Ġ|| Ġmodifiers . contains ( Modifier . DEFAULT )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull Ġ Ġ// Ġskip Ġstatic Ġor Ġdefault Ġmethods ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġmethod Element Ġ= Ġelement Ġas ĠExec utable Element ĊĠĠĠĠĠĠĠ Ġif Ġ( element . getAnnotation ( Path :: class . java ) Ġ== Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ&& Ġelement . getAnnotation ( Param :: class . java ) Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmethod Element , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"' ${ method Element . simple Name }' Ġmust Ġhave Ġeither Ġ@ % s Ġor Ġ@ % s ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPath :: class . simple Name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠParam :: class . simple Name ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull Ġ// Ġskip Ġunsupported Ġmethod ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval ĠreturnType Ġ= ĠType Name . get ( method Element . returnType ) ĊĠĠĠĠĠĠĠ Ġif Ġ( TypeName . VOID Ġ== ĠreturnType ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelement , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"@ % s Ġand Ġ@ % s Ġcan Ġbe Ġapplied Ġonly Ġto Ġgetter Ġmethods ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPath :: class . simple Name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠParam :: class . simple Name ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull Ġ Ġ// Ġskip Ġunsupported Ġmethod ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( method Element . parameters . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparameters Ġ= Ġmethod Element . parameters . join ToString Ġ{ Ġit . simple Name Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn ( element , Ġ" Method Ġparameters Ġ[$ parameters ] Ġwill Ġbe Ġignored ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġmethod Element ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġgenerate Uri Data Class ( ĊĠĠĠĠĠĠĠ Ġsource Element : ĠType Element , ĊĠĠĠĠĠĠĠ Ġuri Metadata : ĠUri Metadata ĊĠĠĠ Ġ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġpackage Element Ġ= Ġelement Utils . get Package Of ( source Element ) ĊĠĠĠĠĠĠĠ Ġval ĠpackageName Ġ= Ġpackage Element . qualified Name . toString () ĊĠĠĠĠĠĠĠ Ġval Ġsimple ClassName Ġ= Ġsource Element . simple Name . toString () Ġ+ ĠCON TAIN ER _ IMPL _ SUFFIX ĊĠĠĠĠĠĠĠ Ġval ĠclassName Ġ= ĠClass Name . get ( packageName , Ġsimple ClassName ) ĊĊĠĠĠĠĠĠĠ Ġval Ġcontent Ġ= Ġgenerate Uri Data Class Content ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠclassName , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsource Element , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuri Metadata , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠType Name . get ( source Element . as Type ()) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġwrite SourceFile ( className , Ġcontent , Ġsource Element ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠCON TAIN ER _ IMPL _ SUFFIX Ġ= Ġ" Impl " ĊĠĠĠĠĠĠĠ Ġval ĠGET TER _ PATTERN Ġ= Ġ"^ (?: get | is | has | are ) ([ A - Z ][ a - zA - Z 0 - 9 ]+ )$ ". to Regex () ĊĠĠĠ Ġ} Ċ Ċ }