Last active
February 10, 2017 19:08
-
-
Save brandonmikeska/ad27c488d4a98d7c55c1ea84e8b9367e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Class TriggerFactory | |
* | |
* Used to instantiate and execute Trigger Handlers associated with sObjects. | |
*/ | |
public with sharing class TriggerFactory | |
{ | |
// Generate unique executionId for debuging execution results | |
private static String executionId; | |
// Map to make sure each trigger handler only runs once | |
private static Map<sObjectType, Boolean> recursions = new Map<sObjectType, Boolean>(); | |
/** | |
* Public static method to create and execute a trigger handler | |
* | |
* Arguments: | |
* - Schema.sObjectType soType - Object type to process (SObject.sObjectType) | |
* | |
* Throws a TriggerException if a handler has not been created. | |
*/ | |
public static void createHandler(Schema.sObjectType soType) | |
{ | |
// Get a handler appropriate to the object being processed | |
ITrigger handler = getHandler(soType); | |
// Execute the handler for the trigger | |
executionId = generateGUID(); | |
if(isFirstRun(soTYpe)) { | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing... '); | |
execute(handler, soType); | |
} else { | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Not Excuting (Recursive call)... '); | |
} | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending... '); | |
} | |
/** | |
* private static method to control the execution of the handler | |
* | |
* Arguments: | |
* - ITrigger handler - A Trigger Handler to execute | |
* - Schema.sObjectType soType - Object type to process (SObject.sObjectType) | |
*/ | |
private static void execute(ITrigger handler, Schema.sObjectType soType) | |
{ | |
// Before Trigger | |
if (Trigger.isBefore) | |
{ | |
// Call the bulk before to handle any caching of data and enable bulkification | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing Bulk Before. SOQL Count - ' + Limits.getQueries()); | |
handler.bulkBefore(); | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending Bulk Before. SOQL Count - ' + Limits.getQueries()); | |
// Iterate through the records to be deleted passing them to the handler. | |
if (Trigger.isDelete) | |
{ | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing Before Delete. SOQL Count - ' + Limits.getQueries()); | |
for (SObject so : Trigger.old) | |
{ | |
handler.beforeDelete(so); | |
} | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending Before Delete. SOQL Count - ' + Limits.getQueries()); | |
} | |
// Iterate through the records to be inserted passing them to the handler. | |
else if (Trigger.isInsert) | |
{ | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing Before Insert. SOQL Count - ' + Limits.getQueries()); | |
for (SObject so : Trigger.new) | |
{ | |
handler.beforeInsert(so); | |
} | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending Before Insert. SOQL Count - ' + Limits.getQueries()); | |
} | |
// Iterate through the records to be updated passing them to the handler. | |
else if (Trigger.isUpdate) | |
{ | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing Before Update. SOQL Count - ' + Limits.getQueries()); | |
for (SObject so : Trigger.old) | |
{ | |
handler.beforeUpdate(so, Trigger.newMap.get(so.Id)); | |
} | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending Before Update. SOQL Count - ' + Limits.getQueries()); | |
} | |
} | |
else | |
{ | |
// Call the bulk after to handle any caching of data and enable bulkification | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing Bulk After. SOQL Count - ' + Limits.getQueries()); | |
handler.bulkAfter(); | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing Bulk After. SOQL Count - ' + Limits.getQueries()); | |
// Iterate through the records deleted passing them to the handler. | |
if (Trigger.isDelete) | |
{ | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing After Delete. SOQL Count - ' + Limits.getQueries()); | |
for (SObject so : Trigger.old) | |
{ | |
handler.afterDelete(so); | |
} | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending After Delete. SOQL Count - ' + Limits.getQueries()); | |
} | |
// Iterate through the records inserted passing them to the handler. | |
else if (Trigger.isInsert) | |
{ | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing After Insert. SOQL Count - ' + Limits.getQueries()); | |
for (SObject so : Trigger.new) | |
{ | |
handler.afterInsert(so); | |
} | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending After Delete. SOQL Count - ' + Limits.getQueries()); | |
} | |
// Iterate through the records updated passing them to the handler. | |
else if (Trigger.isUpdate) | |
{ | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing After Update. SOQL Count - ' + Limits.getQueries()); | |
for (SObject so : Trigger.old) | |
{ | |
handler.afterUpdate(so, Trigger.newMap.get(so.Id)); | |
} | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending After Delete. SOQL Count - ' + Limits.getQueries()); | |
} | |
} | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Executing Final Function. SOQL Count - ' + Limits.getQueries()); | |
// Perform any post processing | |
handler.andFinally(); | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending Final Function. Overal SOQL Count - ' + Limits.getQueries()); | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending Final Function. Overal SOQL MAX LIMIT - ' + Limits.getLimitQueries()); | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending Final Function. Overal DML Count - ' + Limits.getDMLRows()); | |
System.DEBUG('[TF | ' + soType + '] - ' + executionId + ': Ending Final Function. Overal DML MAX LIMIT - ' + Limits.getLimitDMLRows()); | |
} | |
/** | |
* private static method to get the appropriate handler for the object type. | |
* | |
* Arguments: | |
* - Schema.sObjectType soType - Object type to locate (SObject.sObjectType) | |
* | |
* Returns: ITrigger - A trigger handler if one exists or null. | |
*/ | |
private static ITrigger getHandler(Schema.sObjectType soType) | |
{ | |
try { | |
return (ITrigger)Type.forName(soType.getDescribe().getName() + 'TriggerHandler').newInstance(); | |
} catch(Exception e) { | |
throw new TriggerException('No Trigger Handler registered for Object Type: ' + soType); | |
} | |
} | |
/** | |
* private static method to generate a unique GUID for grouping DEBUG Logs. | |
* | |
* Arguments: NA | |
* | |
* Returns: String in a GUID format | |
*/ | |
private static String generateGUID() | |
{ | |
Blob b = Crypto.GenerateAESKey(128); | |
String h = EncodingUtil.ConvertTohex(b); | |
return h.SubString(0,8)+ '-' + h.SubString(8,12) + '-' + h.SubString(12,16) + '-' + h.SubString(16,20) + '-' + h.substring(20); | |
} | |
/** | |
* private static method to make sure the each trigger handler only runs once | |
* | |
* Arguments: | |
* - Schema.sObjectType soType - Object type to locate (SObject.sObjectType) | |
* | |
* Returns: True or False identify if the trigger handler has already ran | |
*/ | |
private static Boolean isFirstRun(Schema.sObjectType soType) { | |
if(!recursions.containsKey(soType)) { | |
recursions.put(soType, true); | |
return true; | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment