package Ġch . max ant . k dc . mf . contracts . control Ċ Ċ import Ġch . max ant . k dc . mf . contracts . definitions . Configuration Ċ import Ġch . max ant . k dc . mf . contracts . definitions . ProductId Ċ import Ġch . max ant . k dc . mf . contracts . dto . Component Ċ import Ġch . max ant . k dc . mf . contracts . entity . Component Entity Ċ import Ġcom . fasterxml . jackson . databind . ObjectMapper Ċ import Ġcom . fasterxml . jackson . module . kotlin . readValue Ċ import Ġjava . util .* Ċ import Ġjavax . enterprise . context . Application Scoped Ċ import Ġjavax . inject . Inject Ċ Ċ @ Application Scoped Ċ @ SuppressWarnings (" unused ") Ċ class ĠInstanti ation Service ( ĊĠĠĠ Ġ@ Inject Ġvar Ġom : ĠObjectMapper Ċ ) Ġ{ ĊĊĠĠĠ Ġfun Ġinstantiate ( merged Component Definition : ĠMerged Component Definition , ĠparentId : ĠUUID ? Ġ= Ġnull ): ĠList < Component > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcomponents Output : ĠMutable List < Component > Ġ= Ġmutable ListOf () ĊĠĠĠĠĠĠĠ Ġinstantiate ( merged Component Definition , Ġcomponents Output , ĠparentId ) ĊĠĠĠĠĠĠĠ Ġreturn Ġcomponents Output ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġinstantiate ( merged Component Definition : ĠMerged Component Definition , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomponents Output : ĠMutable List < Component >, ĠparentId : ĠUUID ? Ġ= Ġnull , Ġpath : ĠString ? Ġ= Ġnull ): ĠList < Component > Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ// Ġinstantiate Ġthe Ġdefinition Ġthe Ġrequired Ġnumber Ġof Ġtimes ĊĠĠĠĠĠĠĠĠ 1 . range To ( merged Component Definition . cardinality Default ). forEach Ġ{ Ġcardinality Key Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġnew Path Ġ= Ġ"${ merged Component Definition . component Definition Id }$ cardinality Key " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( path Ġ!= Ġnull ) Ġnew Path Ġ= Ġ"$ path ->$ new Path " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcomponent Ġ= ĠComponent ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUUID . randomUUID (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠparentId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . component Definition Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . configs , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . productId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"$ cardinality Key ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnew Path ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcomponents Output . add ( component ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . children . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinstantiate ( it , Ġcomponents Output , Ġcomponent . id , Ġnew Path ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġcomponents Output ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** Ġinstantiate Ġthe Ġgiven Ġmerged Component Definition Ġinto Ġthe Ġinstance Ġtree Ġdefined Ġby Ġall Components , Ġwith Ġthe Ġparent ĊĠĠĠĠ Ġ* Ġhaving Ġthe Ġsupplied ĠID . Ġreturns Ġa Ġlist Ġof Ġthe Ġnew Ġcomponent Ġand Ġall Ġits Ġchildren . Ġthis Ġalgorithm Ġcalculates Ġthe ĊĠĠĠĠ Ġ* Ġcorrect Ġcardinality Ġkey , Ġbased Ġon Ġall Ġexisting Ġones Ġplus Ġone Ġ*/ ĊĠĠĠ Ġfun Ġinstantiate Sub tree ( all Components : ĠList < Component >, Ġmerged Component Definition : ĠMerged Component Definition , Ġpath ToAdd : ĠString ): ĠList < Component > Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠparentId : ĠUUID Ġ= Ġget Component Id For Path ( all Components , Ġpath ToAdd . substring ( 0 , Ġpath ToAdd . lastIndexOf (" -> "))) ĊĠĠĠĠĠĠĠ Ġval Ġcomponents Output Ġ= Ġmutable ListOf < Component >() ĊĠĠĠĠĠĠĠ Ġval Ġroot Instance Ġ= ĠTree Component ( all Components . map Ġ{ ĠComponent Object Wrapper ( it ) Ġ}) ĊĠĠĠĠĠĠĠ Ġroot Instance . accept Ġ{ Ġparent Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( parent . component . id Ġ== ĠparentId ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcardinality Key Ġ= Ġ( parent . children ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . component . component Definition Id Ġ== Ġmerged Component Definition . component Definition Id Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . component . cardinality Key . toInt () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. max () Ġ?: Ġ 0 ) Ġ+ Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Path Ġ= Ġ"${ parent . getPath ()} -> ${ merged Component Definition . component Definition Id }$ cardinality Key " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcomponent Ġ= ĠComponent ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUUID . randomUUID (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠparentId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . component Definition Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . configs , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . productId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"$ cardinality Key ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnew Path ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomponents Output . add ( component ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . children . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinstantiate ( it , Ġcomponents Output , Ġcomponent . id , Ġnew Path ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġcomponents Output ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** Ġfix Ġcardinality Ġkeys Ġand Ġpaths Ġof Ġall Ġs iblings Ġof Ġthe Ġsame Ġtime . Ġrequired Ġafter Ġremoving Ġa Ġcomp n ent . ĊĠĠĠĠ Ġ* Ġtypically Ġthe Ġsibling Ġis Ġnot Ġin Ġthe Ġtree Ġanymore ! Ġ*/ ĊĠĠĠ Ġfun Ġreset Cardinality Keys And Paths ( all Components : ĠList < Component >, Ġsibling : ĠComponent ): ĠMutable List < Component > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcomponents Output Ġ= Ġmutable ListOf < Tree Component >() ĊĠĠĠĠĠĠĠ Ġval Ġs iblings Ġ= Ġmutable ListOf < Tree Component >() ĊĠĠĠĠĠĠĠ Ġval Ġroot Instance Ġ= ĠTree Component ( all Components . map Ġ{ ĠComponent Object Wrapper ( it ) Ġ}) ĊĠĠĠĠĠĠĠ Ġroot Instance . accept Ġ{ Ġcomponent Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcomponents Output . add ( component ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( component . component . parentId Ġ== Ġsibling . parentId ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ&& Ġcomponent . component . component Definition Id Ġ== Ġsibling . component Definition Id ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġs iblings . add ( component ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġs iblings ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. sorted By Ġ{ Ġit . component . cardinality Key Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. with Index () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Cardinality Key Ġ= Ġit . index . plus ( 1 ). toString () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . value . component . cardinality Key Ġ= Ġnew Cardinality Key ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġreset Ġpath Ġtoo ĊĠĠĠĠĠĠĠ Ġreturn Ġcomponents Output . map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdto Ġ= Ġit . component . original () Ġas ĠComponent ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdto . path Ġ= Ġit . getPath () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdto ĊĠĠĠĠĠĠĠ Ġ}. to Mutable List () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** Ġbuilds Ġan Ġinternal Ġtree Ġof Ġall Components Ġand Ġthen Ġvalidates Ġeach Ġnode Ġin Ġthe Ġtree Ġagainst ĊĠĠĠĠ Ġ* Ġthe Ġmatching Ġnode Ġfrom Ġthe Ġmerged Ġdefinition , Ġbased Ġon Ġpaths . Ġthe Ġconfigs Ġin Ġthe ĊĠĠĠĠ Ġ* Ġmerged Ġcomponent Ġdefinitions Ġare Ġir relevant Ġ( with Ġinitial / default Ġvalues ), Ġbecause Ġwe Ġuse Ġthe Ġactual ĊĠĠĠĠ Ġ* Ġconfigs Ġfrom Ġall Components . Ġ*/ ĊĠĠĠ Ġfun Ġvalidate ( merged Component Definition : ĠMerged Component Definition , Ġall Components : ĠList < Component >) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ// Ġcreate Ġa Ġtemporary Ġtree Ġof Ġthe Ġflat Ġcomponents , Ġso Ġwe Ġcan Ġretrieve Ġand Ġcompare Ġsub trees ĊĠĠĠĠĠĠĠ Ġval Ġroot Instance Ġ= ĠTree Component ( all Components . map Ġ{ ĠComponent Object Wrapper ( it ) Ġ}) ĊĊĠĠĠĠĠĠĠ Ġ// Ġnow Ġapply Ġvalues Ġout Ġof Ġcomponents Ġonto Ġmerged Component Definition ĊĠĠĠĠĠĠĠ Ġroot Instance . accept Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdefinition Sub tree Ġ= Ġmerged Component Definition . find ( it . getPath ()) !! ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvalidate ( definition Sub tree , Ġit ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate ( merged Component Definition : ĠMerged Component Definition , Ġtree Component : ĠTree Component ) Ġ{ ĊĠĠĠĠĠĠĠ Ġtree Component . component . configs . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . ensure Config Value Is Per mitted ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIllegalArgumentException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException ("${ e . message } Ġat Ġpath Ġ${ tree Component . getPath () }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmerged Component Definition . run Rules ( tree Component . component . configs , Ġtree Component . component ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIllegalArgumentException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException ("${ e . message } Ġat Ġpath Ġ${ tree Component . getPath () }") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif ( tree Component . parent Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠnumOf S iblings Ġ= Ġtree Component . parent . children ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . getPath (). matches ( Regex ( merged Component Definition . getPath ())) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. count () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequire ( num Of S iblings Ġ>= Ġmerged Component Definition . cardinality Min ) Ġ{ Ġ" too Ġfew Ġ Ġk ids Ġof Ġtype Ġ${ tree Component . component . component Definition Id } Ġin Ġpath Ġ${ tree Component . parent . getPath () }" Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequire ( num Of S iblings Ġ<= Ġmerged Component Definition . cardinality Max ) Ġ{ Ġ" too Ġmany Ġk ids Ġof Ġtype Ġ${ tree Component . component . component Definition Id } Ġin Ġpath Ġ${ tree Component . parent . getPath () }" Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġre instantiate ( entities : ĠList < Component Entity >): ĠList < Component > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠTree Component ( entities . map Ġ{ ĠComponent Entity Wrapper ( it , Ġom ) Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. flatten () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠComponent ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . component . id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . component . parentId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . component . component Definition Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . component . configs , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . component . productId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . component . cardinality Key , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . getPath () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Component Id For Path ( components : ĠList < Component >, Ġpath : ĠString ): ĠUUID Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget Component For Path ( components , Ġpath ). id ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Component For Path ( components : ĠList < Component >, Ġpath : ĠString ): ĠComponent Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġcomponent : ĠTree Component ? Ġ= Ġnull ĊĠĠĠĠĠĠĠ ĠTree Component ( components . map Ġ{ ĠComponent Object Wrapper ( it ) Ġ}). accept Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( it . getPath () Ġ== Ġpath ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomponent Ġ= Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġwrapper Ġ= Ġcomponent ?. component Ġ?: Ġthrow ĠIllegalArgumentException (" no Ġcomponent Ġfound Ġfor Ġpath Ġ$ path ") ĊĠĠĠĠĠĠĠ Ġreturn Ġwrapper . original () Ġas ĠComponent ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġinterface ĠComponent Wrapper < T > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġid : ĠUUID ĊĠĠĠĠĠĠĠ Ġval ĠparentId : ĠUUID ? ĊĠĠĠĠĠĠĠ Ġval Ġcomponent Definition Id : ĠString ĊĠĠĠĠĠĠĠ Ġval Ġconfigs : ĠList < Configuration <* >> ĊĠĠĠĠĠĠĠ Ġval ĠproductId : ĠProduct Id ? ĊĠĠĠĠĠĠĠ Ġvar Ġcardinality Key : ĠString ĊĊĠĠĠĠĠĠĠ Ġfun Ġoriginal (): ĠT ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġclass ĠComponent Entity Wrapper ( private Ġval Ġe : ĠComponent Entity , Ġprivate Ġval Ġom : ĠObjectMapper ) Ġ: ĠComponent Wrapper < Component Entity > Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġval Ġid : ĠUUID ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġe . id ĊĠĠĠĠĠĠĠ Ġoverride Ġval ĠparentId : ĠUUID ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġe . parentId ĊĠĠĠĠĠĠĠ Ġoverride Ġval Ġcomponent Definition Id : ĠString ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġe . component Definition Id ĊĠĠĠĠĠĠĠ Ġoverride Ġval Ġconfigs : ĠList < Configuration <* >> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġom . readValue < ArrayList < Configuration <* >> >( e . configuration ) ĊĠĠĠĠĠĠĠ Ġoverride Ġval ĠproductId : ĠProduct Id ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġe . productId ĊĠĠĠĠĠĠĠ Ġoverride Ġvar Ġcardinality Key : ĠString ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġe . cardinality Key ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset ( value ) Ġ{ Ġe . cardinality Key Ġ= Ġvalue Ġ} ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġoriginal () Ġ= Ġe ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġclass ĠComponent Object Wrapper ( private Ġval Ġc : ĠComponent ) Ġ: ĠComponent Wrapper < Component > Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġval Ġid : ĠUUID ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġc . id ĊĠĠĠĠĠĠĠ Ġoverride Ġval ĠparentId : ĠUUID ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġc . parentId ĊĠĠĠĠĠĠĠ Ġoverride Ġval Ġcomponent Definition Id : ĠString ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġc . component Definition Id ĊĠĠĠĠĠĠĠ Ġoverride Ġval Ġconfigs : ĠList < Configuration <* >> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġc . configs ĊĠĠĠĠĠĠĠ Ġoverride Ġval ĠproductId : ĠProduct Id ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġc . productId ĊĠĠĠĠĠĠĠ Ġoverride Ġvar Ġcardinality Key : ĠString ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġc . cardinality Key ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset ( value ) Ġ{ Ġc . cardinality Key Ġ= Ġvalue Ġ} ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġoriginal () Ġ= Ġc ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġclass ĠTree Component ( all Components : ĠList < Component Wrapper <* >>, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcomponent : ĠComponent Wrapper < *> Ġ= Ġall Components . find Ġ{ Ġit . parentId Ġ== Ġnull Ġ} !! , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparent : ĠTree Component ? Ġ= Ġnull ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġchildren Ġ= Ġmutable ListOf < Tree Component >() ĊĊĠĠĠĠĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparent ?. children ?. add ( this ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġall Components . filter Ġ{ Ġit . parentId Ġ== Ġcomponent . id Ġ}. forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTree Component ( all Components , Ġit , Ġthis ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun ĠgetPath (): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġname Ġ= Ġcomponent . component Definition Id Ġ+ Ġcomponent . cardinality Key ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġif ( parent Ġ== Ġnull ) Ġname Ġelse Ġ"${ parent . getPath ()} ->$ name " ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** Ġchildren Ġlast Ġrecursion Ġa ka Ġpre Ġorder Ġtraversal ĊĠĠĠĠĠĠĠĠ Ġ* Ġhttps :// tow ard sd at asci ence . com / 4 - types - of - tree - traversal - algorithms - d 5 6 3 2 8 4 5 0 8 4 6 Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġaccept ( f : Ġ( tree Component : ĠTree Component ) Ġ-> ĠUnit ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġf ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchildren . forEach Ġ{ Ġit . accept ( f ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġflatten (): ĠList < Tree Component > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlist Ġ= Ġmutable ListOf < Tree Component >() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . accept Ġ{ Ġlist . add ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġlist ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ Ċ }