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.
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) $METHODS Case CURPTH When "HISTORY" : # Events on a collection Case ACTION When "ADDLINE_AFTER" Gosub INIT_HISTORY_LINE Endcase When "" : # Global events Case ACTION When "UPDATE_HISTORY" Gosub UPDATE_HISTORY When "READ_AFTER" Gosub COMPUTE_HISTORY Endcase Endcase Return $INIT_HISTORY_LINE this.DOCUMENT_UPD = this.APARENT.MYDOC this.USER_UPD=this.ACTX.USER this.CRETIM_UPD=timestamp$ this.NBTIMES_UPD=1 Return # A propagation rule is triggered on the history if document number is changed $PROPERTIES Case CURPRO When "NUMDOC" Case ACTION When "PROPAGATE" Gosub PROPAGATE_NUMDOC Endcase Endcase Return # Dedicated method usually called before the creation and the update # Updates the history lines # "this" is the current document instance $UPDATE_HISTORY Local Integer NUML, TWO_YEARS, OLDLINE, NEWLINE, NBLINES, OK, FIVE_YEARS Local 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_AOK OLDLINE=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 present OK=0 For NUML=1 To maxtab(this.HISTORY) If this.HISTORY(NUML)<>null : # The pointer can be null if a first validation has been done If find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0 If this.HISTORY(NUML).USER_UPD=this.ACTX.USER OLDLINE=NUML Elsif val(this.CRETIME_UPD)+FIVE_YEARS*24*3600*1000<TIMESTP : # Timestamps are in milliseconds OK=fmet this.ADELLINE("HISTORY",NUML) Break (OK<>[V]CST_AOK) Endif Endif Endif Next NUML # Handle the error If OK<>[V]CST_AOK ASTATUS=fmet this.ASETERROR("","Cannot delete line from history"-num$(NUML),[V]CST_AERROR) Return Endif # Insert a line at the first position of the grid to store the most recent user updating the document NEWLINE=fmet this.ADDLINE("HISTORY",[V]CST_AFIRSTPOS) If NEWLINE=[V]CST_ANOTDEFINED ASTATUS=fmet this.ASETERROR("","Cannot add line in history",[V]CST_AERROR) Return Endif # If a line already existed for the customer, update the last line and delete the previous one If OLDLINE<>0 this.HISTORY(NEWLINE).NBTIMES_UPD=this.HISTORY(OLDLINE).NBTIMES_UPD+1 OK=fmet this.ADELLINE("HISTORY",OLDLINE) Endif # Handle the error If OK<>[V]CST_AOK ASTATUS=fmet this.ASETERROR("","Cannot delete line from history"-num$(NUML),[V]CST_AERROR) Return Endif # Count the number of lines in the collection NBLINES=0 For NUML=1 To maxtab(this.HISTORY) If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0 NBLINES+=1 Endif Next NUML # Delete the line having an index over 10 # Here the technical property AORDER is used # But the AGETINDBYLINE method could also have been used If NBLINES>10 OK=[V]CST_AOK For NUML=1 To maxtab(this.HISTORY) If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0 If this.HISTORY(NUML).AORDER>10 OK=fmet this.ADELLINE("HISTORY",NUML) Break (OK<>[V]CST_AOK) Endif Endif Next NUML Endif # Handle the error If OK<>[V]CST_AOK ASTATUS=fmet this.ASETERROR("","Cannot delete line from history"-num$(NUML),[V]CST_AERROR) Return Endif Return $PROPAGATE_NUMDOC For NUML=1 To maxtab(this.HISTORY) If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0 this.HISTORY(NUML).DOCUMENT_UPD = this.MYDOC Endif Next NUML Return # Computes the percentage of updates $COMPUTE_HISTORY Local Integer NBLINE, TOTLINE # Count the number of lines in the collection and the total NBLINES=0 For NUML=1 To maxtab(this.HISTORY) If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0 NBLINES+=1 TOTLINE+=this.HISTORY(NUML).NBTIMES_UPD Endif Next NUML # Assign the percentages For NUML=1 To maxtab(this.HISTORY) If this.HISTORY(NUML)<>null & find(this.HISTORY(NUML).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0 this.HISTORY(NUML).PERC_UPD=ar2(100*this.HISTORY(NUML).NBTIMES_UPD/TOTLINE) Endif Next NUML Return
Refer to the Classes Standard Methods Developer Guide for more information on collections.