├── Trigger Framework
├── TriggerFramework.png
└── AbstractTriggerContext.cls
├── Export Meta data UI + Controller
├── ExportMetaDataDetails.page
└── ExportMetaDataDetails.apxc
├── README.md
└── ApexUtilities.cls
/Trigger Framework/TriggerFramework.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vimaltiwari2612/SalesforceApexUtilites/HEAD/Trigger Framework/TriggerFramework.png
--------------------------------------------------------------------------------
/Export Meta data UI + Controller/ExportMetaDataDetails.page:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Export Meta data UI + Controller/ExportMetaDataDetails.apxc:
--------------------------------------------------------------------------------
1 | public class ExportMetaDataDetails {
2 |
3 | public List customFields {get;set;}
4 | public String objectName {get;set;}
5 |
6 | public void getAllCustomFields(){
7 | customFields = new List();
8 | System.debug('objectName '+objectName);
9 | if(objectName == null || objectName == '' || objectName.trim() == '') return;
10 | Map completeSchema = Schema.getGlobalDescribe();
11 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
12 | System.debug('requiredObject '+requiredObject);
13 | for(Schema.SObjectField f : requiredObject.getDescribe().fields.getMap().values()){
14 | Schema.DescribeFieldResult fq = f.getDescribe();
15 | String name = fq.getName();
16 | String label = fq.getLabel();
17 | String fType = fq.getType().name();
18 | if(name.endsWithIgnoreCase('__c')){
19 | System.debug(name+' '+label+' '+ftype);
20 | customFields.add(new field(label,name,fType));
21 | }
22 | }
23 | }
24 |
25 |
26 | class Field{
27 | public String label {get;set;}
28 | public String apiname {get;set;}
29 | public String fType {get;set;}
30 |
31 | public Field(String label,String apiname,String fType){
32 | this.label=label;
33 | this.apiname=apiname;
34 | this.fType=fType;
35 | }
36 |
37 | }
38 |
39 | }
40 |
41 |
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SalesforceApexUtilites
2 |
3 | Many times, we came across such scenarios, where we need to use Apex standard APIs like Schema or Describe, and we end up searching the code on the Internet.
4 |
5 | Here is a Util class, that you can deploy in your org and use it whenever needed. Also, add new methods in it, if required.
6 |
7 | The class had All the bulkified versions of all methods too.
8 |
9 | https://medium.com/elevate-salesforce/salesforce-apex-utilities-fe11692a9288
10 |
11 |
12 | --------------------------------------------------
13 | # Trigger Framework POC
14 |
15 | Complete Details :
16 |
17 | https://medium.com/elevate-salesforce/apex-trigger-framework-a-generic-way-to-join-tigger-contexts-46c4d9277db0
18 |
19 | ***This Framework is beneficial when we have more than one triggers on any object. This Framwwork will help us to keep only one trigger on an object irrrespective of different packages and business use cases***
20 |
21 | Developers extend "AbstractTriggerContext" class, and override necessary methods which are needed.
22 | Then they need to register their classes in a Custom meta data with the context and operation type
23 |
24 | **Framework Overview**
25 |
26 | The idea is to join all the trigger contexts of similar types, together. For example, all BEFORE (INSERT/UPDATE/DELETE) will run together, doesn’t matter, it’s a package trigger or custom trigger logic added by customers.
27 |
28 | 
29 |
30 |
31 | **Architecture Overview**
32 |
33 | 
34 |
35 |
36 |
37 |
38 |
39 |
40 | Custom Meta Data details
41 | 1. Class Name : Name of class
42 | 2. Context : Before/After
43 | 3. operation : delete, undelete, insert, update
44 | 4. object name : for which object you want to run given class code
45 | 5. Is Active : to enable /disable trigge logics
46 |
47 |
48 | Usage : Sample Account Trigger
49 | trigger AccountTrigger on Account (before insert, after insert) {
50 |
51 | AbstractTriggerContext.run('Account',Trigger.operationType,Trigger.new, Trigger.old,Trigger.newMap,Trigger.oldMap);
52 | }
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Trigger Framework/AbstractTriggerContext.cls:
--------------------------------------------------------------------------------
1 | /*
2 | This Framework is beneficial when we have more than one triggers on any object.
3 | Developers extend this class, and override necessary methods which are needed.
4 | Then they need to register their classes in a Custom meta data with the context and operation type
5 |
6 |
7 | Custom Meta Data details
8 | 1. Class Name : Name of class
9 | 2. Context : Before/After
10 | 3. operation : delete, undelete, insert, update
11 | 4. object name : for which object you want to run given class code
12 | 5. Is Active : to enable /disable trigge logics
13 |
14 |
15 | Usage : sample Account Trigger
16 | trigger AccountTrigger on Account (before insert, after insert) {
17 |
18 | AbstractTriggerContext.run('Account',Trigger.operationType,Trigger.new, Trigger.old,Trigger.newMap,Trigger.oldMap);
19 | }
20 |
21 | */
22 |
23 |
24 |
25 | global abstract class AbstractTriggerContext {
26 |
27 | global static void run(String objectName, System.TriggerOperation operationType, List newList, List oldList, Map newMap, Map oldMap){
28 | //query the meta data
29 | for(TriggerContext__mdt record : getMetaData(objectName,operationType)){
30 | //get the instance
31 | AbstractTriggerContext instance = (AbstractTriggerContext)Type.forName(record.Class_Name__c).newInstance();
32 | //call the method
33 | if(operationType == System.TriggerOperation.BEFORE_INSERT){
34 | instance.beforeInsert(newList, oldList, newMap, oldMap);
35 | }else if(operationType == System.TriggerOperation.BEFORE_UPDATE){
36 | instance.beforeUpdate(newList, oldList, newMap, oldMap);
37 | }else if(operationType == System.TriggerOperation.BEFORE_DELETE){
38 | instance.beforeDelete(oldList, oldMap);
39 | }else if(operationType == System.TriggerOperation.AFTER_INSERT){
40 | instance.afterInsert(newList, oldList, newMap, oldMap);
41 | }else if(operationType == System.TriggerOperation.AFTER_UPDATE){
42 | instance.afterUpdate(newList, oldList, newMap, oldMap);
43 | }else if(operationType == System.TriggerOperation.AFTER_UNDELETE){
44 | instance.afterUndelete(newList, newMap);
45 | }
46 | }
47 | }
48 |
49 | global virtual void beforeInsert(List newList, List oldList, Map newMap, Map oldMap){
50 | //override for before insert logic
51 | }
52 |
53 | global virtual void beforeUpdate(List newList, List oldList, Map newMap, Map oldMap){
54 | //override for before update logic
55 | }
56 |
57 | global virtual void afterInsert(List newList, List oldList, Map newMap, Map oldMap){
58 | //override for after insert logic
59 | }
60 |
61 | global virtual void afterUpdate(List newList, List oldList, Map newMap, Map oldMap){
62 | //override for after update logic
63 | }
64 |
65 | global virtual void beforeDelete(List oldList, Map oldMap){
66 | //override for before delete logic
67 | }
68 |
69 | global virtual void afterUndelete(List newList, Map newMap){
70 | //override for after undelete logic
71 | }
72 |
73 |
74 | global static List getMetaData(String objectName, System.TriggerOperation operationType){
75 |
76 | String query = 'Select Class_Name__c from TriggerContext__mdt where Class_Name__c !=null And Is_Active__c = true AND Object_Name__C = :objectName';
77 | String context = '';
78 | if(operationType == System.TriggerOperation.BEFORE_INSERT){
79 | context = ' AND Context__c = \'Before\' AND Operation__c = \'Insert\'';
80 | }else if(operationType == System.TriggerOperation.BEFORE_UPDATE){
81 | context = ' AND Context__c = \'Before\' AND Operation__c = \'Update\'';
82 | }else if(operationType == System.TriggerOperation.BEFORE_DELETE){
83 | context = ' AND Context__c = \'Before\' AND Operation__c = \'Delete\'';
84 | }else if(operationType == System.TriggerOperation.AFTER_INSERT){
85 | context = ' AND Context__c = \'After\' AND Operation__c = \'Insert\'';
86 | }else if(operationType == System.TriggerOperation.AFTER_UPDATE){
87 | context = ' AND Context__c = \'After\' AND Operation__c = \'Update\'';
88 | }else if(operationType == System.TriggerOperation.AFTER_UNDELETE){
89 | context = ' AND Context__c = \'After\' AND Operation__c = \'UnDelete\'';
90 | }
91 | query +=context;
92 | return (List)Database.query(query);
93 | }
94 | }
--------------------------------------------------------------------------------
/ApexUtilities.cls:
--------------------------------------------------------------------------------
1 | global class ApexUtilities{
2 |
3 | /**************************************************** Object Fields Related Methods****************************************************/
4 |
5 | /*
6 | * @methodName = getAllFields
7 | * @return = Set of field Names
8 | * @params = object name (both custom and standard)
9 | * @description = Method takes object name as an argument and return all (both custom and standard) fields
10 | */
11 | global static Set getAllFields(String objectName){
12 | Map completeSchema = Schema.getGlobalDescribe();
13 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
14 | return requiredObject.getDescribe().fields.getMap().keySet();
15 | }
16 |
17 | /*
18 | * @methodName = getAllFields
19 | * @return = Map of object names and their field Names
20 | * @params = List of object name (both custom and standard)
21 | * @description = Method takes object name as an argument and return Map of object name and their (both custom and standard) fields
22 | */
23 | global static Map> getAllFields(List objectNames){
24 | Map completeSchema = Schema.getGlobalDescribe();
25 | Map> objectVsFieldMap = new Map>();
26 | for(String objectName : objectNames){
27 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
28 | objectVsFieldMap.put(objectName,requiredObject.getDescribe().fields.getMap().keySet());
29 | }
30 | return objectVsFieldMap;
31 | }
32 |
33 | /*
34 | * @methodName = getAllCustomFields
35 | * @return = Set of field Names
36 | * @params = object name (both custom and standard)
37 | * @description = Method takes object name as an argument and return all Custom fields
38 | */
39 | global static Set getAllCustomFields(String objectName){
40 | Map completeSchema = Schema.getGlobalDescribe();
41 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
42 | Set customFields = new Set();
43 | for(String field : requiredObject.getDescribe().fields.getMap().keySet()){
44 | if(field.endsWithIgnoreCase('__c')){
45 | customFields.add(field);
46 | }
47 | }
48 | return customFields;
49 | }
50 |
51 | /*
52 | * @methodName = getAllCustomFields
53 | * @return = Map of object names and their field Names
54 | * @params = List of object name (both custom and standard)
55 | * @description = Method takes object name as an argument and return Map of object name and their (custom) fields
56 | */
57 | global static Map> getAllCustomFields(List objectNames){
58 | Map completeSchema = Schema.getGlobalDescribe();
59 | Map> objectVsFieldMap = new Map>();
60 | for(String objectName : objectNames){
61 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
62 | Set customFields = new Set();
63 | for(String field : requiredObject.getDescribe().fields.getMap().keySet()){
64 | if(field.endsWithIgnoreCase('__c')){
65 | customFields.add(field);
66 | }
67 | }
68 | objectVsFieldMap.put(objectName,customFields);
69 | }
70 | return objectVsFieldMap;
71 | }
72 |
73 | /*
74 | * @methodName = getAllStandardFields
75 | * @return = Set of field Names
76 | * @params = object name (both custom and standard)
77 | * @description = Method takes object name as an argument and return all Standard fields
78 | */
79 | global static Set getAllStandardFields(String objectName){
80 | Map completeSchema = Schema.getGlobalDescribe();
81 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
82 | Set standardFields = new Set();
83 | for(String field : requiredObject.getDescribe().fields.getMap().keySet()){
84 | if(!field.endsWithIgnoreCase('__c')){
85 | standardFields.add(field);
86 | }
87 | }
88 | return standardFields;
89 | }
90 |
91 | /*
92 | * @methodName = getAllStandardFields
93 | * @return = Map of object names and their field Names
94 | * @params = List of object name (both custom and standard)
95 | * @description = Method takes object name as an argument and return Map of object name and their (standard) fields
96 | */
97 | global static Map> getAllStandardFields(List objectNames){
98 | Map completeSchema = Schema.getGlobalDescribe();
99 | Map> objectVsFieldMap = new Map>();
100 | for(String objectName : objectNames){
101 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
102 | Set sFields = new Set();
103 | for(String field : requiredObject.getDescribe().fields.getMap().keySet()){
104 | if(!field.endsWithIgnoreCase('__c')){
105 | sFields.add(field);
106 | }
107 | }
108 | objectVsFieldMap.put(objectName,sFields);
109 | }
110 | return objectVsFieldMap;
111 | }
112 |
113 | /*
114 | * @methodName = getAllFieldsInNameSpace
115 | * @return = Set of field Names
116 | * @params = object name (both custom and standard), namespace
117 | * @description = Method takes object name as an argument and return all Standard fields
118 | */
119 | global static Set getAllFieldsInNameSpace(String objectName,String namespace){
120 | Map completeSchema = Schema.getGlobalDescribe();
121 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
122 | Set requiredFields = new Set();
123 | for(String field : requiredObject.getDescribe().fields.getMap().keySet()){
124 | if(field.startsWithIgnoreCase(namespace+'__')){
125 | requiredFields.add(field);
126 | }
127 | }
128 | return requiredFields;
129 | }
130 |
131 | /*
132 | * @methodName = getAllFieldsInNameSpace
133 | * @return = Map of object names and their field Names
134 | * @params = list of object name (both custom and standard), namespace
135 | * @description = Method takes object name as an argument and return Map of object name and their fields
136 | */
137 | global static Map> getAllFieldsInNameSpace(List objectNames,String namespace){
138 | Map completeSchema = Schema.getGlobalDescribe();
139 | Map> objectVsFieldMap = new Map>();
140 | for(String objectName : objectNames){
141 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
142 | Set requiredFields = new Set();
143 | for(String field : requiredObject.getDescribe().fields.getMap().keySet()){
144 | if(field.startsWithIgnoreCase(namespace+'__')){
145 | requiredFields.add(field);
146 | }
147 | }
148 | objectVsFieldMap.put(objectName,requiredFields);
149 | }
150 | return objectVsFieldMap;
151 | }
152 |
153 | /*
154 | * @methodName = getAllFieldsOfType
155 | * @return = Set of field Names
156 | * @params = object name (both custom and standard), and field type like String,Boolean etc
157 | * @description = Method takes object name as an argument and return all (both custom and standard) fields of specific type
158 | */
159 | global static Set getAllFieldsOfType(String objectName,String fieldType){
160 | Map completeSchema = Schema.getGlobalDescribe();
161 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
162 | Set requiredFields = new Set();
163 | for(Schema.SObjectField field : requiredObject.getDescribe().fields.getMap().values()){
164 | Schema.DescribeFieldResult fieldDetails = field.getDescribe();
165 | Schema.DisplayType fType = fieldDetails.getType();
166 | if(fType.name().toLowerCase() == fieldType.toLowerCase()){
167 | requiredFields.add(fieldDetails.getName());
168 | }
169 | }
170 | return requiredFields;
171 | }
172 |
173 | /*
174 | * @methodName = getAllFieldsOfType
175 | * @return = Map of object name vs Fields of required type
176 | * @params = list of object name (both custom and standard), and field type like String,Boolean etc
177 | * @description = Method takes object name as an argument and return all (both custom and standard) fields of specific type
178 | */
179 | global static Map> getAllFieldsOfType(List objectNames, String fieldType){
180 | Map completeSchema = Schema.getGlobalDescribe();
181 | Map> objectVsFieldMap = new Map>();
182 | for(String objectName : objectNames){
183 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
184 | Set requiredFields = new Set();
185 | for(Schema.SObjectField field : requiredObject.getDescribe().fields.getMap().values()){
186 | Schema.DescribeFieldResult fieldDetails = field.getDescribe();
187 | Schema.DisplayType fType = fieldDetails.getType();
188 | if(fType.name().toLowerCase() == fieldType.toLowerCase()){
189 | requiredFields.add(fieldDetails.getName());
190 | }
191 | objectVsFieldMap.put(objectName,requiredFields);
192 | }
193 | }
194 | return objectVsFieldMap;
195 | }
196 |
197 | /*
198 | * @methodName = getAllRequiredFields
199 | * @return = Set of required fields
200 | * @params = object name
201 | * @description = Method takes object name as an argument and return all (both custom and standard) fields which are required
202 | */
203 | global static Set getAllRequiredFields(String objectName){
204 | Map completeSchema = Schema.getGlobalDescribe();
205 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
206 | Set requiredFields = new Set();
207 | for(Schema.SObjectField field : requiredObject.getDescribe().fields.getMap().values()){
208 | Schema.DescribeFieldResult fieldDetails = field.getDescribe();
209 | //IF FIELD IS CREATEABLE AND IS NOT NILLABLE AND IS NOT DEFAULTED ON CREATE THEN ITS REQUIRED
210 | if(fieldDetails.isCreateable() && !fieldDetails.isNillable() && !fieldDetails.isDefaultedOnCreate()){
211 | requiredFields.add(fieldDetails.getName());
212 | }
213 | }
214 | return requiredFields;
215 | }
216 |
217 | /*
218 | * @methodName = getAllRequiredFields
219 | * @return = Map of object name vs Fields which are required
220 | * @params = list of object name (both custom and standard), and field type like String,Boolean etc
221 | * @description = Method takes object name as an argument and return all (both custom and standard) fields which are required
222 | */
223 | global static Map> getAllRequiredFields(List objectNames){
224 | Map completeSchema = Schema.getGlobalDescribe();
225 | Map> objectVsFieldMap = new Map>();
226 | for(String objectName : objectNames){
227 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
228 | Set requiredFields = new Set();
229 | for(Schema.SObjectField field : requiredObject.getDescribe().fields.getMap().values()){
230 | Schema.DescribeFieldResult fieldDetails = field.getDescribe();
231 | //IF FIELD IS CREATEABLE AND IS NOT NILLABLE AND IS NOT DEFAULTED ON CREATE THEN ITS REQUIRED
232 | if(fieldDetails.isCreateable() && !fieldDetails.isNillable() && !fieldDetails.isDefaultedOnCreate()){
233 | requiredFields.add(fieldDetails.getName());
234 | }
235 | objectVsFieldMap.put(objectName,requiredFields);
236 | }
237 | }
238 | return objectVsFieldMap;
239 | }
240 |
241 | /**************************************************** Object Related Methods****************************************************/
242 |
243 |
244 | /*
245 | * @methodName = getObjectNameById
246 | * @return = Object Name
247 | * @params = Salesforce Id
248 | * @description = Method takes SF Id and returns Object name
249 | */
250 | global static String getObjectNameById(Id objectId){
251 | return objectId.getSObjectType().getDescribe().getName();
252 | }
253 |
254 | /*
255 | * @methodName = getObjectNameById
256 | * @return = Map of Id vs Object Name
257 | * @params = Set of Salesforce Id
258 | * @description = Method takes SF Ids and returns Map of Id vs Object name
259 | */
260 | global static Map getObjectNameById(Set objectIds){
261 | Map objectIdVsName = new Map();
262 | for(Id objectId : objectIds){
263 | objectIdVsName.put(objectId,objectId.getSObjectType().getDescribe().getName());
264 | }
265 | return objectIdVsName;
266 | }
267 |
268 | /*
269 | * @methodName = getAllParentOfAnObject
270 | * @return = List of parent objects
271 | * @params = object names
272 | * @description = Method takes object names and returns list of parent object names
273 | */
274 | global static List getAllParentOfAnObject(String objectName){
275 | Map completeSchema = Schema.getGlobalDescribe();
276 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
277 | List parentObjectName = new List();
278 | for(Schema.SobjectField strFld: requiredObject.getDescribe().fields.getMap().Values()){
279 | if(strFld.getDescribe().getType() == Schema.DisplayType.REFERENCE){
280 | for(Schema.SObjectType obj : strFld.getDescribe().getReferenceTo()){
281 | parentObjectName.add(obj.getDescribe().getName());
282 | }
283 | }
284 | }
285 | return parentObjectName;
286 | }
287 |
288 | /*
289 | * @methodName = getAllParentOfAnObject
290 | * @return = List of parent objects
291 | * @params = object names
292 | * @description = Method takes object names and returns Map of object name vs parent object names
293 | */
294 | global static Map> getAllParentOfAnObject(List objectNames){
295 | Map completeSchema = Schema.getGlobalDescribe();
296 | Map> objectNameVsParentObjectNames = new Map>();
297 | for(String objectName : objectNames){
298 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
299 | List parentObjectNames = new List();
300 | for(Schema.SobjectField strFld: requiredObject.getDescribe().fields.getMap().Values()){
301 | if(strFld.getDescribe().getType() == Schema.DisplayType.REFERENCE){
302 | for(Schema.SObjectType obj : strFld.getDescribe().getReferenceTo()){
303 | parentObjectNames.add(obj.getDescribe().getName());
304 | }
305 | }
306 | }
307 | objectNameVsParentObjectNames.put(objectName,parentObjectNames);
308 | }
309 | return objectNameVsParentObjectNames;
310 | }
311 |
312 | /*
313 | * @methodName = getAllChildrenOfAnObject
314 | * @return = List of parent objects
315 | * @params = object names
316 | * @description = Method takes object names and returns list of child object names
317 | */
318 | global static List getAllChildrenOfAnObject(String objectName){
319 | Map completeSchema = Schema.getGlobalDescribe();
320 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
321 | List childObjectName = new List();
322 | Schema.DescribeSObjectResult result = requiredObject.getDescribe();
323 | for (Schema.ChildRelationship cr: result.getChildRelationships()) {
324 | childObjectName.add(cr.getChildSObject().getDescribe().getName());
325 | }
326 | return childObjectName;
327 | }
328 |
329 | /*
330 | * @methodName = getAllChildrenOfAnObject
331 | * @return = List of parent objects
332 | * @params = object names
333 | * @description = Method takes object names and returns Map of object name vs parent object names
334 | */
335 | global static Map> getAllChildrenOfAnObject(List objectNames){
336 | Map completeSchema = Schema.getGlobalDescribe();
337 | Map> objectNameVsChildObjectNames = new Map>();
338 | for(String objectName : objectNames){
339 | Schema.SObjectType requiredObject = completeSchema.get(objectName);
340 | Schema.DescribeSObjectResult result = requiredObject.getDescribe();
341 | List childObjectNames = new List();
342 | for (Schema.ChildRelationship cr: result.getChildRelationships()) {
343 | childObjectNames.add(cr.getChildSObject().getDescribe().getName());
344 | }
345 | objectNameVsChildObjectNames.put(objectName,childObjectNames);
346 | }
347 | return objectNameVsChildObjectNames;
348 | }
349 |
350 |
351 | }
352 |
--------------------------------------------------------------------------------