Best Practices - Handling Collections

The purpose of this document is to provide best practices to handle collections.

Collections of child instances are managed as arrays, with additional technical properties and methods that simplify their management. For persistent classes, the supervisor handles all the code, and no additional line needs to be written.

Insertion and deletion

Control rules

Propagation rules

Line count

Example

The following example of code summarizes the different concepts mentioned above. Every section of this program can be considered autonomously.

To handle this, the code is created at the document class level.

## The history update is done after all the other controls, and before launching the update or the creation actions.# The percentage of update number is computed after read (if creation, no history exists)$METHODSCase CURPTHWhen "HISTORY" : # Events on a collectionCase ACTIONWhen "ADDLINE_AFTER"Gosub INIT_HISTORY_LINEEndcaseWhen "" : # Global eventsCase ACTIONWhen "UPDATE_HISTORY"Gosub UPDATE_HISTORYWhen "READ_AFTER"Gosub COMPUTE_HISTORYEndcaseEndcaseReturn$INIT_HISTORY_LINEthis.DOCUMENT_UPD = this.APARENT.MYDOCthis.USER_UPD=this.ACTX.USERthis.CRETIM_UPD=timestamp$this.NBTIMES_UPD=1Return# A propagation rule is triggered on the history if document number is changed$PROPERTIESCase CURPROWhen "NUMDOC"Case ACTIONWhen "PROPAGATE"Gosub PROPAGATE_NUMDOCEndcaseEndcaseReturn# Dedicated method usually called before the creation and the update# Updates the history lines# "this" is the current document instance$UPDATE_HISTORYLocal Integer NUML, TWO_YEARS, OLDLINE, NEWLINE, NBLINES, OK, FIVE_YEARSLocal Decimal TIMESTP# Inititialize values: current timestamp value in milliseconds, number of days for the last 5 years...TIMESTP=val(timestamp$)FIVE_YEARS=(date$-gdat$(day(date$),month(date$),year(date$)-5))OK=[V]CST_AOKOLDLINE=0# Delete the line that is too old (if it is still present and not associated with the user)# Compute also in this loop OLDNUM: If not null, the user is already presentOK=0For NUML=1 To maxtab(this.HISTORY)If this.HISTORY(NUML)<>null : # The pointer can be null if a first validation has been doneIf find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0If this.HISTORY(NUML).USER_UPD=this.ACTX.USEROLDLINE=NUMLElsif val(this.CRETIME_UPD)+FIVE_YEARS*24*3600*1000<TIMESTP : # Timestamps are in millisecondsOK=fmet this.ADELLINE("HISTORY",NUML)Break (OK<>[V]CST_AOK)EndifEndifEndifNext NUML# Handle the errorIf OK<>[V]CST_AOKASTATUS=fmet this.ASETERROR("","Cannot delete line from history"-num$(NUML),[V]CST_AERROR)ReturnEndif# Insert a line at the first position of the grid to store the most recent user updating the documentNEWLINE=fmet this.ADDLINE("HISTORY",[V]CST_AFIRSTPOS)If NEWLINE=[V]CST_ANOTDEFINEDASTATUS=fmet this.ASETERROR("","Cannot add line in history",[V]CST_AERROR)ReturnEndif# If a line already existed for the customer, update the last line and delete the previous oneIf OLDLINE<>0this.HISTORY(NEWLINE).NBTIMES_UPD=this.HISTORY(OLDLINE).NBTIMES_UPD+1OK=fmet this.ADELLINE("HISTORY",OLDLINE)Endif# Handle the errorIf OK<>[V]CST_AOKASTATUS=fmet this.ASETERROR("","Cannot delete line from history"-num$(NUML),[V]CST_AERROR)ReturnEndif# Count the number of lines in the collectionNBLINES=0For NUML=1 To maxtab(this.HISTORY)If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0NBLINES+=1EndifNext NUML# Delete the line having an index over 10# Here the technical property AORDER is used# But the AGETINDBYLINE method could also have been usedIf NBLINES>10OK=[V]CST_AOKFor NUML=1 To maxtab(this.HISTORY)If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0If this.HISTORY(NUML).AORDER>10OK=fmet this.ADELLINE("HISTORY",NUML)Break (OK<>[V]CST_AOK)EndifEndifNext NUMLEndif# Handle the errorIf OK<>[V]CST_AOKASTATUS=fmet this.ASETERROR("","Cannot delete line from history"-num$(NUML),[V]CST_AERROR)ReturnEndifReturn$PROPAGATE_NUMDOCFor NUML=1 To maxtab(this.HISTORY)If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0this.HISTORY(NUML).DOCUMENT_UPD = this.MYDOCEndifNext NUMLReturn# Computes the percentage of updates$COMPUTE_HISTORYLocal Integer NBLINE, TOTLINE# Count the number of lines in the collection and the totalNBLINES=0For NUML=1 To maxtab(this.HISTORY)If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0NBLINES+=1TOTLINE+=this.HISTORY(NUML).NBTIMES_UPDEndifNext NUML# Assign the percentagesFor NUML=1 To maxtab(this.HISTORY)If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0this.HISTORY(NUML).PERC_UPD=ar2(100*this.HISTORY(NUML).NBTIMES_UPD/TOTLINE)EndifNext NUMLReturn

Refer to the Classes Standard Methods Developer Guide for more information on collections.