Apex Plugins - Generic Implementation
The generic implementation is new more flexible method of implementing the Duplicate Check apex plugins. The following plugins are available:
- Direct Processing Plugin
- Merge Set Master Plugin
- Merge Set Field Plugin
- After Index Search Plugin
How to start with the generic apex plugin
Step 1 Implement the Apex Interface
First step is to implement the dupcheck.dc3PluginInterface interface in a custom apex class. You can start with any of the examples below. At least the minimal implementation is needed.
Step 2 Enable the Apex Class for execution
Duplicate Check needs to know which class to execute. This is done via the DC Setup tab in Salesforce.
- Go to 'DC Setup'
- Open the 'Settings'. This can be found in the left menu bar under General Setup.
- Scroll down to the 'Apex Plugins' section.
- Select the defined class in the dropdown for 'Plugin Generic'
Direct Processing Plugin
With the direct processing plugin the standard flow of the direct processing feature can be changed. With the default implementation the direct processing will merge/convert the records when the scoring is above a configured threshold. The custom code within the plugin can make a more informed decision based on the information provided. The plugin can stop the direct processing and just store the result or remove a found duplicate from the result set so it will continue with other records.
Example Implementation of the Direct Processing Plugin
global class DefaultGenericPlugin implements dupcheck.dc3PluginInterface {
private static Set<String> implementedEvents = new Set<String>{'DIRECT_PROCESS_BEFORE'};
global Boolean isAvailable(dupcheck.dc3Plugin.PluginEventType eventType) {
return DefaultGenericPlugin.implementedEvents.contains(eventType.name());
}
global Object execute(dupcheck.dc3Plugin.PluginEventType eventType, Object eventData) {
switch on eventType {
when DIRECT_PROCESS_BEFORE {
return this.directProcessBefore((dupcheck.dc3PluginModel.DirectProcessBeforeInput) eventData);
}
when else {
return null;
}
}
}
public dupcheck.dc3PluginModel.DirectProcessBeforeOutput directProcessBefore(dupcheck.dc3PluginModel.DirectProcessBeforeInput input) {
// execute some custom logic based on the input values.
// built the output and tell DC Direct Processing how to continue.
dupcheck.dc3PluginModel.DirectProcessBeforeOutput output = new dupcheck.dc3PluginModel.DirectProcessBeforeOutput(input);
return output;
}
}
Merge Set Master Plugin
With the Merge Set Master plugin there is the possibility to override the selected master record to a record defined via code. The input of the Merge Set Master plugin will contain all relevant information and the Master Record Id defined via the DC Merge Rules.
Example Implementation of the Merge Set Master Plugin
global class DefaultGenericPlugin implements dupcheck.dc3PluginInterface {
private static Set<String> implementedEvents = new Set<String>{'MERGE_SET_MASTER'};
global Boolean isAvailable(dupcheck.dc3Plugin.PluginEventType eventType) {
return DefaultGenericPlugin.implementedEvents.contains(eventType.name());
}
global Object execute(dupcheck.dc3Plugin.PluginEventType eventType, Object eventData) {
switch on eventType {
when MERGE_SET_MASTER {
return this.mergeSetMaster((dupcheck.dc3PluginModel.MergeSetMasterInput) eventData);
}
when else {
return null;
}
}
}
public dupcheck.dc3PluginModel.MergeSetMasterOutput mergeSetMaster(dupcheck.dc3PluginModel.MergeSetMasterInput input) {
dupcheck.dc3PluginModel.MergeSetMasterOutput output = new dupcheck.dc3PluginModel.MergeSetMasterOutput(input);
if (input.objectPrefix == '00Q') {
for (Sobject ld : input.objectDataList) {
Lead leadData = (Lead) ld;
if (leadData.FirstName == 'I WANT TO BE A MASTER') {
output.masterRecordId = leadData.Id;
break;
}
}
}
return output;
}
}
Merge Set Field Plugin
With the Merge Set Field plugin the field selection of a merge can be altered or even custom values can be set for individual fields. The input of the Merge Set Field plugin contains the field selection for each field as this is determined by the DC Merge Rules. In the output it can be defined which field should be taken from which record or if a custom value is needed this value can be set as well.
Example Implementation of the Merge Set Field Plugin
global class DefaultGenericPlugin implements dupcheck.dc3PluginInterface {
private static Set<String> implementedEvents = new Set<String>{'MERGE_SET_FIELD'};
global Boolean isAvailable(dupcheck.dc3Plugin.PluginEventType eventType) {
return DefaultGenericPlugin.implementedEvents.contains(eventType.name());
}
global Object execute(dupcheck.dc3Plugin.PluginEventType eventType, Object eventData) {
switch on eventType {
when MERGE_SET_FIELD {
return this.mergeSetField((dupcheck.dc3PluginModel.MergeSetFieldInput) eventData);
}
when else {
return null;
}
}
}
public dupcheck.dc3PluginModel.MergeSetFieldOutput mergeSetField(dupcheck.dc3PluginModel.MergeSetFieldInput input) {
dupcheck.dc3PluginModel.MergeSetFieldOutput output = new dupcheck.dc3PluginModel.MergeSetFieldOutput(input);
if (input.objectPrefix == '00Q') {
for (String fieldName : input.fieldSourceMap.keySet()) {
if (fieldName == 'FirstName') {
// Take the FirstName value of the record where the FirstName has a certain value.
for (Sobject objectData : input.objectDataList) {
if (String.valueOf(objectData.get(fieldName)) == 'I WANT TO BE TAKEN') {
output.fieldSourceMap.put(fieldName, objectData.Id);
}
}
} else if (fieldName == 'Website') {
// Take the value of the master record
output.fieldSourceMap.put(fieldName, input.masterRecordId);
} else if (fieldName == 'Email') {
// Set a custom value for the email field
output.fieldSourceMap.put(fieldName, 'custom');
output.customValueMap.put(fieldName, 'custom@custom.com');
}
}
}
return output;
}
After Index Search Plugin
Use the After Index Search plugin to feed records into the DC index search.
Example Implementation of the After Index Search Plugin
global class dc3PluginGeneral implements dupcheck.dc3PluginInterface {
global Object execute(dupcheck.dc3Plugin.PluginEventType eventType, Object eventData) {
switch on eventType {
when INDEX_SEARCH_AFTER {
return indexSearchAfter((dupcheck.dc3PluginModel.IndexSearchAfterInput) eventData);
}
when else {
return null;
}
}
}
private static Set implementedEvents = new Set{ 'INDEX_SEARCH_AFTER' };
global Boolean isAvailable(dupcheck.dc3Plugin.PluginEventType eventType) {
return dc3PluginGeneral.implementedEvents.contains(eventType.name());
}
public dupcheck.dc3PluginModel.IndexSearchAfterOutput indexSearchAfter(dupcheck.dc3PluginModel.IndexSearchAfterInput input) {
dupcheck.dc3PluginModel.IndexSearchAfterOutput output = new dupcheck.dc3PluginModel.IndexSearchAfterOutput(input);
// You can add any record Id to the "output.foundRecords" id list.
// Any record id to this list will be used in the score calculation.
for (lead ld : [SELECT Id FROM LEAD LIMIT 100]) {
output.foundRecords.add(ld.Id);
}
return output;
}
}
Interface Definition
In order to use the Generic Apex Plugin the following interface should be implemented in an Apex Class.
dupcheck.dc3PluginInterface
METHODS
Object execute(dupcheck.dc3Plugin.PluginEventType eventType, Object eventData)
This method will be called to execute the actual plugin.
Boolean isAvailable(dc3Plugin.PluginEventType eventType)
This method will be called to check if a certain plugin is implemented.
Example Minimal Implementation
global class DefaultGenericPlugin implements dupcheck.dc3PluginInterface { private static Set<String> implementedEvents = new Set<String>(); global Boolean isAvailable(dupcheck.dc3Plugin.PluginEventType eventType) { return DefaultGenericPlugin.implementedEvents.contains(eventType.name()); } global Object execute(dupcheck.dc3Plugin.PluginEventType eventType, Object eventData) { return null; } }
Class Definitions
ENUM dupcheck.dc3Plugin.PluginEventType
This enum will give information which plugin is executed.
DIRECT_PROCESS_BEFORE, MERGE_SET_MASTER, MERGE_SET_FIELD
dupcheck.dc3PluginModel.DirectProcessBeforeInput
This is the input class of the Direct Process plugin. This class will give you the information needed to make informed decisions within the plugin itself.
PROPERTIES
doConvert | Boolean | Determines if the 'conversion' is configured for the direct processing |
doMerge | Boolean | Determines if the 'merging' is configured for the direct processing. |
feature | String | the feature which has executed the search and calls the direct processing. |
objectData | Sobject | Contains the generic Sobject with the source record for this direct processing. |
objectPrefix | String | The object prefix for this source object. |
searchResults | Map<String,List<dupcheck.dc3SearchResults>>> | The duplicate search results which will be processed by this direct processing. |
dupcheck.dc3PluginModel.DirectProcessBeforeOutput
This is the output class of the Direct Process plugin. This class will give the direct processing functionality instruction on how to proceed.
PROPERTIES
doConvert |
Boolean | Should the direct processing process continue with a convert. |
doMerge | Boolean | Should the direct processing process continue with a merge |
storeAsJob | Boolean | If no merge or convert is executed, should the remainder of the results stored inside a DC Job. |
searchResults | Map<String,dupcheck.dc3SearchResults>> | The duplicate search results which will be processed by this direct processing. |
dupcheck.dc3PluginModel.MergeSetFieldInput
This is the input class of the Merge Set Field plugin. This class will provide the code with the field select determined by the DC Merge Rules.
PROPERTIES
fieldSourceMap | Map<String,String> | This map contains the selection per field of the object. The key contains the fieldname and the value contains the Id of the record which is selected for this field. |
masterRecordId | String | The record Id of the selected master record by the merge rules. |
objectDataList | List<Sobject> | This lists contains all records in the merge process. |
objectPrefix | String | The object prefix for the records included in the merge process. |
dupcheck.dc3PluginModel.MergeSetFieldOutput
This is the output class of the Merge Set Field plugin. The information provided in this class will determine how the field values of the master record will be after the merge has been executed.
PROPERTIES
fieldSourceMap | Map<String,String> | This map contains the selection per field of the object. The key contains the fieldname and the value contains the Id of the record which is selected for this field or a custom value is provided for the field it should contain 'custom'. |
customValueMap | Map<String,Object> | This map contains the custom value for a specific field. The key of the map is the fieldname and the value is a generic object containing the result field value. |
dupcheck.dc3PluginModel.MergeSetMasterInput
This is the input class of the Merge Set Master plugin. This class will provide the code with the master record determined by the DC Merge Rules.
PROPERTIES
masterRecordId | String | The record Id of the selected master record by the merge rules. |
objectDataList | List<Sobject> | This lists contains all records in the merge process. |
objectPrefix | String | The object prefix for the records included in the merge process. |
dupcheck.dc3PluginModel.MergeSetMasterOutput
This is the output class of the Merge Set Master plugin. The information provided in this class will determine which record will be the master record will be after the merge has been executed.
PROPERTIES
masterRecordId | String | The record Id of the record which should remain as master after the merge. |
dupcheck.dc3SearchResult
This class contains the search result for a matching record.
PROPERTIES
score | Integer | The matching score between the source record and the object referenced in the objectData |
objectData | Sobject | The object data of the matched record. |
scenarioScores | List<dupcheck.dc3SearchResult.ScenarioScore> | The individual matching scores per DC Scenario |
dupcheck.dc3SearchResult.ScenarioScore
This class contains the matching scores for an individual scenario
PROPERTIES
scenarioScore | Integer | The matching score between the source record and the object referenced in the objectData for the specified scenario. |
scenarioName | String | The name of the scenario as this can be found in the scenario configuration. |
scenarioId | Id | The Id of the scenario as this can be found in the scenario configurarion |