/* Ċ Ġ* Ġ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 Ġxyz . chr is ime . cro od . service Ċ Ċ import Ġorg . jooq . Condition Ċ import Ġorg . jooq . DSL Context Ċ import Ġorg . jooq . Field Ċ import Ġorg . jooq . Record Ċ import Ġorg . jooq . Table Ċ import Ġorg . jooq . Table Field Ċ import Ġorg . jooq . Up datable Record Ċ import Ġorg . jooq . exception . Data AccessException Ċ import Ġorg . jooq . impl . DSL Ċ import Ġxyz . chr is ime . cro od . domain . Ident ifiable Domain Ċ import Ġxyz . chr is ime . cro od . error . Generic Error Ċ import Ġxyz . chr is ime . cro od . extensions . as Type Ċ import Ġxyz . chr is ime . cro od . extensions . getClass AtIndex Ċ import Ġxyz . chr is ime . cro od . extensions . newInstance Ċ import Ġxyz . chr is ime . cro od . id . Identifier Ċ import Ġjava . util . Optional Ċ import Ġjava . util . stream . Stream Ċ Ċ /** Ċ Ġ* ĠCommon Ġservice Ġbased Ġon Ġj OO Q Ġthat Ġprovides Ġbasic ĠCRUD Ġoperations . Ċ Ġ* Ċ Ġ* Ġ@ param ĠR Ġtable Ġrecord Ġtype : Ġa Ġrecord Ġcontains Ġa Ġrow 's Ġdata Ċ Ġ* Ġ@ param ĠID Ġtable Ġidentifier Ġtype Ġ( primary Ġkey ) Ċ Ġ* Ġ@ param ĠD Ġdomain Ġtype : Ġa Ġdomain Ġcontains Ġthe Ġvalues Ġof Ġa Ġsingle Ġtable Ġrow Ċ Ġ* Ċ Ġ* Ġ@ author ĠChristian ĠM ey er Ġ& lt ch rist ian . me yer @ gmail . com : gt ; Ċ Ġ*/ Ċ abstract Ġclass ĠCRUD Service < R Ġ: ĠUp datable Record < R >, ĠID Ġ: ĠAny , ĠD Ġ: ĠIdent ifiable Domain >( private Ġval Ġd sl : ĠDSL Context ) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġr Table : ĠTable < R > ĊĊĠĠĠ Ġprivate Ġval Ġc Domain : ĠClass < D > ĊĊĠĠĠ Ġprivate Ġval Ġpk Fields : ĠArray < Table Field < Record , ĠID >> ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġd sl . settings (). is Render Formatted Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠ Ġr Table Ġ= Ġnew Instance < Up datable Record < R >> (). table ĊĠĠĠĠĠĠĠ Ġpk Fields Ġ= Ġr Table . get Primary Keys () ĊĠĠĠĠĠĠĠ Ġc Domain Ġ= ĠgetClass AtIndex ( 2 ) ĊĊĠĠĠĠĠĠĠ Ġd sl . configuration (). record Un mapper Provider (). provide ( c Domain , Ġr Table . record Type ()) ĊĠĠĠĠĠĠĠ Ġd sl . configuration (). record Mapper Provider (). provide ( r Table . record Type (), Ġc Domain ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġcount Ġof Ġrows Ġin Ġtable Ġfiltered Ġby Ġgiven Ġcondition . ĊĠĠĠĠ Ġ* Ġ@ param Ġcondition Ġpredicate Ġto Ġfilter Ġresult Ġfor ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġfetch Count Where ( condition : Ġ() Ġ-> ĠCondition ): ĠInt Ġ= ĊĠĠĠĠĠĠĠ Ġd sl . select Count (). from ( r Table ). where ( condition ()). fetch One ( 0 , ĠInt :: class . java Primitive Type ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠGeneric Error . Database (" no Ġresults Ġin Ġ${ r Table . name }") ĊĊĠĠĠ Ġfun Ġ< F > Ġfetch One ( field : ĠField < F >, Ġvalue : ĠF ): ĠF Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġd sl . select ( field ). from ( r Table ). where ( field . eq ( value )). fetch One Into ( field . type ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠGeneric Error . Database (" no Ġresults Ġin Ġ${ r Table . name }") ĊĠĠĠ Ġ} Ġcatch Ġ( dae : ĠData AccessException ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠGeneric Error . Database ( dae . message , Ġd ae . cause ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġ< F > Ġfetch Optional ( field : ĠField < F >, Ġvalue : ĠF ): ĠOptional < F > Ġ= ĊĠĠĠĠĠĠĠ Ġd sl . select ( field ). from ( r Table ). where ( field . eq ( value )). fetch Optional Into ( field . type ) ĊĊĠĠĠ Ġfun Ġ< F > Ġfetch All ( field : ĠField < F >, Ġvar arg Ġvalues : ĠF ): ĠStream < F > Ġ= ĊĠĠĠĠĠĠĠ Ġd sl . select ( field ). from ( r Table ). where ( field .` in ` (* values )). fetch Stream Into ( field . type ) ĊĊĠĠĠ Ġfun Ġ< F > Ġfetch One Where ( field : ĠField < F >, Ġcondition : Ġ() Ġ-> ĠCondition ): ĠF Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġd sl . select ( field ). from ( r Table ). where ( condition ()). fetch One Into ( field . type ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠGeneric Error . Database (" no Ġresults Ġin Ġ${ r Table . name }") ĊĠĠĠ Ġ} Ġcatch Ġ( dae : ĠData AccessException ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠGeneric Error . Database ( dae . message , Ġd ae . cause ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġ< F > Ġfetch Optional Where ( field : ĠField < F >, Ġcondition : Ġ() Ġ-> ĠCondition ): ĠOptional < F > Ġ= ĊĠĠĠĠĠĠĠ Ġd sl . select ( field ). from ( r Table ). where ( condition ()). fetch Optional Into ( field . type ) ĊĊĠĠĠ Ġfun Ġ< F > Ġfetch All Where ( field : ĠField < F >, Ġcondition : Ġ() Ġ-> ĠCondition ): ĠStream < F > Ġ= ĊĠĠĠĠĠĠĠ Ġd sl . select ( field ). from ( r Table ). where ( condition ()). fetch Stream Into ( field . type ) ĊĊĠĠĠ Ġfun ĠfindAll (): ĠStream < D > Ġ= Ġd sl . select From ( r Table ). fetch Stream Into ( c Domain ) ĊĊĠĠĠ Ġfun ĠfindAll Where ( condition : Ġ() Ġ-> ĠCondition ): ĠStream < D > Ġ= ĊĠĠĠĠĠĠĠ Ġd sl . select From ( r Table ). where ( condition ()). fetch Stream Into ( c Domain ) ĊĊĠĠĠ Ġfun Ġfind One Where ( condition : Ġ() Ġ-> ĠCondition ): ĠD Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠ Ġd sl . select From ( r Table ). where ( condition ()). fetch One Into ( c Domain ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠGeneric Error . Database (" no Ġresults Ġin Ġ${ r Table . name }") ĊĠĠĠ Ġ} Ġcatch Ġ( dae : ĠData AccessException ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠGeneric Error . Database ( dae . message , Ġd ae . cause ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġfind Optional Where ( condition : Ġ() Ġ-> ĠCondition ): ĠOptional < D > Ġ= ĊĠĠĠĠĠĠĠ Ġd sl . select From ( r Table ). where ( condition ()). fetch Optional Into ( c Domain ) ĊĊĠĠĠ Ġfun Ġfind ById ( id : ĠID ): ĠD Ġ= Ġd sl . select From ( r Table ). where ( id . isEqual ()). fetch One Into ( c Domain ) ĊĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠGeneric Error . Database (" no Ġresults Ġin Ġ${ r Table . name }") ĊĊĠĠĠ Ġfun Ġfind Optional ById ( id : ĠID ): ĠOptional < D > Ġ= ĊĠĠĠĠĠĠĠ Ġd sl . select From ( r Table ). where ( id . isEqual ()). fetch Optional Into ( c Domain ) ĊĊĠĠĠ Ġfun Ġexists ById ( id : ĠID ): ĠBoolean Ġ= Ġd sl . fetch Exists ( dsl . select From ( r Table ). where ( id . isEqual ())) ĊĊĠĠĠ Ġfun Ġexists Where ( condition : Ġ() Ġ-> ĠCondition ): ĠBoolean Ġ= ĊĠĠĠĠĠĠĠ Ġd sl . fetch Exists ( dsl . select From ( r Table ). where ( condition ())) ĊĊĠĠĠ Ġfun Ġcreate ( source : ĠD ): ĠInt Ġ= Ġd sl . new Record ( r Table , Ġsource ). insert () ĊĊĠĠĠ Ġfun Ġcreate ( var arg Ġsources : ĠD ): ĠInt Array Ġ= Ġcreate ( sources . toList ()) ĊĊĠĠĠ Ġfun Ġcreate ( sources : ĠCollection < D >): ĠInt Array Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġsources . isEmpty () Ġ-> Ġint ArrayOf ( 0 ) ĊĠĠĠĠĠĠĠ Ġsources . size Ġ== Ġ 1 Ġ-> Ġint ArrayOf ( create ( sources . iterator (). next ())) ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġsources . map Ġ{ Ġsrc Ġ-> Ġd sl . new Record ( r Table , Ġsrc ) Ġ}. map Ġ{ Ġr Ġ-> Ġr . insert () Ġ}. to IntArray () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġupdate ( var arg Ġsources : ĠD ): ĠInt Array Ġ= Ġupdate ( sources . toList ()) ĊĊĠĠĠ Ġfun Ġupdate ( sources : ĠCollection < D >): ĠInt Array Ġ= Ġupdate Or Delete ( sources , ĠOperation . UPDATE ) ĊĊĠĠĠ Ġfun Ġdelete ById ( id : ĠID ): ĠInt Ġ= Ġd sl . delete From ( r Table ). where ( id . isEqual ()). execute () ĊĊĠĠĠ Ġfun Ġdelete Where ( condition : Ġ() Ġ-> ĠCondition ): ĠInt Ġ= Ġd sl . delete From ( r Table ). where ( condition ()). execute () ĊĊĠĠĠ Ġfun Ġdelete ( var arg Ġsources : ĠD ): ĠInt Array Ġ= Ġdelete ( sources . toList ()) ĊĊĠĠĠ Ġfun Ġdelete ( sources : ĠCollection < D >): ĠInt Array Ġ= Ġupdate Or Delete ( sources , ĠOperation . DELETE ) ĊĊĠĠĠ Ġfun Ġtruncate (): ĠInt Ġ= Ġd sl . truncate ( r Table ). restart Identity (). cascade (). execute () ĊĊĠĠĠ Ġprivate Ġfun Ġset Field For Update Or Delete ( domains : ĠIterable < D >): ĠList < Up datable Record <* >> Ġ= Ġdomains . map Ġ{ ĊĠĠĠĠĠĠĠ Ġwith ( dsl . new Record ( r Table , Ġit )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpk Fields . forEach Ġ{ Ġpk Field Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġchanged ( pk Field , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Or Delete ( sources : ĠCollection < D >, Ġoperation : ĠOperation ): ĠInt Array Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġsources . isEmpty () Ġ-> Ġint ArrayOf () ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġset Field For Update Or Delete ( sources ). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( it . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 1 Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( operation ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠOperation . DELETE Ġ-> Ġint ArrayOf ( it [ 0 ]. delete ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠOperation . UPDATE Ġ-> Ġint ArrayOf ( it [ 0 ]. update ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġwhen Ġ( operation ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠOperation . DELETE Ġ-> Ġit . map Ġ{ Ġr Ġ-> Ġr . delete () Ġ}. to IntArray () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠOperation . UPDATE Ġ-> Ġit . map Ġ{ Ġr Ġ-> Ġr . update () Ġ}. to IntArray () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠID . isEqual (): ĠCondition Ġ= Ġwhen Ġ( val Ġid Ġ= Ġthis ) Ġ{ ĊĠĠĠĠĠĠĠ Ġis ĠIdentifier Ġ-> ĠDSL . row (* pk Fields ). eq ( DSL . row (* id . identifier )) ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġpk Fields [ 0 ]. eq ( pk Fields [ 0 ]. dataType . convert ( id )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠTable <* >. get Primary Keys () Ġ= Ġthis . keys ĊĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . is Primary Ġ} ĊĠĠĠĠĠĠĠ Ġ. flatMap Ġ{ Ġit . fields . as Type < List < Table Field < Record , ĠID >> >() Ġ}. to Typed Array () ĊĊĠĠĠ Ġprivate Ġenum Ġclass ĠOperation Ġ{ ĊĠĠĠĠĠĠĠ ĠUPDATE , ĠDELETE ĊĠĠĠ Ġ} Ċ Ċ } Ċ