-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathDML.cls
More file actions
131 lines (115 loc) · 4.71 KB
/
Copy pathDML.cls
File metadata and controls
131 lines (115 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
@SuppressWarnings('PMD.CognitiveComplexity')
public virtual without sharing class DML implements IDML {
/**
* To use this class properly, see the Factory class:
* DML should be injected as a dependency by the factory
* then in your tests, the Factory.withMocks method
* becomes your one-stop-shop signal for switching to the DMLMock in tests
*/
@TestVisible
private static final Integer MAX_DML_CHUNKING = 10;
private System.AccessLevel accessLevel = System.AccessLevel.SYSTEM_MODE;
private Database.DMLOptions options {
get {
if (this.options == null) {
this.options = new Database.DMLOptions();
}
this.options.OptAllOrNone = this.options.OptAllOrNone ?? true;
return this.options;
}
set;
}
private enum OperationLoggingValue {
INSERTING,
UPDATING,
UPSERTING,
DELETING,
UNDELETING,
PUBLISHING
}
public virtual Database.SaveResult doInsert(SObject record) {
return this.doInsert(new List<SObject>{ record })[0];
}
public virtual List<Database.SaveResult> doInsert(List<SObject> records) {
this.sortToPreventChunkingErrors(records);
log(OperationLoggingValue.INSERTING, records);
return Database.insert(records, this.options, this.accessLevel);
}
public virtual Database.SaveResult doUpdate(SObject record) {
return this.doUpdate(new List<SObject>{ record })[0];
}
public virtual List<Database.SaveResult> doUpdate(List<SObject> records) {
this.sortToPreventChunkingErrors(records);
log(OperationLoggingValue.UPDATING, records);
return Database.update(records, this.options, this.accessLevel);
}
public virtual Database.UpsertResult doUpsert(SObject record) {
return this.doUpsert(new List<SObject>{ record })[0];
}
public virtual List<Database.UpsertResult> doUpsert(List<SObject> records) {
this.sortToPreventChunkingErrors(records);
log(OperationLoggingValue.UPSERTING, records);
return Database.upsert(records, this.options.OptAllOrNone, this.accessLevel);
}
public virtual List<Database.UpsertResult> doUpsert(List<SObject> records, Schema.SObjectField externalIdField) {
this.sortToPreventChunkingErrors(records);
log(OperationLoggingValue.UPSERTING, records);
return Database.upsert(records, externalIdField, this.options.OptAllOrNone, this.accessLevel);
}
public virtual Database.UndeleteResult doUndelete(SObject record) {
return this.doUndelete(new List<SObject>{ record })[0];
}
public virtual List<Database.UndeleteResult> doUndelete(List<SObject> records) {
log(OperationLoggingValue.UNDELETING, records);
return Database.undelete(records, this.options.OptAllOrNone, this.accessLevel);
}
public virtual Database.DeleteResult doDelete(SObject record) {
return this.doDelete(new List<SObject>{ record })[0];
}
public virtual List<Database.DeleteResult> doDelete(List<SObject> records) {
log(OperationLoggingValue.DELETING, records);
return Database.delete(records, this.options.OptAllOrNone, this.accessLevel);
}
public virtual Database.DeleteResult doHardDelete(SObject record) {
return this.doHardDelete(new List<SObject>{ record })[0];
}
public virtual List<Database.DeleteResult> doHardDelete(List<SObject> records) {
List<Database.DeleteResult> results = this.doDelete(records);
if (records.isEmpty()) {
return results;
}
System.debug(System.LoggingLevel.FINE, 'emptying recycling bin...');
Database.emptyRecycleBin(records);
return results;
}
public virtual Database.SaveResult publish(SObject event) {
log(OperationLoggingValue.PUBLISHING, event);
return EventBus.publish(event);
}
public virtual List<Database.SaveResult> publish(List<SObject> events) {
log(OperationLoggingValue.PUBLISHING, events);
return EventBus.publish(events);
}
public DML setOptions(Database.DMLOptions options) {
return this.setOptions(options, this.accessLevel);
}
public DML setOptions(Database.DMLOptions options, System.AccessLevel accessLevel) {
this.options = options ?? this.options;
this.accessLevel = accessLevel;
return this;
}
private void sortToPreventChunkingErrors(List<SObject> records) {
// prevents a chunking error that can occur if SObject types are in the list out of order.
// no need to sort if the list size is below the limit
if (records.size() >= MAX_DML_CHUNKING) {
records.sort();
}
}
private static void log(OperationLoggingValue loggingValue, Object recordOrRecords) {
Integer size = (recordOrRecords instanceof List<SObject>) ? ((List<SObject>) recordOrRecords).size() : 1;
System.debug(
System.LoggingLevel.FINEST,
loggingValue.name().toLowerCase() + ' ' + size + ' record' + (size > 1 ? 's' : '') + '...'
);
}
}