I'm doing some work with the ESAPI Library. In particular, when updating records it is used to enforce FLS with the following method:
global SFDCAccessControlResults.UpdateResults updateAsUser(
Map<ID, sObject> objMap,
List<String> fieldsToUpdate
) {}
Example call:
try {
List<Contact> contactsToUpdate = [select LastName,id from Contact];
// Make some changes to contacts LastName field...
SFDCAccessControlResults.UpdateResults res =
ESAPI.accessController().updateAsUser(
new Map<ID, Contact>(contactsToUpdate),
new List<String>{'LastName'}
);
contactsToUpdate = res.getUpdatedObjects();
} catch (SFDCAccessControlException e) {
// error handling
}
Note the need to explicitly convert the input list contactsToUpdate
into a Map<Id, Contact>
. I find this a bit unwieldy and would rather just pass in the existing list of contacts and let the underlying method sort out the Map conversion.
As a quick first attempt I added another method signature to SFDCAccessController
that did just that:
global SFDCAccessControlResults.UpdateResults updateAsUser(List<sObject> objs) {
Map<ID, sObject> objMap = new Map<ID, sObject>(objs);
// Note: This is only going to build up the field set for the first sObject in the collection.
// If different sObjects have different fields then they will be ignored.
Set<String> keySet = objs.get(0).getPopulatedFieldsAsMap().keySet();
keySet.remove('Id');
List<String> fieldsToUpdate = new List<string>(keySet);
Schema.SObjectType objType = objs.get(0).getSObjectType();
return getACImpl().updateAsUser(objMap, fieldsToUpdate, objType);
}
However, this fails with the message:
System.TypeException: Operation only applies to concrete SObject value map types: SObject
This makes sense as a generic SObject could be any number of actual concrete sObject types.
That leaves the question - How can I create a Map from the ID to the concrete type of the sObjects?