Created
August 22, 2017 15:38
-
-
Save NikiforovAll/ba86d1547f9ff51383abaf6eac90ba73 to your computer and use it in GitHub Desktop.
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 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