/* Ċ Ġ* ĠCopyright Ġ 2 0 1 8 - 2 0 2 1 ĠAnd rei ĠHe ide lb acher Ġ< and rei . he ide lb acher @ gmail . com > Ċ Ġ* Ċ Ġ* Ġ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 Ġorg . chron ol ens . core . model Ċ Ċ import Ġorg . chron ol ens . core . model . List Edit . Companion . apply Ċ import Ġorg . chron ol ens . core . model . Set Edit . Companion . apply Ċ Ċ /** ĠAn Ġatomic Ġchange Ġwhich Ġshould Ġbe Ġapplied Ġto Ġa Ġ[ Source Tree ]. Ġ*/ Ċ public Ġsealed Ġclass ĠSource Tree Edit Ġ{ ĊĠĠĠ Ġ/** ĠThe Ġqualified Ġid Ġof Ġthe Ġedited Ġnode . Ġ*/ ĊĠĠĠ Ġpublic Ġabstract Ġval Ġid : ĠString ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠApplies Ġthis Ġedit Ġon Ġthe Ġgiven Ġmutable Ġmap Ġof Ġ[ nodes ]. ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ throws ĠIllegalStateException Ġif Ġthe Ġ[ nodes ] Ġhave Ġan Ġinvalid Ġstate Ġand ĊĠĠĠĠ Ġ* Ġthis Ġedit Ġcouldn 't Ġbe Ġapplied ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġinternal Ġabstract Ġfun Ġapply On ( nodes : ĠNode HashMap ) ĊĊĠĠĠ Ġpublic Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠReturns Ġthe Ġedits Ġwhich Ġmust Ġbe Ġapplied Ġto Ġ[ this ] Ġsource Ġtree Ġin ĊĠĠĠĠĠĠĠĠ Ġ* Ġorder Ġto Ġobtain Ġthe Ġ[ other ] Ġsource Ġtree . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Jvm Static ĊĠĠĠĠĠĠĠ Ġpublic Ġfun ĠSource Tree . diff ( other : ĠSource Tree ): ĠList < Source Tree Edit > Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġthis Sources Ġ= Ġthis . sources . map ( SourceFile :: path ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġother Sources Ġ= Ġother . sources . map ( SourceFile :: path ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġall Sources Ġ= Ġthis Sources . union ( other Sources ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnodes Before Ġ= ĠNode HashMap () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnodes After Ġ= ĠNode HashMap () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( path Ġin Ġall Sources ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . get < SourceFile ? >( path )?. let ( nodes Before :: put Source Tree ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġother . get < SourceFile ? >( path )?. let ( nodes After :: put Source Tree ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġfun Ġparent Exists ( id : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠparentId Ġ= Ġid . parentId Ġ?: Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠparentId Ġin Ġnodes Before Ġ&& ĠparentId Ġin Ġnodes After ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnode Ids Ġ= Ġnodes Before . keys Ġ+ Ġnodes After . keys ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnode Ids . filter (:: parent Exists ). map NotNull Ġ{ Ġid Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbefore Ġ= Ġnodes Before [ id ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġafter Ġ= Ġnodes After [ id ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġedit Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbefore Ġ== Ġnull Ġ&& Ġafter Ġ!= Ġnull Ġ-> ĠAdd Node ( id , Ġafter . source Node ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbefore Ġ!= Ġnull Ġ&& Ġafter Ġ== Ġnull Ġ-> ĠRemove Node ( id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbefore Ġ!= Ġnull Ġ&& Ġafter Ġ!= Ġnull Ġ-> Ġbefore . diff ( after ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠAssertionError (" Node Ġ'$ id ' Ġdoesn 't Ġexist !") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġedit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠIndicates Ġthat Ġa Ġ[ Source Node ] Ġshould Ġbe Ġadded Ġto Ġa Ġsource Ġtree . Ċ Ġ* Ċ Ġ* Ġ@ property Ġnode Ġthe Ġnode Ġwhich Ġshould Ġbe Ġadded Ġto Ġthe Ġsource Ġtree Ċ Ġ*/ Ċ public Ġdata Ġclass ĠAdd Node ( ĊĠĠĠ Ġoverride Ġval Ġid : ĠString , ĊĠĠĠ Ġval Ġnode : ĠSource Node , Ċ ) Ġ: ĠSource Tree Edit () Ġ{ ĊĊĠĠĠ Ġval Ġsource TreeNode : ĠSource TreeNode < *> Ġget () Ġ= ĠSource TreeNode ( id , Ġnode ) ĊĊĠĠĠ Ġoverride Ġfun Ġapply On ( nodes : ĠNode HashMap ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcheck ( id Ġ! in Ġnodes ) Ġ{ Ġ" Node Ġ'$ id ' Ġalready Ġexists !" Ġ} ĊĠĠĠĠĠĠĠ Ġnodes . put Source Tree ( source TreeNode ) ĊĠĠĠĠĠĠĠ Ġif Ġ( node Ġis ĠSource Entity ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate An cestors ( nodes , Ġid , Ġnode ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠIndicates Ġthat Ġa Ġ[ Source Node ] Ġshould Ġbe Ġremoved Ġfrom Ġa Ġsource Ġtree . Ċ Ġ* Ċ Ġ* Ġ@ throws ĠIllegalArgumentException Ġif Ġthe Ġ` id ` Ġis Ġnot Ġa Ġvalid Ġnode Ġid Ċ Ġ*/ Ċ public Ġdata Ġclass ĠRemove Node ( override Ġval Ġid : ĠString ) Ġ: ĠSource Tree Edit () Ġ{ ĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġvalidate NodeId ( id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġapply On ( nodes : ĠNode HashMap ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnode Ġ= Ġnodes [ id ] Ġ?: Ġerror (" Node Ġ'$ id ' Ġdoesn 't Ġexist !") ĊĠĠĠĠĠĠĠ Ġnodes . remove Source Tree ( node ) ĊĠĠĠĠĠĠĠ Ġif Ġ( node . source Node Ġis ĠSource Entity ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate An cestors ( nodes , Ġid , Ġnode . source Node ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠIndicates Ġthat Ġthe Ġproperties Ġof Ġa Ġ[ Type ] Ġwithin Ġa Ġ[ Source Tree ] Ġshould Ġbe Ċ Ġ* Ġedited . Ċ Ġ* Ċ Ġ* Ġ@ property Ġsup ertype Ed its Ġthe Ġedits Ġwhich Ġshould Ġbe Ġapplied Ġto Ġthe Ċ Ġ* Ġ[ Type . sup ert ypes ] Ġof Ġthe Ġtype Ġwith Ġthe Ġgiven Ġ[ id ] Ċ Ġ* Ġ@ property Ġmodifier Ed its Ġthe Ġedits Ġwhich Ġshould Ġbe Ġapplied Ġto Ġthe Ċ Ġ* Ġ[ Type . modifiers ] Ġof Ġthe Ġtype Ġwith Ġthe Ġgiven Ġ[ id ] Ċ Ġ* Ġ@ throws ĠIllegalArgumentException Ġif Ġthe Ġ[ id ] Ġis Ġnot Ġa Ġvalid Ġtype Ġid Ċ Ġ*/ Ċ public Ġdata Ġclass ĠEdit Type ( ĊĠĠĠ Ġoverride Ġval Ġid : ĠString , ĊĠĠĠ Ġval Ġsup ertype Ed its : ĠList < Set Edit < String >> Ġ= Ġempty List (), ĊĠĠĠ Ġval Ġmodifier Ed its : ĠList < Set Edit < String >> Ġ= Ġempty List () Ċ ) Ġ: ĠSource Tree Edit () Ġ{ ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġvalidate TypeId ( id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġapply On ( nodes : ĠNode HashMap ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtype Ġ= Ġnodes [ id ]?. source Node Ġas ? ĠType ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġerror (" Type Ġ'$ id ' Ġdoesn 't Ġexist !") ĊĠĠĠĠĠĠĠ Ġval Ġnew Type Ġ= Ġtype . copy ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsup ert ypes Ġ= Ġtype . sup ert ypes . apply ( sup ertype Ed its ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmodifiers Ġ= Ġtype . modifiers . apply ( modifier Ed its ), ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġnodes [ id ] Ġ= ĠSource TreeNode ( id , Ġnew Type ) ĊĠĠĠĠĠĠĠ Ġupdate An cestors ( nodes , Ġid , Ġnew Type ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠIndicates Ġthat Ġthe Ġproperties Ġof Ġa Ġ[ Function ] Ġwithin Ġa Ġ[ Source Tree ] Ġshould Ġbe Ċ Ġ* Ġedited . Ċ Ġ* Ċ Ġ* Ġ@ property Ġparameter Ed its Ġthe Ġedits Ġwhich Ġshould Ġbe Ġapplied Ġto Ġthe Ċ Ġ* Ġ[ Function . parameters ] Ġof Ġthe Ġfunction Ġwith Ġthe Ġgiven Ġ[ id ] Ċ Ġ* Ġ@ property Ġmodifier Ed its Ġthe Ġedits Ġwhich Ġshould Ġbe Ġapplied Ġto Ġthe Ċ Ġ* Ġ[ Function . modifiers ] Ġof Ġthe Ġfunction Ġwith Ġthe Ġgiven Ġ[ id ] Ċ Ġ* Ġ@ property Ġbody Ed its Ġthe Ġedits Ġwhich Ġshould Ġbe Ġapplied Ġto Ġthe Ġ[ Function . body ] Ċ Ġ* Ġof Ġthe Ġfunction Ġwith Ġthe Ġgiven Ġ[ id ] Ċ Ġ* Ġ@ throws ĠIllegalArgumentException Ġif Ġthe Ġ[ id ] Ġis Ġnot Ġa Ġvalid Ġfunction Ġid Ċ Ġ*/ Ċ public Ġdata Ġclass ĠEdit Function ( ĊĠĠĠ Ġoverride Ġval Ġid : ĠString , ĊĠĠĠ Ġval Ġparameter Ed its : ĠList < List Edit < String >> Ġ= Ġempty List (), ĊĠĠĠ Ġval Ġmodifier Ed its : ĠList < Set Edit < String >> Ġ= Ġempty List (), ĊĠĠĠ Ġval Ġbody Ed its : ĠList < List Edit < String >> Ġ= Ġempty List () Ċ ) Ġ: ĠSource Tree Edit () Ġ{ ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġvalidate Function Id ( id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġapply On ( nodes : ĠNode HashMap ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfunction Ġ= Ġnodes [ id ]?. source Node Ġas ĠFunction ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġerror (" Function Ġ'$ id ' Ġdoesn 't Ġexist !") ĊĠĠĠĠĠĠĠ Ġval Ġnew Function Ġ= Ġfunction . copy ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparameters Ġ= Ġfunction . parameters . apply ( parameter Ed its ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmodifiers Ġ= Ġfunction . modifiers . apply ( modifier Ed its ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbody Ġ= Ġfunction . body . apply ( body Ed its ), ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġnodes [ id ] Ġ= ĠSource TreeNode ( id , Ġnew Function ) ĊĠĠĠĠĠĠĠ Ġupdate An cestors ( nodes , Ġid , Ġnew Function ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠIndicates Ġthat Ġthe Ġproperties Ġof Ġa Ġ[ Variable ] Ġwithin Ġa Ġ[ Source Tree ] Ġshould Ġbe Ċ Ġ* Ġedited . Ċ Ġ* Ċ Ġ* Ġ@ property Ġmodifier Ed its Ġthe Ġedits Ġwhich Ġshould Ġbe Ġapplied Ġto Ġthe Ċ Ġ* Ġ[ Variable . modifiers ] Ġof Ġthe Ġvariable Ġwith Ġthe Ġgiven Ġ[ id ] Ċ Ġ* Ġ@ property Ġinitializer Ed its Ġthe Ġedits Ġwhich Ġshould Ġbe Ġapplied Ġto Ġthe Ċ Ġ* Ġ[ Variable . initializer ] Ġof Ġthe Ġvariable Ġwith Ġthe Ġgiven Ġ[ id ] Ċ Ġ* Ġ@ throws ĠIllegalArgumentException Ġif Ġthe Ġ[ id ] Ġis Ġnot Ġa Ġvalid Ġvariable Ġid Ċ Ġ*/ Ċ public Ġdata Ġclass ĠEdit Variable ( ĊĠĠĠ Ġoverride Ġval Ġid : ĠString , ĊĠĠĠ Ġval Ġmodifier Ed its : ĠList < Set Edit < String >> Ġ= Ġempty List (), ĊĠĠĠ Ġval Ġinitializer Ed its : ĠList < List Edit < String >> Ġ= Ġempty List () Ċ ) Ġ: ĠSource Tree Edit () Ġ{ ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġvalidate Variable Id ( id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġapply On ( nodes : ĠNode HashMap ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġvariable Ġ= Ġnodes [ id ]?. source Node Ġas ? ĠVariable ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġerror (" Variable Ġ'$ id ' Ġdoesn 't Ġexist !") ĊĠĠĠĠĠĠĠ Ġval Ġnew Variable Ġ= Ġvariable . copy ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmodifiers Ġ= Ġvariable . modifiers . apply ( modifier Ed its ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinitializer Ġ= Ġvariable . initializer . apply ( initializer Ed its ), ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġnodes [ id ] Ġ= ĠSource TreeNode ( id , Ġnew Variable ) ĊĠĠĠĠĠĠĠ Ġupdate An cestors ( nodes , Ġid , Ġnew Variable ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠUpdates Ġall Ġthe Ġan cestors Ġof Ġthe Ġgiven Ġmodified Ġ[ entity ] Ġfrom Ġthe Ġgiven Ċ Ġ* Ġmutable Ġmap Ġof Ġ[ nodes ] Ċ Ġ* Ċ Ġ* Ġ@ throws ĠIllegalStateException Ġif Ġthe Ġgiven Ġ[ nodes ] Ġhave Ġan Ġinvalid Ġstate Ġand Ċ Ġ* Ġthe Ġan cestors Ġof Ġthe Ġgiven Ġ[ entity ] Ġcouldn 't Ġbe Ġupdated Ċ Ġ*/ Ċ private Ġfun Ġupdate An cestors ( ĊĠĠĠ Ġnodes : ĠNode HashMap , ĊĠĠĠ Ġqualified Id : ĠString , ĊĠĠĠ Ġentity : ĠSource Entity , Ċ ) Ġ{ ĊĠĠĠ Ġfun ĠSet < Source Entity >. updated With Entity (): ĠSet < Source Entity > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnew Entities Ġ= ĠLinked HashSet < Source Entity >( size ) ĊĠĠĠĠĠĠĠ Ġthis . filter To ( new Entities ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . kind Ġ!= Ġentity . kind Ġ|| Ġit . simple Id Ġ!= Ġentity . simple Id ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( qualified Id Ġin Ġnodes ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnew Entities Ġ+= Ġentity ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġnew Entities ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun ĠSource File . updated () Ġ= Ġcopy ( entities Ġ= Ġentities . updated With Entity ()) ĊĠĠĠ Ġfun ĠType . updated () Ġ= Ġcopy ( members Ġ= Ġmembers . updated With Entity ()) ĊĊĠĠĠ Ġ// ĠTODO : Ġsimplify ĠparentId Ġcomputation . ĊĠĠĠ Ġval ĠparentId Ġ= ĠSource TreeNode ( qualified Id , Ġentity ). parentId ĊĠĠĠ Ġval Ġparent Ġ= Ġnodes [ parentId ]?. source Node ĊĠĠĠĠĠĠĠ Ġ?: Ġerror (" Parent Ġ'$ parentId ' Ġdoesn 't Ġexist !") ĊĠĠĠ Ġval Ġnew Parent Ġ= Ġwhen Ġ( parent ) Ġ{ ĊĠĠĠĠĠĠĠ Ġis ĠSource File Ġ-> Ġparent . updated () ĊĠĠĠĠĠĠĠ Ġis ĠType Ġ-> Ġparent . updated () ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġerror (" Unknown Ġcontainer Ġ'${ parent :: class }' !") ĊĠĠĠ Ġ} ĊĠĠĠ Ġnodes [ parentId ] Ġ= ĠSource TreeNode ( parentId , Ġnew Parent ) ĊĠĠĠ Ġif Ġ( new Parent Ġis ĠSource Entity ) Ġ{ ĊĠĠĠĠĠĠĠ Ġupdate An cestors ( nodes , ĠparentId , Ġnew Parent ) ĊĠĠĠ Ġ} Ċ } Ċ