├── .gitignore
├── LICENSE
├── README.md
└── src
├── classes
├── AccountTriggerHandler.cls
├── AccountTriggerHandler.cls-meta.xml
├── TriggerHandler.cls
├── TriggerHandler.cls-meta.xml
├── TriggerHandlerManager.cls
└── TriggerHandlerManager.cls-meta.xml
└── triggers
├── AccountTrigger.trigger
└── AccountTrigger.trigger-meta.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Xiaoan Lin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SFDC Apex Trigger Framework
2 | @see https://www.xgeek.net/salesforce/a-simple-salesforce-trigger-framework/
3 |
4 |
5 |
7 |
8 |
9 | Well,this is another Salesforce Trigger framework but more simple.
10 |
11 | ## Usage
12 | ###AccountTriggerHandler.cls
13 | ```java
14 | //This is a sample code for AccountTriggerHandler
15 | public class AccountTriggerHandler extends TriggerHandler{
16 |
17 | public override void beforeInsert(){
18 | System.debug( 'AccountTriggerHandler beforeInsert Start' );
19 |
20 | System.debug( 'Trigger.isExecuting : ' + isExecuting );
21 | System.debug( 'Trigger.isInsert : ' + isInsert );
22 | System.debug( 'Trigger.isUpdate : ' + isUpdate );
23 | System.debug( 'Trigger.isDelete : ' + isDelete );
24 | System.debug( 'Trigger.isBefore : ' + isBefore );
25 | System.debug( 'Trigger.isAfter : ' + isAfter );
26 | System.debug( 'Trigger.isUndelete : ' + isUndelete );
27 | System.debug( 'Trigger.new : ' + newList );
28 | System.debug( 'Trigger.newMap : ' + newMap );
29 | System.debug( 'Trigger.old : ' + oldList );
30 | System.debug( 'Trigger.oldMap : ' + oldMap );
31 | System.debug( 'Trigger.size : ' + size );
32 |
33 | System.debug('AccountTriggerHandler beforeInsert End');
34 | }
35 |
36 | public override void afterInsert(){
37 | System.debug('AccountTriggerHandler afterInsert Start');
38 | }
39 |
40 | public override void beforeUpdate(){
41 | System.debug('AccountTriggerHandler beforeUpdate Start');
42 | }
43 |
44 | public override void afterUpdate(){
45 | System.debug('AccountTriggerHandler afterUpdate Start');
46 | }
47 |
48 | public override void beforeDelete(){
49 | System.debug('AccountTriggerHandler beforeDelete Start');
50 | }
51 |
52 | public override void afterDelete(){
53 | System.debug('AccountTriggerHandler afterDelete Start');
54 | }
55 |
56 | public override void afterUndelete(){
57 | System.debug('AccountTriggerHandler afterUndelete Start');
58 | }
59 |
60 | }
61 | ```
62 | ###AccountTrigger.trigger
63 | ####In normal case.
64 | ```java
65 | trigger AccountTrigger on Account (before delete, before insert, before update,
66 | after delete, after insert, after update,after Undelete) {
67 | TriggerHandlerManager handlerManager = new TriggerHandlerManager();
68 | handlerManager.add( new AccountTriggerHandler() );
69 | handlerManager.run();
70 | }
71 | ```
72 | ####Other cases
73 | Stop and resume sObject Trigger in APEX code
74 | ```java
75 | TriggerHandlerManager.stop( 'CustomObject__c' );
76 | TriggerHandlerManager.resume( 'CustomObject__c' );
77 | ```
78 | Stop and resume a TriggerHandler in APEX code
79 | ```java
80 | TriggerHandlerManager.stop( 'AccountTriggerHandler' );
81 | TriggerHandlerManager.resume( 'AccountTriggerHandler' );
82 | ```
83 |
--------------------------------------------------------------------------------
/src/classes/AccountTriggerHandler.cls:
--------------------------------------------------------------------------------
1 | //Sample code for AccountTriggerHandler
2 | public class AccountTriggerHandler extends TriggerHandler{
3 |
4 | public override void beforeInsert(){
5 | System.debug( 'AccountTriggerHandler beforeInsert Start' );
6 |
7 | System.debug( 'Trigger.isExecuting : ' + isExecuting );
8 | System.debug( 'Trigger.isInsert : ' + isInsert );
9 | System.debug( 'Trigger.isUpdate : ' + isUpdate );
10 | System.debug( 'Trigger.isDelete : ' + isDelete );
11 | System.debug( 'Trigger.isBefore : ' + isBefore );
12 | System.debug( 'Trigger.isAfter : ' + isAfter );
13 | System.debug( 'Trigger.isUndelete : ' + isUndelete );
14 | System.debug( 'Trigger.new : ' + newList );
15 | System.debug( 'Trigger.newMap : ' + newMap );
16 | System.debug( 'Trigger.old : ' + oldList );
17 | System.debug( 'Trigger.oldMap : ' + oldMap );
18 | System.debug( 'Trigger.size : ' + size );
19 |
20 | System.debug('AccountTriggerHandler beforeInsert End');
21 | }
22 |
23 | public override void afterInsert(){
24 | System.debug('AccountTriggerHandler afterInsert Start');
25 | }
26 |
27 | public override void beforeUpdate(){
28 | System.debug('AccountTriggerHandler beforeUpdate Start');
29 | }
30 |
31 | public override void afterUpdate(){
32 | System.debug('AccountTriggerHandler afterUpdate Start');
33 | }
34 |
35 | public override void beforeDelete(){
36 | System.debug('AccountTriggerHandler beforeDelete Start');
37 | }
38 |
39 | public override void afterDelete(){
40 | System.debug('AccountTriggerHandler afterDelete Start');
41 | }
42 |
43 | public override void afterUndelete(){
44 | System.debug('AccountTriggerHandler afterUndelete Start');
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/src/classes/AccountTriggerHandler.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/src/classes/TriggerHandler.cls:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2012, Xgeek.net, inc
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification,
6 | * are permitted provided that the following conditions are met:
7 | *
8 | * - Redistributions of source code must retain the above copyright notice,
9 | * this list of conditions and the following disclaimer.
10 | * - Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | * - Neither the name of the Xgeek.net, inc nor the names of its contributors
14 | * may be used to endorse or promote products derived from this software without
15 | * specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 | * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | public virtual class TriggerHandler{
28 |
29 | protected Boolean isExecuting = Trigger.isExecuting;
30 | protected Boolean isInsert = Trigger.isInsert;
31 | protected Boolean isUpdate = Trigger.isUpdate;
32 | protected Boolean isDelete = Trigger.isDelete;
33 | protected Boolean isBefore = Trigger.isBefore;
34 | protected Boolean isAfter = Trigger.isAfter;
35 | protected Boolean isUndelete = Trigger.isUndelete;
36 | protected List newList = Trigger.new;
37 | protected Map newMap = Trigger.newMap;
38 | protected List oldList = Trigger.old;
39 | protected Map oldMap = Trigger.oldMap;
40 | protected Integer size = Trigger.size;
41 |
42 | /**
43 | * Get TriggerHandler class name
44 | * @return String Class Name
45 | */
46 | public String getName(){
47 | return String.valueOf( this ).split( ':' )[0];
48 | }
49 |
50 | /**
51 | * Get sObject name from Trigger
52 | * @return String sObject Name
53 | */
54 | public String getObjectName(){
55 | if( newList != null && !newList.isEmpty() ) return newList[0].getSObjectType().getDescribe().getName();
56 | else return oldList[0].getSObjectType().getDescribe().getName();
57 | }
58 |
59 | public virtual void beforeInsert(){}
60 |
61 | public virtual void beforeUpdate(){}
62 |
63 | public virtual void beforeDelete(){}
64 |
65 | public virtual void afterInsert(){}
66 |
67 | public virtual void afterUpdate(){}
68 |
69 | public virtual void afterDelete(){}
70 |
71 | public virtual void afterUndelete(){}
72 |
73 | }
--------------------------------------------------------------------------------
/src/classes/TriggerHandler.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/src/classes/TriggerHandlerManager.cls:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2012, Xgeek.net, inc
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification,
6 | * are permitted provided that the following conditions are met:
7 | *
8 | * - Redistributions of source code must retain the above copyright notice,
9 | * this list of conditions and the following disclaimer.
10 | * - Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | * - Neither the name of the Xgeek.net, inc nor the names of its contributors
14 | * may be used to endorse or promote products derived from this software without
15 | * specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 | * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | public class TriggerHandlerManager{
28 |
29 | private List handlerList = new List();
30 |
31 | private static Map handlerLockMap = new Map();
32 |
33 | /**
34 | * Add a TriggerHandler
35 | * @param TriggerHandler handler
36 | */
37 | public void add( TriggerHandler handler ) {
38 |
39 | handlerList.add( handler );
40 | }
41 |
42 | /**
43 | * Run Trigger Handlers
44 | */
45 | public void run() {
46 |
47 | if( handlerList.isEmpty() ) return;
48 |
49 | for( TriggerHandler handler : handlerList ) {
50 | //TriggerHandler has been locked.
51 | if( isHandlerLock( handler.getName() ) ) continue;
52 | //sObject Trigger has been locked.
53 | if( isHandlerLock( handler.getObjectName() ) ) continue;
54 |
55 | if( Trigger.isBefore && Trigger.isInsert ) {
56 | handler.beforeInsert();
57 | } else if( Trigger.isBefore && Trigger.isUpdate ) {
58 | handler.beforeUpdate();
59 | } else if( Trigger.isBefore && Trigger.isDelete ) {
60 | handler.beforeDelete();
61 | } else if( Trigger.isAfter && Trigger.isInsert ) {
62 | handler.afterInsert();
63 | } else if( Trigger.isAfter && Trigger.isUpdate ) {
64 | handler.afterUpdate();
65 | } else if( Trigger.isAfter && Trigger.isDelete ) {
66 | handler.afterDelete();
67 | } else if( Trigger.isAfter && Trigger.isUndelete ) {
68 | handler.afterUndelete();
69 | }
70 | }
71 | }
72 |
73 | /**
74 | * Stop a TriggerHandler
75 | * @param String TriggerHandler class name
76 | * @return none
77 | */
78 | public static void stop( String handlerName ) {
79 |
80 | handlerLockMap.put( handlerName, true );
81 | }
82 | /**
83 | * Resume a TriggerHandler
84 | * @param String TriggerHandler class name
85 | * @return none
86 | */
87 | public static void resume( String handlerName ) {
88 |
89 | handlerLockMap.put( handlerName, false );
90 | }
91 |
92 | //TriggerHandler or sObject is locked
93 | private Boolean isHandlerLock( String handlerName ) {
94 |
95 | if( !handlerLockMap.containsKey( handlerName ) ) return false;
96 |
97 | Boolean isLock = handlerLockMap.get( handlerName );
98 | return isLock;
99 | }
100 |
101 | }
--------------------------------------------------------------------------------
/src/classes/TriggerHandlerManager.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/src/triggers/AccountTrigger.trigger:
--------------------------------------------------------------------------------
1 | trigger AccountTrigger on Account (before delete, before insert, before update,
2 | after delete, after insert, after update,
3 | after Undelete) {
4 |
5 | //TriggerHandlerManager.stop( 'CustomObject__c' );
6 | //TriggerHandlerManager.resume( 'CustomObject__c' );
7 | TriggerHandlerManager handlerManager = new TriggerHandlerManager();
8 | handlerManager.add( new AccountTriggerHandler() );
9 | handlerManager.run();
10 | //TriggerHandlerManager.stop( 'AccountTriggerHandler' );
11 | //TriggerHandlerManager.resume( 'AccountTriggerHandler' );
12 | }
--------------------------------------------------------------------------------
/src/triggers/AccountTrigger.trigger-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------