Skip to content

Instantly share code, notes, and snippets.

@NikiforovAll
Created August 22, 2017 15:38
Show Gist options
  • Save NikiforovAll/ba86d1547f9ff51383abaf6eac90ba73 to your computer and use it in GitHub Desktop.
Save NikiforovAll/ba86d1547f9ff51383abaf6eac90ba73 to your computer and use it in GitHub Desktop.
public class ObjectHierarchyManager {
//TBD: move custom settings to wrapper config object
private Map<String, Mapper_Object_Settings__c> dmlSettings;
private String mappingName;
public ObjectHierarchyManager(String mappingName) {
this.mappingName = mappingName;
fetchDmlSettings();
}
public void commitObjects(List<SObjectContainer> sObjectList){
List<Schema.SObjectType> typeList = new List<Schema.SObjectType>();
fflib_SObjectUnitOfWork uow = new fflib_SObjectUnitOfWork(typeList);
Map<String, DmlUnitOfWorkHelper> unitOfWorkHelperRegistry = new Map<String, DmlUnitOfWorkHelper>();
commitObjects(uow, unitOfWorkHelperRegistry, sObjectList, null, null);
uow.commitWork();
}
private void commitObjects(fflib_SObjectUnitOfWork uow, Map<String, DmlUnitOfWorkHelper> unitOfWorkHelperRegistry, List<SObjectContainer> sObjectList, String parentContainer, DmlUnitOfWorkHelper prevWorker){
for(SObjectContainer sobjectContainer_i : sObjectList){
String containerGroupId = sobjectContainer_i.getContainerGroupId().toLowerCase();
Schema.DescribeSObjectResult objectDescribeResult = sobjectContainer_i
.getData()
.getSObjectType()
.getDescribe();
Mapper_Object_Settings__c currentObjectSetting;
// system.debug('containerGroupId ' + containerGroupId);
// system.debug('dmlSettings ' + dmlSettings);
if(String.isNotBlank(containerGroupId) && dmlSettings.containsKey(containerGroupId)){
currentObjectSetting = dmlSettings.get(containerGroupId);
}else{
currentObjectSetting = new Mapper_Object_Settings__c(Name = 'InMemorySetting', Mode__c = 'Insert', Container_Id__c = containerGroupId);
}
// system.debug('currentObjectSetting ' + currentObjectSetting);
DmlUnitOfWorkHelper currentWorker;
if(!unitOfWorkHelperRegistry.containsKey(containerGroupId)){
currentWorker = generateUnitOfWorkHelper(currentObjectSetting, objectDescribeResult.getSobjectType());
unitOfWorkHelperRegistry.put(containerGroupId, currentWorker);
uow.registerWork(currentWorker);
currentWorker.registerPrevWork(prevWorker);
}else{
currentWorker = unitOfWorkHelperRegistry
.get(containerGroupId);
}
Integer numberOfRecordsInUnitOfWork = currentWorker.records.size();
String currentContainerId = containerGroupId + String.valueOf(numberOfRecordsInUnitOfWork);
// system.debug('currentContainerId ' + currentContainerId);
currentWorker.registerRecord(currentContainerId, sobjectContainer_i.getData());
if(String.isNotBlank(parentContainer)){
// system.debug('registerRelationship.parentContainer ' + parentContainer);
currentWorker
.registerRelationship(
currentContainerId,
parentContainer,
getFieldFromName(currentObjectSetting.Parent_Relationship_Name__c, objectDescribeResult.getName())
);
}
if(sobjectContainer_i.getChildContainers() != null && sobjectContainer_i.getChildContainers().size() > 0){
commitObjects(uow, unitOfWorkHelperRegistry, sobjectContainer_i.getChildContainers(), currentContainerId, currentWorker);
}
}
}
private void fetchDmlSettings(){
List<Mapper_Object_Settings__c> settingsList = [
SELECT
Container_Id__c,
External_Id__c,
Mapping_Name__c,
Mode__c,
Parent_Container_Id__c,
Parent_Relationship_Name__c
FROM Mapper_Object_Settings__c
WHERE Mapping_Name__c = :mappingName
];
dmlSettings = new Map<String, Mapper_Object_Settings__c>();
for(Mapper_Object_Settings__c setting_i : settingsList){
if(!dmlSettings.containsKey(setting_i.Container_Id__c)){
dmlSettings.put(setting_i.Container_Id__c.toLowerCase(), setting_i);
}
}
}
private static DmlUnitOfWorkHelper generateUnitOfWorkHelper(Mapper_Object_Settings__c setting, Schema.SObjectType objectType){
String action = setting.Mode__c;
DmlUnitOfWorkHelper helper;
if(action == 'Insert'){
helper = new InsertUnitOfWorkHelper(objectType);
}else if(action == 'Update'){
helper = new UpdateUnitOfWorkHelper(objectType);
}else if(action == 'Upsert'){
helper = new UpsertUnitOfWorkHelper(objectType);
((UpsertUnitOfWorkHelper)helper).setExternalId(getFieldFromName(setting.External_Id__c, objectType.getDescribe().getName()));
}
return helper;
}
private static Schema.SObjectField getFieldFromName(String field, String objectName){
if(String.isBlank(field)){
return null;
}
Schema.DescribeSObjectResult[] dResult = Schema.describeSObjects(new List<String>{objectName});
Map<String,Schema.SObjectField> fieldMap = dResult[0].fields.getMap();
return fieldMap.get(field.toLowerCase());
}
private virtual class DmlUnitOfWorkHelper implements fflib_SObjectUnitOfWork.IDoWork {
public Object Results {get; private set;} //Database.SaveResult[]
public Map<String, SObject> records;
private Map<String, String> recordToParentId;
private Map<String, Schema.SObjectField> recordToParentFieldInfo;
private DmlUnitOfWorkHelper previousWorker;
public DmlUnitOfWorkHelper(){
recordToParentFieldInfo = new Map<String, Schema.SObjectField>();
recordToParentId = new Map<String, String>();
}
// public DmlUnitOfWorkHelper(Schema.SObjectType objectType){
// this();
// String mapType = 'Map<String, ' + objectType + '>';
// records = (Map<String, SObject>)Type.forName(mapType).newInstance();
// }
public void registerRecord(String recordId, SObject record){
records.put(recordId, record);
}
public void registerRelationship(String recordId, String parentId, Schema.SObjectField parentLookupField){
this.recordToParentFieldInfo.put(recordId, parentLookupField);
this.recordToParentId.put(recordId, parentId);
}
public void registerPrevWork(DmlUnitOfWorkHelper prevWorker){
this.previousWorker = prevWorker;
}
public virtual void doWork(){
if(previousWorker == null){
return;
}
system.debug('DmlUnitOfWorkHelper.doWork');
for(String key : Records.keySet()){
String parentId = recordToParentId.get(key);
Schema.SObjectField parentLookupField = recordToParentFieldInfo.get(key);
if(parentLookupField == null){
continue;
}
if(previousWorker.records.containsKey(parentId) && previousWorker.records.get(parentId).Id != null){
// system.debug('parentId ' + parentId);
// system.debug('previousWorker.records.get(parentId).Id ' + previousWorker.records.get(parentId).Id);
this.Records.get(key).put(parentLookupField, previousWorker.records.get(parentId).Id);
}
}
}
}
private class InsertUnitOfWorkHelper extends DmlUnitOfWorkHelper {
public InsertUnitOfWorkHelper(Schema.SObjectType objectType){
String mapType = 'Map<String, ' + objectType + '>';
records = (Map<String, SObject>)Type.forName(mapType).newInstance();
}
public override void doWork(){
if(Records.values().isEmpty()){
return;
}
super.doWork();
Results = Database.insert(records.values(), true);
}
}
private class UpdateUnitOfWorkHelper extends DmlUnitOfWorkHelper {
public UpdateUnitOfWorkHelper(Schema.SObjectType objectType){
String mapType = 'Map<String, ' + objectType + '>';
records = (Map<String, SObject>)Type.forName(mapType).newInstance();
}
public override void doWork(){
if(Records.values().isEmpty()){
return;
}
super.doWork();
Results = Database.update(records.values(), true);
}
}
private class UpsertUnitOfWorkHelper extends DmlUnitOfWorkHelper {
private Schema.SObjectField externalId;
public UpsertUnitOfWorkHelper(Schema.SObjectType objectType){
String mapType = 'Map<String, ' + objectType + '>';
records = (Map<String, SObject>)Type.forName(mapType).newInstance();
}
public void setExternalId(Schema.SObjectField externalId){
this.externalId = externalId;
}
public override void doWork(){
if(Records.values().isEmpty()){
return;
}
super.doWork();
if(externalId == null){
Results = Database.upsert(records.values(), true);
}else{
Results = Database.upsert(records.values(), externalId);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment