Delegate Common Tasks to your own Instance List 'Manager'
So far we have seen how the task of adding to, updating and deleting instance list entries may be delegated to a common shared instance list 'manager'.
Any other activity that is likely to involve repeated code in a filter or a command handler can usually be delegated in the same way.
For example, in the preceding section RAMP scripts can access the instance list 'manager' by signaling an event to it via a listening filter. Since you will not always know which filter is listening, you would have to repeat the listening code in every filter.
One way to delegate this listening task, and virtually any listening task, to a common shared instance list manager is as follows:
In the instance list 'manager' define 2 collections like this:
* Keep track of all registered active filters and command handlers
DEFINE_COM CLASS(#Prim_Acol<#VF_ac007>) NAME(#ActiveFilters)
DEFINE_COM CLASS(#Prim_Acol<#VF_ac010>) NAME(#ActiveHandlers)
Then add 2 methods like this:
MthRoutine RegisterInitialize
Define_map *input #VF_AC007 #Filter Pass(*By_Reference) Mandatory(null)
Define_map *input #VF_AC010 #Handler Pass(*By_Reference) Mandatory(null)
* Keep track of registered and active filters
If_ref #Filter is_not(*null)
Invoke #ActiveFilters.Insert Item(#Filter)
Endif
* Keep track of all registered and active command handlers
If_ref #Handler is_not(*null)
Invoke #ActiveHandlers.Insert Item(#Handler)
Endif
Endroutine
MthRoutine RegisterTerminate
Define_map *input #VF_AC007 #Filter Pass(*By_Reference) Mandatory(null)
Define_map *input #VF_AC010 #Handler Pass(*By_Reference) Mandatory(null)
* Remove the specified filter from the active collection
If_ref #Filter is_not(*null)
Invoke #ActiveFilters.Remove Object(#Filter)
Endif
* Remove the specifeid command handler from the active collection
If_ref #Handler is_not(*null)
Invoke #ActiveHandlers.Remove Object(#Handler)
Endif
Endroutine
Now, in each filter or command handler, you need to do three things:
- Define the instance list manager:
DEFINE_COM CLASS(#EMPMNGR) NAME(#EmployeeManager) scope(*Application)
- Register with the instance list manager when starting up. In a filter do this:
MthRoutine uInitialize Options(*Redefine)
Invoke #EmployeeManager.RegisterInitialize Filter(#Com_Owner)
Endroutine
In a command handler do this:
MthRoutine uInitialize Options(*Redefine)
Invoke #EmployeeManager.RegisterInitialize Handler(#Com_Owner)
Endroutine
- (De)Register with the instance list manager when terminating. In a filter do this:
MthRoutine uTerminate Options(*Redefine)
Invoke #EmployeeManager.RegisterTerminate Filter(#Com_Owner)
Endroutine
In a command handler do this:
MthRoutine uTerminate Options(*Redefine)
Invoke #EmployeeManager.RegisterTerminate Handler(#Com_Owner)
Endroutine
Your instance list 'manager' is now aware all active filters and command handlers that are actively doing something with the business object (eg: Employees).
It can start to perform common shared actions on their behalf.
For example, if your instance list 'manager' had an event routine like this in it:
Evtroutine Handling(#ActiveFilters<>.avEvent) WithId(#EventId) WithAInfo1(#AInfo1) WithAInfo2(#AInfo2) WithAInfo3(#AInfo3) COM_Sender(#SendingFilter) Options(*NOCLEARMESSAGES *NOCLEARERRORS)
Case #EventId.Value
When (= UPDATE_EMPLOYEE_5250)
#Com_Owner.UpdateListDetails ListManager(#SendingFilter.avListManager) ForEmpno(#AInfo1)
When (= DELETE_EMPLOYEE_5250)
#Com_Owner.DeleteListDetails ListManager(#SendingFilter.avListManager) ForEmpno(#AInfo1) inDepartment(#AInfo2) InSection(#AInfo3)
EndCase
Endroutine
then it has taken over the job of listening for RAMP script events for all filters. There is no longer any need to add this listening code to any specific filter.
The use of #ActiveFilters<>.avEvent is special. This instance list manager event routine is listening in to (or, eavesdropping, if you like) to all the filters that have registered with it. You can do the same sort of thing using #ActiveHandlers<> of course.
On the other side of this coin, an instance list manager can also signal events to all active filters and command handlers. Typically this is done like this:
First, define the events and methods to signal them into your instance lists 'manager', like in this example:
Define_Evt EmployeeUpdate
Define_map *input #Empno #EmployeeNumber
Define_Evt EmployeeDelete
Define_map *input #Empno #EmployeeNumber
Mthroutine Sig_EmployeeUpdate
Define_map *input #Empno #EmployeeNumber
Signal EmployeeUpdate EmployeeNumber(#EmployeeNumber)
Endroutine
Mthroutine Sig_EmployeeDelete
Define_map *input #Empno #EmployeeNumber
Signal EmployeeDelete EmployeeNumber(#EmployeeNumber)
Endroutine
Now, in any filter or command handler that wants to be notified when these events happen, you just need to put an event handling routine in to listen like this:
Evtroutine Handling(#EmployeeManager.EmployeeUpdate) EmployeeNumber(#EmployeeNUmber) Options(*NOCLEARMESSAGES *NOCLEARERRORS)
Use Message_box_show (ok ok info *Component ("I have just been notified that employee number " + #EmployeeNumber + " has been updated"))
Endroutine
Evtroutine Handling(#EmployeeManager.EmployeeDelete) EmployeeNumber(#EmployeeNUmber) Options(*NOCLEARMESSAGES *NOCLEARERRORS)
Use Message_box_show (ok ok info *Component ("I have just been notified that employee number " + #EmployeeNumber + " has been deleted"))
Endroutine
Finally, in the filter or command handler that wants to signal (or trigger, or notify) the event to others, you just need to do this:
#EmployeeManager.Sig_EmployeeUpdate EmployeeNumber(#Empno)
or
#EmployeeManager.Sig_EmployeeDelete EmployeeNumber(#Empno)