/* Ċ Ġ* ĠOption Processor Factory . kt Ċ Ġ* ĠCopyright ĠÂ© Ġ 1 9 9 3 - 2 0 2 0 , ĠThe ĠAv ail ĠFoundation , ĠLLC . Ċ Ġ* ĠAll Ġrights Ġreserved . Ċ Ġ* Ċ Ġ* ĠRedistribution Ġand Ġuse Ġin Ġsource Ġand Ġbinary Ġforms , Ġwith Ġor Ġwithout Ċ Ġ* Ġmodification , Ġare Ġpermitted Ġprovided Ġthat Ġthe Ġfollowing Ġconditions Ġare Ġmet : Ċ Ġ* Ċ Ġ* Ġ* ĠRedistributions Ġof Ġsource Ġcode Ġmust Ġretain Ġthe Ġabove Ġcopyright Ġnotice , Ġthis Ċ Ġ* ĠĠ Ġlist Ġof Ġconditions Ġand Ġthe Ġfollowing Ġdisclaimer . Ċ Ġ* Ċ Ġ* Ġ* ĠRedistributions Ġin Ġbinary Ġform Ġmust Ġreproduce Ġthe Ġabove Ġcopyright Ġnotice , Ċ Ġ* ĠĠ Ġthis Ġlist Ġof Ġconditions Ġand Ġthe Ġfollowing Ġdisclaimer Ġin Ġthe Ġdocumentation Ċ Ġ* ĠĠ Ġand / or Ġother Ġmaterials Ġprovided Ġwith Ġthe Ġdistribution . Ċ Ġ* Ċ Ġ* Ġ* ĠNeither Ġthe Ġname Ġof Ġthe Ġcopyright Ġholder Ġnor Ġthe Ġnames Ġof Ġthe Ġcontributors Ċ Ġ* ĠĠ Ġmay Ġbe Ġused Ġto Ġendorse Ġor Ġpromote Ġproducts Ġderived Ġfrom Ġthis Ġsoftware Ċ Ġ* ĠĠ Ġwithout Ġspecific Ġprior Ġwritten Ġpermission . Ċ Ġ* Ċ Ġ* ĠTHIS ĠSOFTWARE ĠIS ĠPROVIDED ĠBY ĠTHE ĠCOPYRIGHT ĠHOLDERS ĠAND ĠCONTRIBUTORS Ġ" AS ĠIS " Ċ Ġ* ĠAND ĠANY ĠEXPRESS ĠOR ĠIMPLIED ĠWARRANTIES , ĠINCLUDING , ĠBUT ĠNOT ĠLIMITED ĠTO , ĠTHE Ċ Ġ* ĠIMPLIED ĠWARRANTIES ĠOF ĠMERCHANTABILITY ĠAND ĠFITNESS ĠFOR ĠA ĠPARTICULAR ĠPURPOSE Ċ Ġ* ĠARE ĠDISCLAIMED . ĠIN ĠNO ĠEVENT ĠSHALL ĠTHE ĠCOPYRIGHT ĠHOLDER ĠOR ĠCONTRIBUTORS ĠBE Ċ Ġ* ĠLIABLE ĠFOR ĠANY ĠDIRECT , ĠINDIRECT , ĠINCIDENTAL , ĠSPECIAL , ĠEXEMPLARY , ĠOR Ċ Ġ* ĠCONSEQUENTIAL ĠDAMAGES Ġ( INCLUDING , ĠBUT ĠNOT ĠLIMITED ĠTO , ĠPROCUREMENT ĠOF Ċ Ġ* ĠSUBSTITUTE ĠGOODS ĠOR ĠSERVICES ; ĠLOSS ĠOF ĠUSE , ĠDATA , ĠOR ĠPROFITS ; ĠOR ĠBUSINESS Ċ Ġ* ĠINTERRUPTION ) ĠHOWEVER ĠCAUSED ĠAND ĠON ĠANY ĠTHEORY ĠOF ĠLIABILITY , ĠWHETHER ĠIN Ċ Ġ* ĠCONTRACT , ĠSTRICT ĠLIABILITY , ĠOR ĠTORT Ġ( INCLUDING ĠNEGLIGENCE ĠOR ĠOTHERWISE ) Ċ Ġ* ĠARISING ĠIN ĠANY ĠWAY ĠOUT ĠOF ĠTHE ĠUSE ĠOF ĠTHIS ĠSOFTWARE , ĠEVEN ĠIF ĠADVISED ĠOF ĠTHE Ċ Ġ* ĠPOSSIBILITY ĠOF ĠSUCH ĠDAMAGE . Ċ Ġ*/ Ċ Ċ package Ġcom . avail . tools . options Ċ Ċ import Ġcom . avail . tools . options . Option Processor Factory . Cardinality . Companion . OPTIONAL Ċ import Ġcom . avail . utility . configuration . Configuration Ċ import Ġjava . util . Enum Set Ċ Ċ /** Ċ Ġ* ĠAn Ġ` Option Processor Factory ` Ġenables Ġa Ġclient Ġto Ġdynamically Ġspecify Ġand Ċ Ġ* Ġassemble Ġan Ġ[ option &# 3 2 ; processor ][ Option Processor ]. ĠIn Ġparticular , Ġthe Ċ Ġ* Ġfactory Ġallows Ġa Ġclient Ġto Ġflex ibly Ġdefine Ġa Ġparticular Ġoption Ġprocessor Ċ Ġ* Ġwhile Ġignoring Ġspecification Ġand Ġevaluation Ġorder Ġdependency . ĠValidation Ġis Ċ Ġ* Ġpost p oned Ġuntil Ġfinal Ġassembly Ġtime , Ġat Ġwhich Ġtime Ġa Ġ`[ ValidationException ]` Ċ Ġ* Ġwill Ġbe Ġthrown Ġin Ġthe Ġevent Ġof Ġincorrect Ġor Ġincomplete Ġspecification ; Ċ Ġ* Ġotherwise , Ġthe Ġconstructed Ġoption Ġprocessor Ġprov ably Ġreflect s Ġthe Ġclient Ċ Ġ* Ġspecification . Ċ Ġ* Ċ Ġ* Ġ@ param ĠOption KeyType Ċ Ġ* ĠĠ ĠThe Ġtype Ġof Ġthe Ġoption . Ċ Ġ* Ġ@ property Ġoption KeyType Ċ Ġ* ĠĠ ĠThe Ġ[ type ][ Class ] Ġof Ġoption Ġkeys . Ċ Ġ* Ġ@ author ĠT odd ĠL ĠSmith Ġ& lt ; tod d @ avail lang . org & gt ; Ċ Ġ* Ċ Ġ* Ġ@ constructor Ċ Ġ* Ċ Ġ* ĠConstruct Ġa Ġnew Ġ` Option Processor Factory `. Ċ Ġ* Ċ Ġ* Ġ@ param Ġoption KeyType Ċ Ġ* ĠĠ ĠThe Ġ[ type ][ Class ] Ġof Ġoption Ġkeys . Ċ Ġ*/ Ċ class ĠOption Processor Factory < Option KeyType Ġ: ĠEnum < Option KeyType >> Ċ ĉ private Ġconstructor Ġ( Ċĉ ĉ private Ġval Ġoption KeyType : ĠClass < Option KeyType >) Ċ { Ċ ĉ comp anion Ġobject Ġ{ Ċĉ ĉ inline Ġfun Ġ< re ified ĠO Ġ: ĠEnum < O >> Ġcreate ( Ċĉĉ ĉ no inline Ġsetup : ĠOption Processor Factory < O >. ()-> Unit Ċĉ ĉ ): ĠOption Processor < O > Ġ= Ġprivate Create ( O :: class . java , Ġsetup ) ĊĊĉ ĉ /** Ċĉĉ Ġ* ĠA Ġhelper Ġfactory Ġfunction . Ġ ĠUnfortunately , ĠKotlin 's Ġvisibility Ġrules Ċĉĉ Ġ* Ġ( effect ively Ġinherited Ġfrom Ġthe ĠJVM ) Ġfor Ġthings Ġaccessed Ġfrom Ġinline Ċĉĉ Ġ* Ġfunction Ġbodies Ġprevents Ġthis Ġfrom Ġbeing Ġhidden Ġentirely . Ċĉĉ Ġ*/ Ċĉ ĉ fun Ġ< O Ġ: ĠEnum < O >> Ġprivate Create ( Ċĉĉ ĉ option KeyType : ĠClass < O >, Ċĉĉ ĉ setup : ĠOption Processor Factory < O >. ()-> Unit Ċĉ ĉ ): ĠOption Processor < O > Ġ= Ċĉĉ ĉ with ( Option Processor Factory ( option KeyType )) Ġ{ Ċĉĉĉ ĉ setup () Ċĉĉĉ ĉ create Option Processor () Ċĉĉ ĉ } Ċ ĉ } ĊĊ ĉ /** ĠThe Ġ[ set ][ Set ] Ġof Ġall Ġ[ options ][ Option ]. Ġ Ġ*/ Ċ ĉ private Ġval Ġall Options Ġ= Ġmutable Set Of < Option < Option KeyType >>() ĊĊ ĉ /** ĠThe Ġrules Ġto Ġcheck , Ġin Ġorder , Ġfor Ġvalid Ġoptions Ġand Ġarguments . Ġ*/ Ċ ĉ private Ġval Ġall Rules Ġ= Ċĉ ĉ mutable ListOf < Option Processor < Option KeyType >. ()-> Unit >() ĊĊ ĉ /** ĠA Ġhelper Ġclass Ġto Ġmake Ġoption Ġbodies Ġmore Ġdirectly Ġexpress ible . Ġ*/ Ċ ĉ data Ġclass ĠOption Invocation < Option KeyType Ġ: ĠEnum < Option KeyType >>( Ċĉ ĉ val Ġprocessor : ĠOption Processor < Option KeyType >, Ċĉ ĉ val Ġkeyword : ĠString ) ĊĊ ĉ /** Ċĉ Ġ* ĠA Ġhelper Ġclass Ġto Ġmake Ġbodies Ġof Ġoptions Ġwith Ġarguments Ġmore Ġdirectly Ċĉ Ġ* Ġexpress ible . Ċĉ Ġ*/ Ċ ĉ data Ġclass ĠOption Invocation With Argument < Option KeyType Ġ: ĠEnum < Option KeyType >> Ċ ĉ ( Ċĉ ĉ val Ġprocessor : ĠOption Processor < Option KeyType >, Ċĉ ĉ val Ġkeyword : ĠString , Ċĉ ĉ val Ġargument : ĠString ) ĊĊ ĉ /** Ċĉ Ġ* ĠAn Ġoptional Ġparameter Ġwhen Ġdefining Ġan Ġ[ option ] Ġor Ġ[ option With Argument ], Ċĉ Ġ* Ġto Ġindicate Ġhow Ġmany Ġoccurrences Ġof Ġthe Ġoption Ġare Ġpermitted / required . Ċĉ Ġ* ĠFor Ġmore Ġprecise Ġcontrol , Ġthe Ġoption Ġbody Ġcan Ġuse Ċĉ Ġ* Ġ[ Option Processor . check Encounter ed ] Ġduring Ġprocessing , Ġor Ġdefine Ġa Ġ[ rule ]. Ċĉ Ġ*/ Ċ ĉ @ Suppress (" unused ") Ċ ĉ data Ġclass ĠCard inality ( val Ġmin : ĠInt , Ġval Ġmax : ĠInt ) Ġ{ Ċĉ ĉ comp anion Ġobject Ġ{ Ċĉĉ ĉ /** ĠThe Ġoption Ġmay Ġoccur Ġzero Ġor Ġone Ġtimes . Ġ*/ Ċĉĉ ĉ val ĠOPTIONAL Ġ= ĠCard inality ( 0 , Ġ 1 ) ĊĊĉĉ ĉ /** ĠThe Ġoption Ġmust Ġbe Ġpresent . Ġ*/ Ċĉĉ ĉ val ĠM AND AT ORY Ġ= ĠCard inality ( 1 , Ġ 1 ) ĊĊĉĉ ĉ /** ĠThe Ġoption Ġmay Ġoccur Ġzero Ġor Ġmore Ġtimes . Ġ*/ Ċĉĉ ĉ val ĠZERO _ OR _ MORE Ġ= ĠCard inality ( 0 , ĠInt . MAX _ VALUE ) ĊĊĉĉ ĉ /** ĠThe Ġoption Ġmust Ġoccur Ġat Ġleast Ġonce . Ġ*/ Ċĉĉ ĉ val ĠONE _ OR _ MORE Ġ= ĠCard inality ( 1 , ĠInt . MAX _ VALUE ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** ĠDeclare Ġa Ġgeneric Ġoption Ġthat Ġtakes Ġno Ġargument . Ġ*/ Ċ ĉ fun Ġoption ( Ċĉ ĉ key : ĠOption KeyType , Ċĉ ĉ keywords : ĠCollection < String >, Ċĉ ĉ description : ĠString , Ċĉ ĉ cardinality : ĠCard inality Ġ= ĠOPTIONAL , Ċĉ ĉ action : ĠOption Invocation < Option KeyType >. () Ġ-> ĠUnit Ċ ĉ ) Ġ= Ġall Options . add ( Ċĉ ĉ Generic Option ( key , Ġkeywords , Ġcardinality , Ġdescription , Ġaction , Ġnull )) ĊĊ ĉ /** ĠDeclare Ġa Ġgeneric Ġoption Ġthat Ġtakes Ġan Ġargument . Ġ*/ Ċ ĉ fun Ġoption With Argument ( Ċĉ ĉ key : ĠOption KeyType , Ċĉ ĉ keywords : ĠCollection < String >, Ċĉ ĉ description : ĠString , Ċĉ ĉ cardinality : ĠCard inality Ġ= ĠOPTIONAL , Ċĉ ĉ action 2 : ĠOption Invocation With Argument < Option KeyType >. () Ġ-> ĠUnit Ċ ĉ ) Ġ= Ġall Options . add ( Ċĉ ĉ Generic Option ( key , Ġkeywords , Ġcardinality , Ġdescription , Ġnull , Ġaction 2 )) ĊĊ ĉ /** Ċĉ Ġ* ĠAdd Ġthe Ġdefault Ġoption , Ġwhich Ġis Ġwhat Ġto Ġdo Ġwith Ġbare Ġarguments Ġthat Ġhave Ċĉ Ġ* Ġno Ġargument - requ iring Ġoption Ġpreceding Ġthem . Ċĉ Ġ*/ Ċ ĉ fun Ġdefault Option ( Ċĉ ĉ key : ĠOption KeyType , Ċĉ ĉ description : ĠString , Ċĉ ĉ cardinality : ĠCard inality Ġ= ĠOPTIONAL , Ċĉ ĉ action 2 : ĠOption Invocation With Argument < Option KeyType >. () Ġ-> ĠUnit Ċ ĉ ) Ġ= Ġall Options . add ( Default Option ( key , Ġcardinality , Ġdescription , Ġaction 2 )) ĊĊ ĉ /** Ċĉ Ġ* ĠAdd Ġthe Ġdefault Ġhelp Ġoption , Ġbound Ġto Ġ'- ? '. Ġ ĠAfter Ġthe Ġp reamble , Ġit Ċĉ Ġ* Ġoutputs Ġthe Ġkeywords Ġand Ġdescription Ġfor Ġeach Ġoption . Ċĉ Ġ*/ Ċ ĉ fun Ġhelp Option ( Ċĉ ĉ key : ĠOption KeyType , Ċĉ ĉ pre amble : ĠString , Ċĉ ĉ append able : ĠAppend able Ċ ĉ ) Ġ= Ġall Options . add ( Generic Help Option ( key , Ġp reamble , Ġappend able )) ĊĊ ĉ /** Ċĉ Ġ* ĠAdd Ġa Ġrule . Ġ ĠAll Ġrules Ġrun , Ġin Ġthe Ġorder Ġin Ġwhich Ġthey Ġwere Ġdefined Ġvia Ċĉ Ġ* Ġthis Ġmethod . Ġ ĠIf Ġa Ġrule Ġdiscover s Ġan Ġinvalid Ġcombination Ġof Ġoptions Ġand Ċĉ Ġ* Ġarguments , Ġit Ġshould Ġthrow Ġa Ġsuitable Ġ[ Option Processing Exception ] Ġwhose Ċĉ Ġ* Ġmessage Ġtext Ġis Ġthe Ġ[ rule Text ], Ġwhich Ġwill Ġbe Ġreported Ġto Ġthe Ġuser . Ċĉ Ġ* Ċĉ Ġ* ĠEach Ġoption Ġis Ġfirst Ġgiven Ġthe Ġchance Ġto Ġreport Ġproblems Ġrelated Ġto Ġonly Ċĉ Ġ* Ġthat Ġoption , Ġbut Ġafter Ġthat Ġall Ġrules Ġrun , Ġallowing Ġconsistency Ġchecks Ċĉ Ġ* Ġbetween Ġoptions . Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ċĉ Ġ* ĠĠ ĠThe Ġtext Ġto Ġdisplay Ġif Ġthe Ġrule Ġfails . Ċĉ Ġ* Ġ@ param Ċĉ Ġ* ĠĠ ĠThe Ġrule 's Ġbody , Ġwhich Ġreturns Ġ` true ` Ġiff Ġthe Ġrule Ġis Ġsatisfied . Ċĉ Ġ*/ Ċ ĉ @ Throws ( Option Processing Exception :: class ) Ċ ĉ fun Ġ< C Ġ: ĠConfiguration > ĠC . rule ( Ċĉ ĉ rule Text : ĠString , Ċĉ ĉ rule : ĠC . () Ġ-> ĠBoolean Ċ ĉ ) Ġ= Ġall Rules . add Ġ{ Ċĉ ĉ if Ġ(! rule ()) Ġthrow ĠOption Processing Exception ( rule Text ) Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠCheck Ġthat Ġthe Ġresulting Ġ[ option &# 3 2 ; processor ][ Option Processor ] Ġwill Ċĉ Ġ* Ġhave Ġno Ġdefect s . ĠIn Ġparticular : Ċĉ Ġ* Ċĉ Ġ* Ġ* ĠEvery Ġoption Ġkey Ġuniquely Ġspecifies Ġan Ġoption . Ċĉ Ġ* Ġ* ĠEvery Ġkeyword Ġmust Ġuniquely Ġindicate Ġan Ġoption Ġkey . Ċĉ Ġ* Ġ* ĠAll Ġ[ options ][ Option ] Ġmust Ġhave Ġnon - empty Ċĉ Ġ* ĠĠ Ġ[ description ][ Option . description ]. Ċĉ Ġ* Ġ* ĠAll Ġoption Ġkeys Ġmust Ġbe Ġbound Ġto Ġoptions . Ċĉ Ġ* Ċĉ Ġ* Ġ@ throws ĠValidation Exception Ċĉ Ġ* ĠĠ ĠIf Ġthe Ġspecified Ġ[ option &# 3 2 ; processor ][ Option Processor ] Ġfails Ċĉ Ġ* ĠĠ Ġvalidation Ġfor Ġany Ġreason . Ċĉ Ġ*/ Ċ ĉ @ Throws ( ValidationException :: class ) Ċ ĉ private Ġfun Ġvalidate Factory () Ċ ĉ { Ċĉ ĉ val Ġoption Keys Ġ= ĠEnum Set . none Of ( option KeyType ) Ċĉ ĉ all Options . forEach Ġ{ Ċĉĉ ĉ if Ġ( option Keys . contains ( it . key )) Ċĉĉ ĉ { Ċĉĉĉ ĉ throw ĠValidation Exception ( Ċĉĉĉĉ ĉ " some Ġoption Ġkeys Ġof Ġ" Ċĉĉĉĉ ĉ + Ġoption KeyType . canonical Name Ċĉĉĉĉ ĉ + Ġ" Ġdo Ġnot Ġuniquely Ġspecify Ġoptions ") Ċĉĉ ĉ } Ċĉĉ ĉ option Keys . add ( it . key ) Ċĉ ĉ } ĊĊĉ ĉ val Ġkeywords Ġ= Ġmutable Set Of < String >() Ċĉ ĉ all Options . forEach Ġ{ Ġoption Ġ-> Ċĉĉ ĉ option . keywords . forEach Ġ{ Ġkeyword Ġ-> Ċĉĉĉ ĉ if Ġ( keywords . contains ( keyword )) Ċĉĉĉ ĉ { Ċĉĉĉĉ ĉ throw ĠValidation Exception ( Ċĉĉĉĉĉ ĉ " some Ġoption Ġkeywords Ġdo Ġnot Ġuniquely Ġindicate Ġ" Ġ+ Ċĉĉĉĉĉ ĉ " option Ġkeys Ġof Ġ${ option KeyType . canonical Name }") Ċĉĉĉ ĉ } Ċĉĉĉ ĉ keywords . add ( keyword ) Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ all Options . forEach Ġ{ Ġoption Ġ-> Ċĉĉ ĉ if Ġ( option . description . isEmpty ()) Ċĉĉ ĉ { Ċĉĉĉ ĉ throw ĠValidation Exception ( Ċĉĉĉĉ ĉ " some Ġoptions Ġhave Ġempty Ġend - user Ġdescriptions ") Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ if Ġ( all Options . size Ġ!= Ġoption KeyType . enum Constants . size ) Ċĉ ĉ { Ċĉĉ ĉ throw ĠValidation Exception ( Ċĉĉĉ ĉ " some Ġoption Ġkeys Ġof Ġ" Ċĉĉĉ ĉ + Ġoption KeyType . canonical Name Ċĉĉĉ ĉ + Ġ" Ġare Ġnot Ġbound Ġto Ġoptions ") Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠCreate Ġan Ġinstance Ġof Ġthe Ġ[ option &# 3 2 ; processor ][ Option Processor ] Ċĉ Ġ* Ġdescribed Ġby Ġthe Ġreceiver . Ċĉ Ġ* Ċĉ Ġ* Ġ@ return Ċĉ Ġ* ĠĠ ĠThe Ġnew Ġvalidated Ġ[ option &# 3 2 ; processor ][ Option Processor ]. Ċĉ Ġ* Ġ@ throws ĠValidation Exception Ċĉ Ġ* ĠĠ ĠIf Ġvalidation Ġfails . Ċĉ Ġ*/ Ċ ĉ @ Throws ( ValidationException :: class ) Ċ ĉ private Ġfun Ġcreate Option Processor (): ĠOption Processor < Option KeyType > Ċ ĉ { Ċĉ ĉ validate Factory () Ċĉ ĉ val Ġkeywords Ġ= Ġmutable Map Of < String , ĠOption KeyType >() Ċĉ ĉ all Options . forEach Ġ{ Ġoption Ġ-> Ċĉĉ ĉ option . keywords . forEach Ġ{ Ġkeyword Ġ-> Ċĉĉĉ ĉ keywords [ keyword ] Ġ= Ġoption . key Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ return ĠOption Processor ( option KeyType , Ġkeywords , Ġall Options , Ġall Rules ) Ċ ĉ } Ċ } Ċ