Early on as an Apex developer, I adopted the following one-trigger-per-object design pattern:
Class
public with sharing class caseTriggerHandler {
public static boolean firstRun = true;
private boolean m_isExecuting = false;
public caseTriggerHandler (boolean isExecuting){
m_isExecuting = isExecuting;
}
public void OnBeforeInsert(List<Case> newCases){
// EXECUTE BEFORE INSERT LOGIC
}
public void OnAfterInsert(Case[] newCases, Map<Id, Case> caseNewMap){
// AFTER INSERT LOGIC
}
public void OnBeforeUpdate(Case[] oldCases, Case[] updatedCases, Map<Id, Case> caseOldMap, Map<Id, Case> caseNewMap){
// BEFORE UPDATE LOGIC
}
public void OnAfterUpdate(Case[] oldCases, Case[] updatedCases, Map<Id, Case> caseNewMap, Map<Id, Case> caseOldMap){
// PREVENT RECURSIVE TRIGGER
if (firstRun){
firstRun = false;
system.debug('First Run');
} else {
System.debug('Already ran!');
return;
}
// AFTER UPDATE LOGIC
}
public void OnBeforeDelete(Case[] CasesToDelete, Map<Id, Case> caseMap){
// BEFORE DELETE LOGIC
}
public void OnAfterDelete(Case[] deletedCases, Map<Id, Case> caseMap){
// AFTER DELETE LOGIC
}
public void OnUndelete(Case[] restoredCases){
// AFTER UNDELETE LOGIC
}
public boolean IsTriggerContext{
get{ return m_isExecuting;}
}
}
Trigger
trigger caseTrigger on Case (after delete, after insert, after undelete,
after update, before delete, before insert, before update) {
caseTriggerHandler handler = new caseTriggerHandler (true);
/* Before Insert */
if(Trigger.isInsert && Trigger.isBefore){
handler.OnBeforeInsert(Trigger.new);
}
/* After Insert */
else if(Trigger.isInsert && Trigger.isAfter){
handler.OnAfterInsert(Trigger.new, Trigger.newMap);
}
/* Before Update */
else if(Trigger.isUpdate && Trigger.isBefore){
handler.OnBeforeUpdate(Trigger.old, Trigger.new, Trigger.oldMap, Trigger.newMap);
}
/* After Update */
else if(Trigger.isUpdate && Trigger.isAfter){
handler.OnAfterUpdate(Trigger.old, Trigger.new, Trigger.newMap, Trigger.oldMap);
}
/* Before Delete */
else if(Trigger.isDelete && Trigger.isBefore){
handler.OnBeforeDelete(Trigger.old, Trigger.oldMap);
}
/* After Delete */
else if(Trigger.isDelete && Trigger.isAfter){
handler.OnAfterDelete(Trigger.old, Trigger.oldMap);
}
/* After Undelete */
else if(Trigger.isUnDelete){
handler.OnUndelete(Trigger.new);
}
}
However, I now cannot recall how exactly the parameters in the trigger's methods feed the class' methods.
For instance, the trigger's handler.OnAfterUpdate(Trigger.old, Trigger.new, Trigger.newMap, Trigger.oldMap);
obviously calls and populates:
OnAfterUpdate(Case[] oldCases, Case[] updatedCases, Map<Id, Case> caseNewMap, Map<Id, Case> caseOldMap)
in the class.
But the list and map parameters in the class method are generic (apart from the arbitrary words used for their variables). So how is it that oldCases ends up specifically storing trigger.old, updatedCases storing trigger.new and so on?
I bet the answer is obvious, staring me in the face, right under my nose, etc...