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 controller.
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 controller 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 controller is as follows:
In the instance list controller define 2 collections like this:
* Keep track of all registered active filters and command handlers
DEFINE_COM CLASS(#Prim_Acol<#VF_ac007O >) NAME(#ActiveFilters) /* VF_AC007 for WIN */
DEFINE_COM CLASS(#Prim_Acol<#VF_ac010O>) NAME(#ActiveHandlers) /* VF_AC010 for WIN */
Then add 2 methods like this:
MthRoutine RegisterInitialize
Define_map *input #VF_AC007O #Filter Pass(*By_Reference) Mandatory(null)
Define_map *input #VF_AC010O #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_AC007O #Filter Pass(*By_Reference) Mandatory(null)
Define_map *input #VF_AC010O #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_COM CLASS(#EMPMNGR) NAME(#EmployeeController) scope(*Application)
MthRoutine uInitialize Options(*Redefine)
Invoke # EmployeeController.RegisterInitialize Filter(#Com_Owner)
Endroutine
In a command handler do this:
MthRoutine uInitialize Options(*Redefine)
Invoke #EmployeeController.RegisterInitialize Handler(#Com_Owner)
Endroutine
MthRoutine uTerminate Options(*Redefine)
Invoke #EmployeeController.RegisterTerminate Filter(#Com_Owner)
Endroutine
In a command handler do this:
MthRoutine uTerminate Options(*Redefine)
Invoke #EmployeeController.RegisterTerminate Handler(#Com_Owner)
Endroutine
Note: It is really important that the uTerminate logic is used.
Your instance list controller is now aware all active filters and command handlers that are doing something with the business object (e.g. Employees).
It can start to perform common shared actions on their behalf.
For example, if your instance list controller 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 controller 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 controller 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 Signal_EmployeeUpdate
Define_map *input #Empno #EmployeeNumber
Signal EmployeeUpdate EmployeeNumber(#EmployeeNumber)
Endroutine
Mthroutine Signal_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(#EmployeeController.EmployeeUpdate)
EmployeeNumber(#EmployeeNumber)
Use Message_box_show (ok ok info *Component ("I have just been notified that employee number " + #EmployeeNumber + " has been updated"))
Endroutine
Evtroutine Handling(#EmployeeController.EmployeeDelete)
EmployeeNumber(#EmployeeNUmber)
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:
#EmployeeController.Signal_EmployeeUpdate EmployeeNumber(#Empno)
or
#EmployeeController.Signal_EmployeeDelete EmployeeNumber(#Empno)