Last active
April 8, 2024 09:27
-
-
Save jamessimone/fd8f24fd1cbe76f18983cb0f20a2d92e to your computer and use it in GitHub Desktop.
Helper methods for working with collections in Apex
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 CollectionUtils { | |
public static List<Id> convertToIdList(List<SObject> sObjectList) { | |
return new List<Id>(convertToIdSet(sObjectList)); | |
} | |
public static List<Id> convertToIdList(List<SObject> sObjectList, SObjectField field) { | |
return convertToIdList(sObjectList, string.valueOf(field)); | |
} | |
public static List<Id> convertToIdList(List<SObject> sObjectList, string field) { | |
List<Id> returnList = new List<Id>(); | |
for(SObject o : sObjectList) { | |
returnList.add((Id) o.get(field)); | |
} | |
return returnList; | |
} | |
public static Set<Id> convertToIdSet(List<SObject> sObjectList, SObjectField field) { | |
return new Set<Id>(convertToIdList(sObjectList, string.valueOf(field))); | |
} | |
public static Set<Id> convertToIdSet(List<SObject> sObjectList, string field) { | |
return new Set<Id>(convertToIdList(sObjectList, field)); | |
} | |
public static Set<Id> convertToIdSet(List<SObject> sObjectList) { | |
return new Set<Id>(convertToMap(sObjectList).keySet()); | |
} | |
public static Set<String> convertToStringSet(List<SObject> sObjectList, SObjectField filterField) { | |
Set<String> strings = new Set<String>(); | |
for(SObject record : sObjectList) { | |
strings.add((String) record.get(filterField)); | |
} | |
return strings; | |
} | |
public static Map<String, SObject> convertToStringKeyMap(List<SObject> sObjectList, SObjectField filterField) { | |
Map<String, SObject> stringMap = new Map<String, SObject>(); | |
for(SObject record : sObjectList) { | |
stringMap.put((String) record.get(filterField), record); | |
} | |
return stringMap; | |
} | |
public static Map<Id,SObject> convertToMap(List<SObject> sObjectList) { | |
return sObjectList.isEmpty() ? new Map<Id,SObject>() : new Map<Id,SObject>(sObjectList); | |
} | |
public static Map<Id, SObject> convertToMap(List<SObject> sObjectList, SObjectField field) { | |
return convertToMap(sObjectList, string.valueOf(field)); | |
} | |
public static Map<Id, SObject> convertToMap(List<SObject> sObjectList, String fieldName) { | |
Map<Id,SObject> mapping = new Map<Id,SObject>(); | |
if(sObjectList.isEmpty() == false) { | |
SObjectType sObjectType = sObjectList[0].getSObjectType(); | |
if(sObjectType.getdescribe().fields.getmap().containsKey(fieldName)) { | |
//Validation to make sure fieldName is an Id or Lookup | |
Set<String> acceptedFieldTypes = new Set<String>{'STRING','ID','REFERENCE', 'DATACATEGORYGROUPREFERENCE'}; | |
String sObjectField = String.valueOf(sObjectType) + '.' + fieldName; | |
if(!acceptedFieldTypes.contains(DescribeUtils.getFieldType(sObjectField))) { | |
throw new Exceptions.DescribeException('Field should be of type Id'); | |
} else { | |
for(SObject sObj : sObjectList) { | |
if(sObj.get(fieldName) == null) continue; | |
mapping.put((Id)sObj.get(fieldName), sObj); | |
} | |
} | |
} | |
} | |
return mapping; | |
} | |
public static Map<Id, Object> convertToMap(List<Object> objects, String keyFieldName) { | |
// avoid costly serialization/de-serialization if it's anything other than a generic object | |
if(objects instanceof List<SObject>) { | |
return convertToMap((List<SObject>) objects, keyFieldName); | |
} | |
Map<Id, Object> keyFieldToObjects = new Map<Id, Object>(); | |
for(Object obj : objects) { | |
Map<String, Object> deserializedObj = (Map<String, Object>)JSON.deserializeUntyped(JSON.serialize(obj)); | |
if(deserializedObj.containsKey(keyFieldName)) { | |
Id fieldVal = (Id)deserializedObj.get(keyFieldName); | |
if(String.isNotBlank(fieldVal)) { | |
keyFieldToObjects.put(fieldVal, obj); | |
} | |
} | |
} | |
return keyFieldToObjects; | |
} | |
public static Map<Id, Id> convertToIdMap(List<SObject> sObjectList, SObjectField idKey, SObjectField idValue) { | |
Map<Id, Id> resultMap = new Map<Id, Id>(); | |
for(SObject sObj : sObjectList) { | |
if(sObj.get(idKey) == null) continue; | |
resultMap.put((Id)sObj.get(idKey), (Id)sObj.get(idValue)); | |
} | |
return resultMap; | |
} | |
public static Map<String, List<SObject>> convertToListMap(List<SObject> sObjectList, SObjectField idKey) { | |
return convertToListMap(sObjectList, idKey.getDescribe().getName(), null); | |
} | |
public static Map<String, List<SObject>> convertToListMap(List<SObject> sObjectList, String idKey) { | |
return convertToListMap(sObjectList, idKey, null); | |
} | |
public static Map<String, List<SObject>> convertToListMap(List<SObject> sObjectList, SObjectField idKey, CollectionEvaluator eval) { | |
return convertToListMap(sObjectList, idKey.getDescribe().getName(), eval); | |
} | |
public static Map<String, List<SObject>> convertToListMap(List<SObject> sObjectList, String idKey, CollectionEvaluator eval) { | |
Map<String, List<SObject>> keyToListValues = new Map<String, List<SObject>>(); | |
for(SObject sObj : sObjectList) { | |
String key = (String)sObj.get(idKey); | |
if(String.isBlank(key) || eval != null && eval.matchesCriteria(sObj) == false) { continue; } | |
else if(keyToListValues.containsKey(key)) { | |
keyToListValues.get(key).add(sObj); | |
} else { | |
keyToListValues.put(key, new List<SObject>{ sObj }); | |
} | |
} | |
return keyToListValues; | |
} | |
public abstract class CollectionEvaluator { | |
public abstract Boolean matchesCriteria(SObject obj); | |
} | |
public static Set<String> removeStringsFromStringSet(Set<String> source, Set<String> eliminate) { | |
Set<String> excludedSet = new Set<String>(source); | |
excludedSet.removeAll(eliminate); | |
return excludedSet; | |
} | |
public static Map<String, SObject> convertToStringMapLowercase(List<SObject> sObjectList, String fieldName) { | |
Map<String,SObject> mapping = new Map<String,SObject>(); | |
for(SObject sObj : sObjectList) { | |
if(sObj.get(fieldName) != null) { | |
mapping.put(((String)sObj.get(fieldName)).toLowerCase(), sObj); | |
} | |
} | |
return mapping; | |
} | |
public static Boolean isNullOrEmpty(List<Object> listOfThings) { | |
return listOfThings == null || listOfThings.isEmpty(); | |
} | |
public static Boolean isNullOrEmpty(Map<String,String> mapOfThings) { | |
return mapOfThings == null || mapOfThings.isEmpty(); | |
} | |
public static SObject getFirstOrDefault(List<SObject> listOfThings) { | |
return listOfThings.isEmpty() ? null : listOfThings[0]; | |
} | |
public static List<SObject> removeAll(List<SObject> records, Set<Id> idMatches, SObjectField matchField) { | |
List<SObject> reducedList = new List<SObject>(); | |
for(SObject record : records) { | |
if(idMatches.contains((Id)record.get(matchField)) == false) { | |
reducedList.add(record); | |
} | |
} | |
return reducedList; | |
} | |
public static List<SObject> getRecordsMatchingType(List<SObject> records, Schema.SObjectType sObjectType) { | |
List<SObject> matchingRecords = DescribeUtils.createSObjectList(sObjectType); | |
for (SObject record : records) { | |
if(record.getSObjectType() == sObjectType) { | |
matchingRecords.add(record); | |
} | |
} | |
return matchingRecords; | |
} | |
public static SObject getFirstOrDefaultOfType(List<SObject> records, Schema.SObjectType sObjectType){ | |
return getFirstOrDefault(getRecordsMatchingType(records, sObjectType)); | |
} | |
private static string fieldName(SObjectField fieldObject) { | |
return fieldObject.getDescribe().getName(); | |
} | |
private static Set<String> fieldNames(List<SObjectField> fieldObjectList) { | |
Set<String> fieldStrings = new Set<String>(); | |
for(SObjectField fieldObject : fieldObjectList) { | |
fieldStrings.add(fieldName(fieldObject)); | |
} | |
return fieldStrings; | |
} | |
public static Set<String> getFieldNamesFromFieldSet(FieldSet fs) { | |
Set<String> fields = new Set<String>(); | |
for(FieldSetMember member : fs.getFields()) { | |
fields.add(member.getFieldPath().toLowerCase()); | |
} | |
return fields; | |
} | |
public static Set<String> getFieldLabelsFromFieldSet(FieldSet fs) { | |
Set<String> fields = new Set<String>(); | |
for(FieldSetMember member : fs.getFields()) { | |
fields.add(member.getLabel()); | |
} | |
return fields; | |
} | |
public static List<SObject> getUpdatedRecordsWithChangedField(List<SObject> records, Map<Id, SObject> oldRecordMap, SObjectField field) { | |
return getUpdatedRecordsWithChangedFields(records, oldRecordMap, new Set<String> { fieldName(field) }); | |
} | |
public static List<SObject> getUpdatedRecordsWithChangedField(List<SObject> records, Map<Id, SObject> oldRecordMap, String field) { | |
return getUpdatedRecordsWithChangedFields(records, oldRecordMap, new Set<String> { field }); | |
} | |
public static List<SObject> getUpdatedRecordsWithChangedFields(List<SObject> records, Map<Id, SObject> oldRecordMap, List<SObjectField> fields) { | |
return getUpdatedRecordsWithChangedFields(records, oldRecordMap, fieldNames(fields)); | |
} | |
public static List<SObject> getUpdatedRecordsWithChangedFields(List<SObject> records, Map<Id, SObject> oldRecordMap, Set<String> fields) { | |
List<SObject> updatedRecords = new List<SObject>(); | |
List<String> fieldsList = new List<String>(fields); | |
for(SObject record : records) { | |
SObject oldRecord = oldRecordMap.get(record.Id); | |
if(hasChangeBasedOnFields(record, oldRecord, fieldsList)) { | |
updatedRecords.add(record); | |
} | |
} | |
return updatedRecords; | |
} | |
public static Boolean hasChangeBasedOnFields(SObject current, SObject old, List<String> fields) { | |
Boolean hasChange = false; | |
Integer index = 0; | |
while(index < fields.size() && !hasChange) { | |
String fieldName = fields[index]; | |
if(current.get(fieldName) != old.get(fieldName)) { | |
hasChange = true; | |
} | |
index++; | |
} | |
return hasChange; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated with generic
Map<Id, Object>
convertToMap method