global with sharing class BK_FilterCollectionByField {
global class FilterException extends Exception {}
@InvocableMethod(label='Filter Collection By Field')
global static List<Result> filterRecordsByField(List<Request> requests) {
List<Result> results = new List<Result>();
for(Request request : requests) {
// Validate inputs
if (request.allowEmptyCollection != true && (request.inputRecords == null || request.inputRecords.isEmpty())) {
throw new FilterException('Input record collection is required but empty.');
}
if (request.filterValues == null || request.filterValues.isEmpty()) {
throw new FilterException('Filter values are required but empty.');
}
if (String.isBlank(request.fieldAPIName)) {
throw new FilterException('Field to filter by is required but empty.');
}
List<SObject> filteredRecords = new List<SObject>();
if (request.allowEmptyCollection == true && (request.inputRecords == null || request.inputRecords.isEmpty())) {
// Return empty result if allowed
filteredRecords = new List<SObject>{};
} else {
// Prepare the set or list for filter values based on case sensitivity
Set<String> filterValuesSet = new Set<String>();
if(request.caseSensitive == true) {
filterValuesSet.addAll(request.filterValues);
} else {
for(String value : request.filterValues) {
if(value != null) {
filterValuesSet.add(value.toLowerCase());
}
}
}
// Filter records
for(SObject record : request.inputRecords) {
Object fieldValueObj = record.get(request.fieldAPIName);
if(fieldValueObj != null) {
String fieldValue = String.valueOf(fieldValueObj);
if(request.caseSensitive == true) {
if(filterValuesSet.contains(fieldValue)) {
filteredRecords.add(record);
}
} else {
if(filterValuesSet.contains(fieldValue.toLowerCase())) {
filteredRecords.add(record);
}
}
}
}
}
Result result = new Result();
result.filteredRecords = filteredRecords;
results.add(result);
}
return results;
}
global class Request {
@InvocableVariable(label='Input Records' description='Collection of records to filter' required=true)
global List<SObject> inputRecords;
@InvocableVariable(label='Filter Values' description='Collection of string values to filter by' required=true)
global List<String> filterValues;
@InvocableVariable(label='Field API Name' description='API name of the field to filter by' required=true)
global String fieldAPIName;
@InvocableVariable(label='Allow Empty Collection' description='Allow the input record collection to be empty? Default is false')
global Boolean allowEmptyCollection = false;
@InvocableVariable(label='Case Sensitive' description='Perform case-sensitive matching? Default is false')
global Boolean caseSensitive = false;
}
global class Result {
@InvocableVariable(label='Filtered Records' description='Collection of records that match the filter criteria')
global List<SObject> filteredRecords;
}
}
Test class:
@isTest
private class BK_FilterCollectionByFieldTest {
@isTest
static void testFilterRecordsByField() {
// Create sample accounts
Account acc1 = new Account(Name = 'Test Account 1', AccountNumber = '123');
Account acc2 = new Account(Name = 'Test Account 2', AccountNumber = '456');
Account acc3 = new Account(Name = 'Test Account 3', AccountNumber = '789');
insert new List<Account>{acc1, acc2, acc3};
// Prepare request
BK_FilterCollectionByField.Request request = new BK_FilterCollectionByField.Request();
request.inputRecords = new List<SObject>{acc1, acc2, acc3};
request.filterValues = new List<String>{'123', '789'};
request.fieldAPIName = 'AccountNumber';
request.caseSensitive = true;
// Call the method
List<BK_FilterCollectionByField.Result> results = BK_FilterCollectionByField.filterRecordsByField(
new List<BK_FilterCollectionByField.Request>{request}
);
// Assert the results
System.assertEquals(1, results.size(), 'Should return one result object');
System.assertEquals(2, results[0].filteredRecords.size(), 'Should return two filtered records');
Set<Id> expectedIds = new Set<Id>{acc1.Id, acc3.Id};
Set<Id> resultIds = new Set<Id>();
for(SObject sobj : results[0].filteredRecords) {
resultIds.add(sobj.Id);
}
System.assertEquals(expectedIds, resultIds, 'Filtered records should match expected accounts');
}
@isTest
static void testFilterRecordsByField_CaseInsensitive() {
// Create sample accounts with varying case in AccountNumber
Account acc1 = new Account(Name = 'Test Account 1', AccountNumber = 'abc');
Account acc2 = new Account(Name = 'Test Account 2', AccountNumber = 'DEF');
Account acc3 = new Account(Name = 'Test Account 3', AccountNumber = 'GHI');
insert new List<Account>{acc1, acc2, acc3};
// Prepare request
BK_FilterCollectionByField.Request request = new BK_FilterCollectionByField.Request();
request.inputRecords = new List<SObject>{acc1, acc2, acc3};
request.filterValues = new List<String>{'Abc', 'def'};
request.fieldAPIName = 'AccountNumber';
request.caseSensitive = false;
// Call the method
List<BK_FilterCollectionByField.Result> results = BK_FilterCollectionByField.filterRecordsByField(
new List<BK_FilterCollectionByField.Request>{request}
);
// Assert the results
System.assertEquals(1, results.size(), 'Should return one result object');
System.assertEquals(2, results[0].filteredRecords.size(), 'Should return two filtered records');
Set<Id> expectedIds = new Set<Id>{acc1.Id, acc2.Id};
Set<Id> resultIds = new Set<Id>();
for(SObject sobj : results[0].filteredRecords) {
resultIds.add(sobj.Id);
}
System.assertEquals(expectedIds, resultIds, 'Filtered records should match expected accounts');
}
@isTest
static void testFilterRecordsByField_EmptyCollectionAllowed() {
// Prepare request with empty inputRecords
BK_FilterCollectionByField.Request request = new BK_FilterCollectionByField.Request();
request.inputRecords = new List<SObject>();
request.filterValues = new List<String>{'123', '789'};
request.fieldAPIName = 'AccountNumber';
request.allowEmptyCollection = true;
// Call the method
List<BK_FilterCollectionByField.Result> results = BK_FilterCollectionByField.filterRecordsByField(
new List<BK_FilterCollectionByField.Request>{request}
);
// Assert the results
System.assertEquals(1, results.size(), 'Should return one result object');
System.assertEquals(0, results[0].filteredRecords.size(), 'Should return zero filtered records');
}
@isTest
static void testFilterRecordsByField_ExceptionOnEmptyCollection() {
// Prepare request with empty inputRecords
BK_FilterCollectionByField.Request request = new BK_FilterCollectionByField.Request();
request.inputRecords = new List<SObject>();
request.filterValues = new List<String>{'123', '789'};
request.fieldAPIName = 'AccountNumber';
request.allowEmptyCollection = false;
// Call the method and expect exception
try {
List<BK_FilterCollectionByField.Result> results = BK_FilterCollectionByField.filterRecordsByField(
new List<BK_FilterCollectionByField.Request>{request}
);
System.assert(false, 'Expected an exception due to empty inputRecords');
} catch (Exception ex) {
System.assert(ex instanceof BK_FilterCollectionByField.FilterException, 'Expected a FilterException');
System.assertEquals('Input record collection is required but empty.', ex.getMessage());
}
}
@isTest
static void testFilterRecordsByField_ExceptionOnEmptyFilterValues() {
// Create sample accounts
Account acc1 = new Account(Name = 'Test Account 1', AccountNumber = '123');
insert acc1;
// Prepare request with empty filterValues
BK_FilterCollectionByField.Request request = new BK_FilterCollectionByField.Request();
request.inputRecords = new List<SObject>{acc1};
request.filterValues = new List<String>();
request.fieldAPIName = 'AccountNumber';
// Call the method and expect exception
try {
List<BK_FilterCollectionByField.Result> results = BK_FilterCollectionByField.filterRecordsByField(
new List<BK_FilterCollectionByField.Request>{request}
);
System.assert(false, 'Expected an exception due to empty filterValues');
} catch (Exception ex) {
System.assert(ex instanceof BK_FilterCollectionByField.FilterException, 'Expected a FilterException');
System.assertEquals('Filter values are required but empty.', ex.getMessage());
}
}
@isTest
static void testFilterRecordsByField_ExceptionOnEmptyFieldAPIName() {
// Create sample accounts
Account acc1 = new Account(Name = 'Test Account 1', AccountNumber = '123');
insert acc1;
// Prepare request with empty fieldAPIName
BK_FilterCollectionByField.Request request = new BK_FilterCollectionByField.Request();
request.inputRecords = new List<SObject>{acc1};
request.filterValues = new List<String>{'123'};
request.fieldAPIName = '';
// Call the method and expect exception
try {
List<BK_FilterCollectionByField.Result> results = BK_FilterCollectionByField.filterRecordsByField(
new List<BK_FilterCollectionByField.Request>{request}
);
System.assert(false, 'Expected an exception due to empty fieldAPIName');
} catch (Exception ex) {
System.assert(ex instanceof BK_FilterCollectionByField.FilterException, 'Expected a FilterException');
System.assertEquals('Field to filter by is required but empty.', ex.getMessage());
}
}
}
Comments