You are viewing an old version of this content. View the current version.
Compare with Current
View Version History
« Previous
Version 13
Next »
The purpose of this trigger framework is to follow the same implementation across all triggers that may be implemented in University of Sydney’s Salesforce instance.
Base Components
The base components of the trigger framework includes:
Click here to expand...
public abstract class USYD_TriggerHandlerBase {
private final string ALL_TRIGGER_KEY = 'USYD_ALL_TRIGGERS';
private final TriggerOperation TEST_DEFAULT_OP = TriggerOperation.BEFORE_INSERT;
private String triggerName = '-Untitled-';
@testvisible
private USYD_Trigger_Setting__mdt allTriggerConfig = USYD_Trigger_Setting__mdt.getInstance(ALL_TRIGGER_KEY);
@testvisible
private USYD_Trigger_Setting__mdt triggerConfig = null;
USYD_System_Config__c config = USYD_System_Config__c.getInstance();
public virtual void beforeInsert(List<SObject> newRecords){}
public virtual void beforeUpdate(List<SObject> oldRecords, List<SObject> newRecords, Map<ID, SObject> oldRecordMap, Map<ID, SObject> newRecordMap){}
public virtual void beforeDelete(List<SObject> oldRecords, Map<ID, SObject> oldRecordMap){}
public virtual void afterInsert(List<SObject> newRecords, Map<ID, SObject> newRecordMap){}
public virtual void afterUpdate(List<SObject> oldRecords, List<SObject> newRecords, Map<ID, SObject> oldRecordMap, Map<ID, SObject> newRecordMap){}
public virtual void afterDelete(List<SObject> oldRecords, Map<ID, SObject> oldRecordMap){}
public virtual void afterUndelete(List<SObject> newRecords, Map<ID, SObject> newRecordMap){}
public USYD_TriggerHandlerBase(String triggerName) {
this.triggerName = triggerName;
this.triggerConfig = USYD_Trigger_Setting__mdt.getInstance(triggerName);
}
private void Log(String source, String message) {
if (config!=null && config.Trigger_Handler_Logging__c !=null && config.Trigger_Handler_Logging__c==true) {
SM_ApplicationLog.addLog(SM_ApplicationLog.LOGGING_LEVEL.INFO.name(),
message, source, null);
}
}
public void execute() {
integer triggerSize = trigger.size;
if (!trigger.isExecuting && !Test.isRunningTest()) return;
if (!(triggerSize>0) && !Test.isRunningTest()) return;
if (this.isTriggerEnabled()) {
this.Log('USYD_TriggerHandlerBase.execute()',
'Trigger ' + this.triggerName + ' executed for event ' + String.valueOf(Trigger.operationType) +
' with ' + String.valueOf(triggerSize) + ' records: trigger switch is ON.');
this.run(Trigger.operationType);
} else {
this.log('USYD_TriggerHandlerBase.execute()',
'Trigger ' + this.triggerName + ' NOT executed for event ' + String.valueOf(Trigger.operationType) +
' with ' + String.valueOf(triggerSize) + ' records: trigger switch is OFF.');
}
SM_ApplicationLog.publishLogs();
}
public boolean isTriggerEnabled() {
boolean enabled = false;
String operation = String.valueOf(trigger.operationType);
if (operation==null && Test.isRunningTest()) operation = string.valueOf(TEST_DEFAULT_OP);
enabled = allTriggerConfig!=null && (boolean.valueOf(allTriggerConfig.get(operation + '__c'))==true);
enabled = enabled ? triggerConfig!=null && (boolean.valueOf(triggerConfig.get(operation + '__c'))==true) : false;
return enabled;
}
private void run(System.TriggerOperation op) {
if (op==null && Test.isRunningTest()) op = TEST_DEFAULT_OP;
switch on op {
when BEFORE_INSERT {
this.beforeInsert(trigger.new);
}
when BEFORE_UPDATE {
this.beforeUpdate(Trigger.old, Trigger.new, Trigger.oldMap, Trigger.newMap);
}
when BEFORE_DELETE {
this.beforeDelete(Trigger.old, Trigger.oldMap);
}
when AFTER_INSERT {
this.afterInsert(Trigger.new, Trigger.newMap);
}
when AFTER_UPDATE {
this.afterUpdate(Trigger.old, Trigger.new, Trigger.oldMap, Trigger.newMap);
}
when AFTER_DELETE {
this.afterDelete(Trigger.old, Trigger.oldMap);
}
when AFTER_UNDELETE {
this.afterUndelete(Trigger.new, Trigger.newMap);
}
}
}
}
USYD_Trigger_Setting__mdt
custom metadata type and its fields, namely:
After_Delete__c
- checkbox to control whether the after delete event will be executed.
After_Insert__c
- checkbox to control whether the after insert event will be executed.
After_Undelete__c
- checkbox to control whether the after insert event will be executed.
After_Update__c
- checkbox to control whether the after insert event will be executed.
Before_Delete__c
- checkbox to control whether the after insert event will be executed.
Before_Insert__c
- checkbox to control whether the after insert event will be executed.
Before_Update__c
- checkbox to control whether the after insert event will be executed.
USYD_System_Config__c.Trigger_Handler_Logging__c
field - checkbox field whether to control whether to log trigger handler invocation. SM_ApplicationLog
class is used for logging.
How to Implement
To use the framework, create an apex trigger as you would normally do. Kindly note, that the developer still needs to define the event that needs to be processed in the trigger itself. This includes the before
and after
events of specific trigger operation (insert
, update
, delete
) that the programmer intend to catch as per business requirement.
Create the handler class by extending the USYD_TriggerHandlerBase
class.
Create include a constructor
method which carries a String
parameter to pass/contain the trigger name (which can be automatically determined from the trigger body).
Override the applicable events (methods) that need to be implemented/executed (i.e. beforeInsert
, beforeUpdate
, etc.).
Write the business logic. It is recommended to have the business logic written in a separate method and invoke it from the overridden event/method, rather than in the event itself. This promotes separation of event invocation from business logic. The developer may also opt to have business logic written in a separate class and just invoke it from the applicable events.
Sample Trigger Handler Class:
//AccountTriggerHandler.cls
public class AccountTriggerHandler extends USYD_TriggerHandlerBase{
//constructor as explained in step #2
public TriggerTestTriggerHandler(String triggerName) {
super(triggerName);
}
//overridden events as described in step #3
public override void beforeInsert(List<sObject> newRecords){
for (Account record : (Account[])newRecords) {
//invoke before insert business logic as described in step #4
}
}
//overridden events as described in step #3
public override void beforeUpdate(List<sObject> oldRecords, List<sObject> newRecords, Map<ID, sObject> oldRecordMap, Map<ID, sObject> newRecordMap){
for (Account record : (Account[])newRecords) {
//invoke before update business logic as described in step #4
}
}
}
In the trigger code, determine the name of the current trigger by having the this code just before invoking the trigger handler class: String triggerName = String.valueOf(this).split(':')[0];