Best practice for handling collections

Collections of child instances are managed as variable length arrays of instances, with additional technical properties and methods that simplify their management. When this happens in a persistent class, the supervisor takes care of all the code and no additional lines need to be written.

If you need to manage such a collection because of dedicated method inserts or line delete actions in a collection, you must use the dedicated methods listed below.

Insertion and deletion

Control rules

Propagate rules

Concerning the propagate rule:

Line count

Concerning the property that counts the number of lines in a collection:

Example

The following example of code summarizes the different concepts previously discussed. Every section of this program can be considered autonomously. The code is probably not optimized because some actions can be grouped.

The business rules to control are the following:

To handle this, the code will be created only 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

For more information about collections, see the Developer Guide Classes Standard Methods document.