Created
August 29, 2023 02:25
-
-
Save FishOfPrey/e35bcd2f86ac977f5103f8a6d9f9f5de to your computer and use it in GitHub Desktop.
An Apex Comparator implementation for sorting by sObject fields.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class sObjectComparator implements Comparator<sObject> { | |
// Asc and Desc are reserved keywords in Apex! | |
public enum SortOrder { Ascend, Descend} | |
private Schema.sObjectField sortField; | |
private DescribeFieldResult describeResult; | |
public SortOrder order { | |
get; | |
set { | |
order = value; | |
} | |
} | |
public sObjectComparator(Schema.sObjectField compareField) { | |
sortField = compareField; | |
describeResult = sortField.getDescribe(); | |
order = SortOrder.Ascend; | |
} | |
public integer compare(sObject s1, sObject s2) { | |
integer compareResult; | |
// Handle null objects before null field values | |
if(s1 == null && s2 == null) { | |
compareResult = 0; | |
} else if (s1 == null) { | |
compareResult = -1; | |
} else if (s2 == null) { | |
compareResult = 1; | |
} else { | |
object s1FieldValue = s1?.get(sortField); | |
object s2FieldValue = s2?.get(sortField); | |
// Handle null field values then actual value compares | |
if(s1FieldValue == null && s2FieldValue == null) { | |
compareResult = 0; | |
} else if (s1FieldValue == null) { | |
compareResult = -1; | |
} else if (s2FieldValue == null) { | |
compareResult = 1; | |
} else { | |
compareResult = compareFieldTypes(s1FieldValue, s2FieldValue); | |
} | |
} | |
if(order == SortOrder.Descend) { | |
return compareResult * -1; | |
} | |
return compareResult; | |
} | |
private integer compareFieldTypes(object s1FieldValue, object s2FieldValue) { | |
switch on (describeResult.getType()) { | |
when String { | |
string s1 = (string)s1FieldValue; | |
string s2 = (string)s2FieldValue; | |
return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0; | |
} | |
when DateTime { | |
DateTime s1 = (DateTime)s1FieldValue; | |
DateTime s2 = (DateTime)s2FieldValue; | |
return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0; | |
} | |
when Date { | |
Date s1 = (Date)s1FieldValue; | |
Date s2 = (Date)s2FieldValue; | |
return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0; | |
} | |
when Integer { | |
Integer s1 = (Integer)s1FieldValue; | |
Integer s2 = (Integer)s2FieldValue; | |
return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0; | |
} | |
when Id { | |
Id s1 = (Id)s1FieldValue; | |
Id s2 = (Id)s2FieldValue; | |
return (s1 < s2) ? -1 : (s1 > s2) ? 1 : 0; | |
} | |
// TODO: Expand out for additional DisplayType enum values | |
// https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_enum_Schema_DisplayType.htm | |
when else { | |
Assert.fail('Unable to compare field type: ' + describeResult.getType()); | |
} | |
} | |
return 0; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@IsTest | |
public class sObjectComparator_Test { | |
@IsTest | |
static void AccountSorting() { | |
List<Account> toSort = new List<Account>(); | |
toSort.add(new Account(Name='Test1', NumberOfEmployees=5)); | |
toSort.add(new Account(Name='Test3', NumberOfEmployees=2)); | |
toSort.add(new Account(Name='Test2')); | |
toSort.add(null); | |
sObjectComparator nameComp = new sObjectComparator(Account.Name); | |
toSort.sort(nameComp); | |
System.debug(toSort); | |
Assert.isNull(toSort.get(0)); | |
Assert.areEqual('Test1', toSort.get(1).Name); | |
Assert.areEqual('Test2', toSort.get(2).Name); | |
Assert.areEqual('Test3', toSort.get(3).Name); | |
sObjectComparator numEmpCom = new sObjectComparator(Account.NumberOfEmployees); | |
toSort.sort(numEmpCom); | |
Assert.isNull(toSort.get(0)); | |
Assert.areEqual('Test2', toSort.get(1).Name); | |
Assert.areEqual('Test3', toSort.get(2).Name); | |
Assert.areEqual('Test1', toSort.get(3).Name); | |
numEmpCom.order = sObjectComparator.SortOrder.Descend; | |
toSort.sort(numEmpCom); | |
Assert.areEqual('Test1', toSort.get(0).Name); | |
Assert.areEqual('Test3', toSort.get(1).Name); | |
Assert.areEqual('Test2', toSort.get(2).Name); | |
Assert.isNull(toSort.get(3)); | |
} | |
@IsTest | |
static void ContactSorting() { | |
List<Contact> toSort = new List<Contact>(); | |
toSort.add(new Contact(LastName='Test1', Birthdate=DateTime.now().date()) ); | |
toSort.add(new Contact(LastName='Test3')); | |
toSort.add(new Contact(LastName='Test2', Birthdate=DateTime.now().addDays(-10).date())); | |
toSort.add(null); | |
sObjectComparator nameComp = new sObjectComparator(Contact.LastName); | |
toSort.sort(nameComp); | |
System.debug(toSort); | |
Assert.isNull(toSort.get(0)); | |
Assert.areEqual('Test1', toSort.get(1).LastName); | |
Assert.areEqual('Test2', toSort.get(2).LastName); | |
Assert.areEqual('Test3', toSort.get(3).LastName); | |
sObjectComparator numEmpCom = new sObjectComparator(Contact.BirthDate); | |
toSort.sort(numEmpCom); | |
Assert.isNull(toSort.get(0)); | |
Assert.areEqual('Test3', toSort.get(1).LastName); | |
Assert.areEqual('Test2', toSort.get(2).LastName); | |
Assert.areEqual('Test1', toSort.get(3).LastName); | |
numEmpCom.order = sObjectComparator.SortOrder.Descend; | |
toSort.sort(numEmpCom); | |
Assert.areEqual('Test1', toSort.get(0).LastName); | |
Assert.areEqual('Test2', toSort.get(1).LastName); | |
Assert.areEqual('Test3', toSort.get(2).LastName); | |
Assert.isNull(toSort.get(3)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment