package Ġs ck ema Ċ Ċ import Ġcom . squareup . kotlin po et .* Ċ import Ġjava . math . BigDecimal ĊĊ Ċ object ĠValidation Spec { ĊĊĠĠĠ Ġfun Ġvalidation For Object (` package `: ĠString , Ġschema : ĠJson Schema , Ġoverride : ĠBoolean Ġ= Ġfalse ): ĠFun Spec ? { ĊĠĠĠĠĠĠĠ Ġval Ġrequired List Ġ= Ġschema . required . or Empty () ĊĠĠĠĠĠĠĠ Ġval Ġvalidations Ġ= Ġ( schema . properties ?. definitions Ġ?: Ġempty Map ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . key Ġto Ġit . value Ġas ĠJson Schema Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. flatMap Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrequired Ġ= Ġrequired List . contains ( it . first ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen ( it . second . type ?. types ?. first ()){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" string " Ġ-> Ġstring Validation ( it . first , Ġrequired , Ġit . second ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" number " Ġ-> Ġnumber Validation ( it . first , Ġrequired , Ġit . second ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" integer " Ġ-> Ġnumber Validation ( it . first , Ġrequired , Ġit . second ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( it . second .` $ ref ` Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( Code Block . of (" ĠĠ Ġthis .${ it . first }${ if ( required ) Ġ"" Ġelse Ġ"? "} . let { Ġit . validate (\" ${ it . first }\" ). as Children Of ( name ) Ġ} ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġempty List () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif ( valid ations . isEmpty () Ġ&& Ġoverride ) Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġfunction Builder Ġ= ĠFun Spec . builder (" validate ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. also Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( override ) it . add Modifiers ( K Modifier . OVERRIDE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Parameter (" name ", ĠString :: class ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. returns ( ClassName (` package `, Ġ" Validation ")) ĊĠĠĠĠĠĠĠ Ġif ( valid ations . isEmpty ()){ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunction Builder . add Code (" return ĠValid ()\ n ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunction Builder . add Code (" val Ġvalidations Ġ= ĠlistOf NotNull (\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( override ) Ġfunction Builder . add Code (" super . validate ( name ). as Children Of ( name ), \ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvalidations . forEach Indexed Ġ{ Ġindex , Ġcode Block Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunction Builder . add Code ( code Block ). add Code ( if Ġ( index Ġ< Ġvalidations . size Ġ- Ġ 1 ) Ġ", \ n " Ġelse Ġ"\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfunction Builder . add Code (" ). flatten ()\ n return Ġif ( valid ations . isEmpty ()) ĠValid () Ġelse ĠInvalid ( name Ġ= Ġname , Ġvalidation Errors Ġ= Ġvalidations )") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġfunction Builder . build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġstring Validation ( name : ĠString , Ġrequired : ĠBoolean , Ġschema : ĠJson Schema ): ĠList < Code Block >{ ĊĠĠĠĠĠĠĠ Ġreturn ĠlistOf NotNull ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( schema . maxLength Ġ!= Ġnull ) ĠCode Block . of (" ĠĠ Ġthis .$ name ${ if ( required ) Ġ"" Ġelse Ġ"? "} . let { Ġif ( Ġit . length Ġ> Ġ${ schema . maxLength } Ġ) ĠlistOf ( ValidationError (\" $ name \", ĠValidation Reason . STRING _ LENGTH , ĠValidationError . message For String Max (${ schema . maxLength } ))) Ġelse Ġnull Ġ} ") Ġelse Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( schema . min Length Ġ!= Ġnull ) ĠCode Block . of (" ĠĠ Ġthis .$ name ${ if ( required ) Ġ"" Ġelse Ġ"? "} . let { Ġif ( Ġit . length Ġ< Ġ${ schema . min Length } Ġ) ĠlistOf ( ValidationError (\" $ name \", ĠValidation Reason . STRING _ LENGTH , ĠValidationError . message For String Min (${ schema . min Length } ))) Ġelse Ġnull Ġ} ") Ġelse Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( schema . pattern Ġ!= Ġnull ) ĠCode Block . of (" ĠĠ Ġthis .$ name ${ if ( required ) Ġ"" Ġelse Ġ"? "} . let { Ġif ( Ġ! it . matches ( Ġ% T (\" ${ schema . pattern }\ ") Ġ) Ġ) ĠlistOf ( ValidationError (\" $ name \", ĠValidation Reason . STRING _ PATTERN , ĠValidationError . message For String Pattern (\" ${ schema . pattern }\" ))) Ġelse Ġnull Ġ} ", ĠRegex :: class ) Ġelse Ġnull ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġnumber Validation ( name : ĠString , Ġrequired : ĠBoolean , Ġschema : ĠJson Schema ): ĠList < Code Block >{ ĊĠĠĠĠĠĠĠ Ġreturn ĠlistOf NotNull ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( schema . minimum Ġ!= Ġnull ) Code Block . of (" Ġ Ġthis .$ name ${ if ( required ) Ġ"" Ġelse Ġ"? "} . let { Ġif ( Ġit Ġ<= Ġ% T (${ schema . minimum }) Ġ) ĠlistOf ( ValidationError (\" $ name \", ĠValidation Reason . NUMBER _ LIMIT , ĠValidationError . message For Number Min (% T (${ schema . minimum } )))) Ġelse Ġnull Ġ} ", ĠBigDecimal :: class , ĠBigDecimal :: class ) Ġelse Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( schema . exclusive Minimum Ġ!= Ġnull ) Code Block . of (" ĠĠ Ġthis .$ name ${ if ( required ) Ġ"" Ġelse Ġ"? "} . let { Ġif ( Ġit Ġ< Ġ% T (${ schema . exclusive Minimum }) Ġ) ĠlistOf ( ValidationError (\" $ name \", ĠValidation Reason . NUMBER _ LIMIT , ĠValidationError . message For Number Exclusive Min (% T (${ schema . exclusive Minimum } )))) Ġelse Ġnull Ġ} ", ĠBigDecimal :: class , ĠBigDecimal :: class ) Ġelse Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( schema . maximum Ġ!= Ġnull ) Code Block . of (" ĠĠ Ġthis .$ name ${ if ( required ) Ġ"" Ġelse Ġ"? "} . let { Ġif ( Ġit Ġ>= Ġ% T (${ schema . maximum }) Ġ) ĠlistOf ( ValidationError (\" $ name \", ĠValidation Reason . NUMBER _ LIMIT , ĠValidationError . message For Number Max (% T (${ schema . maximum } )))) Ġelse Ġnull Ġ} ", ĠBigDecimal :: class , ĠBigDecimal :: class ) Ġelse Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( schema . exclusive Maximum Ġ!= Ġnull ) Code Block . of (" ĠĠ Ġthis .$ name ${ if ( required ) Ġ"" Ġelse Ġ"? "} . let { Ġif ( Ġit Ġ< Ġ% T (${ schema . exclusive Maximum }) Ġ) ĠlistOf ( ValidationError (\" $ name \", ĠValidation Reason . NUMBER _ LIMIT , ĠValidationError . message For Number Exclusive Max (% T (${ schema . exclusive Maximum } )))) Ġelse Ġnull Ġ} ", ĠBigDecimal :: class , ĠBigDecimal :: class ) Ġelse Ġnull ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġvalidation Helpers (` package `: ĠString ) Ġ= ĠFile Spec . builder (` package `, Ġ" Validation ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Type ( Type Spec . interface Builder (" Validation "). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Type ( Type Spec . class Builder (" Valid "). add Super interface ( ClassName (` package `, " Validation ")). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Type ( Type Spec . enum Builder (" Validation Reason ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Enum Constant (" STRING _ LENGTH ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Enum Constant (" STRING _ PATTERN ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Enum Constant (" NUMBER _ LIMIT ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Type ( Type Spec . class Builder (" ValidationError "). add Modifiers ( K Modifier . DATA ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addProperty ( Property Spec . builder (" property ", ĠString :: class . as TypeName ()). initializer ( Code Block . of (" property ")). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addProperty ( Property Spec . builder (" reason ", ĠClass Name (` package `, Ġ" Validation Reason ")). initializer ( Code Block . of (" reason ")). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addProperty ( Property Spec . builder (" message ", ĠString :: class . as TypeName ()). initializer ( Code Block . of (" message ")). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. primary Constructor ( Fun Spec ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. constructor Builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Parameter ( Parameter Spec . builder (" property ", ĠString :: class . as TypeName ()). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Parameter ( Parameter Spec . builder (" reason ", ĠClass Name (` package `, Ġ" Validation Reason ")). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Parameter ( Parameter Spec . builder (" message ", ĠString :: class . as TypeName ()). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. comp anion Object ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠType Spec . comp anion Object Builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addFunction ( Fun Spec . builder (" message For String Max "). add Parameter (" max ", ĠInt :: class ). returns ( String :: class ). add Code (" return Ġ\" Character Ġlength Ġmust Ġbe Ġless Ġthan Ġor Ġequal Ġto Ġ\$ max \"\ n "). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addFunction ( Fun Spec . builder (" message For String Min "). add Parameter (" min ", ĠInt :: class ). returns ( String :: class ). add Code (" return Ġ\" Character Ġlength Ġmust Ġbe Ġgreater Ġthan Ġor Ġequal Ġto Ġ\$ min \"\ n "). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addFunction ( Fun Spec . builder (" message For String Pattern "). add Parameter (" pattern ", ĠString :: class ). returns ( String :: class ). add Code (" return Ġ\" String Ġmust Ġmatch Ġpattern : Ġ\$ pattern \"\ n "). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addFunction ( Fun Spec . builder (" message For Number Max "). add Parameter (" max ", ĠBigDecimal :: class ). returns ( String :: class ). add Code (" return Ġ\" Number Ġmust Ġbe Ġless Ġthan Ġor Ġequal Ġto Ġ\$ max \"\ n "). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addFunction ( Fun Spec . builder (" message For Number Min "). add Parameter (" min ", ĠBigDecimal :: class ). returns ( String :: class ). add Code (" return Ġ\" Number Ġmust Ġbe Ġgreater Ġthan Ġor Ġequal Ġto Ġ\$ min \"\ n "). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addFunction ( Fun Spec . builder (" message For Number Exclusive Max "). add Parameter (" max ", ĠBigDecimal :: class ). returns ( String :: class ). add Code (" return Ġ\" Number Ġmust Ġbe Ġless Ġthan Ġ\$ max \"\ n "). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addFunction ( Fun Spec . builder (" message For Number Exclusive Min "). add Parameter (" min ", ĠBigDecimal :: class ). returns ( String :: class ). add Code (" return Ġ\" Number Ġmust Ġbe Ġgreater Ġthan Ġ\$ min \"\ n "). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Type ( Type Spec . class Builder (" Invalid "). add Modifiers ( K Modifier . DATA ). add Super interface ( ClassName (` package `, " Validation ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addProperty ( Property Spec . builder (" name ", ĠString :: class ). initializer (" name "). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addProperty ( Property Spec . builder (" validation Errors ", ĠParameter ized TypeName . get ( List :: class . as ClassName (), ĠClass Name (` package `, " ValidationError ")) ). initializer ( Code Block . of (" validation Errors ")). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. primary Constructor ( Fun Spec ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. constructor Builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Parameter (" name ", ĠString :: class ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Parameter ( Parameter Spec . builder (" validation Errors ", ĠParameter ized TypeName . get ( List :: class . as ClassName (), ĠClass Name (` package `, " ValidationError ")) ). build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addFunction ( Fun Spec . builder (" Collection < ValidationError >. as Children Of ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Parameter (" parent ", ĠString :: class ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Code (" return Ġthis . map Ġ{ Ġit . copy ( property Ġ= Ġparent Ġ+ Ġ\ ". \" Ġ+ Ġit . property ) Ġ} ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. addFunction ( Fun Spec . builder (" Validation . as Children Of ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Parameter (" parent ", ĠString :: class ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Code (" return Ġwhen ( this ){ Ġis ĠInvalid Ġ-> Ġthis . validation Errors . as Children Of ( parent ); Ġelse Ġ-> Ġnull Ġ} ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () Ċ Ċ }