Skip to content

Instantly share code, notes, and snippets.

@FishOfPrey
Created August 29, 2023 02:25
Show Gist options
  • Save FishOfPrey/e35bcd2f86ac977f5103f8a6d9f9f5de to your computer and use it in GitHub Desktop.
Save FishOfPrey/e35bcd2f86ac977f5103f8a6d9f9f5de to your computer and use it in GitHub Desktop.
An Apex Comparator implementation for sorting by sObject fields.
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;
}
}
@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