Merge pull request #49 from wimvelzeboer/feature/ChildMapMethodForDomain
Refactor of getChildIdsById and getGrandParentIdById of fflib_SObject2
This commit is contained in:
@@ -29,6 +29,10 @@
|
|||||||
*/
|
*/
|
||||||
public interface fflib_ISObjects2 extends fflib_ISObjects
|
public interface fflib_ISObjects2 extends fflib_ISObjects
|
||||||
{
|
{
|
||||||
|
Map<Id, Set<Id>> getChildIdsById(Map<Schema.SObjectField, fflib_SObjects2> domainsByRelationshipField);
|
||||||
|
Map<Id, Id> getParentIdById(Map<Schema.SObjectField, fflib_SObjects2> domainsByRelationshipField);
|
||||||
|
|
||||||
|
// DEPRECATED METHODS
|
||||||
Map<Id, Id> getGrandParentIdById(List<fflib_ISObjects2> relatedDomains);
|
Map<Id, Id> getGrandParentIdById(List<fflib_ISObjects2> relatedDomains);
|
||||||
Map<Id, Set<Id>> getChildIdsById(List<fflib_SObjects2> relatedDomains);
|
Map<Id, Set<Id>> getChildIdsById(List<fflib_SObjects2> relatedDomains);
|
||||||
}
|
}
|
||||||
@@ -81,33 +81,57 @@ public virtual class fflib_SObjects2
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a map between the record Ids of this domain to the last given grandparent domain.
|
* Creates a map between the record Ids of this domain to the last given grandparent domain.
|
||||||
* This method is using getRelatedFieldByDomainType to determine which SObjectField
|
|
||||||
* is related to the given parent domain
|
|
||||||
*
|
*
|
||||||
* @param relatedDomains A List of domains in hierarchical order from first parent to grandparent
|
* @param domainsByRelationshipField A Map of domains and the in hierarchical order from first parent to grandparent
|
||||||
*
|
*
|
||||||
* @return Returns a map with KEY: The Ids of the records in this domain,
|
* @return Returns a map with KEY: The Ids of the records in this domain,
|
||||||
* to the VALUE: The Id of the last grandparent record listed in the relatedDomains,
|
* to the VALUE: The Id of the last grandparent record listed in the relatedDomains,
|
||||||
* null if no grandparent exists.
|
* null if no grandparent exists.
|
||||||
*
|
*
|
||||||
* @see getRelatedFieldByDomainType
|
|
||||||
*
|
|
||||||
* @example
|
* @example
|
||||||
* IInvoiceLines invoiceLineDomain = InvoiceLines.newInstance(invoiceLineRecords);
|
* ICases casesDomain = Cases.newInstance(caseRecords);
|
||||||
* IInvoices invoicesDomain = Invoices.newInstance(invoiceRecords);
|
* IContacts contactsDomain = Contacts.newInstance(contactRecords);
|
||||||
* IAccount accountDomain = Accounts.newInstance(accountRecords);
|
* IAccount accountDomain = Accounts.newInstance(accountRecords);
|
||||||
*
|
*
|
||||||
* // A map with key - InvoiceLine.Id to value - Account.Id
|
* // A map with key - Case.Id to value - Account.Id
|
||||||
* Map<Id, Id> accountIdByInvoiceLineId =
|
* Map<Id, Id> accountIdByCaseId =
|
||||||
* invoiceLineDomain.getGrandParentIdById(
|
* casesDomain.getParentIdById(
|
||||||
* new List<fflib_SObjects2>
|
* new Map<Schema.SObjectField, fflib_SObjects2>
|
||||||
* {
|
* {
|
||||||
* invoicesDomain,
|
* Schema.Case.ContactId => contactDomain,
|
||||||
* accountDomain
|
* Schema.Contact.AccountId => accountDomain
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
|
public virtual Map<Id, Id> getParentIdById(Map<Schema.SObjectField, fflib_SObjects2> domainsByRelationshipField)
|
||||||
|
{
|
||||||
|
// Takes the highest related domain from the domainsByRelationshipField
|
||||||
|
Schema.SObjectField relationshipField =
|
||||||
|
new List<Schema.SObjectField>(domainsByRelationshipField.keySet())
|
||||||
|
.get(0);
|
||||||
|
fflib_SObjects2 relatedDomain = domainsByRelationshipField.remove(relationshipField);
|
||||||
|
|
||||||
|
// Extract the Id values of the related SObjectType
|
||||||
|
Map<Id, Id> result = getIdFieldByIdField(
|
||||||
|
relationshipField,
|
||||||
|
getSObjectType().getDescribe().fields.getMap().get('Id'));
|
||||||
|
|
||||||
|
// Check if we need to resolve another parent relation, if not return the results
|
||||||
|
if (domainsByRelationshipField.isEmpty()) return result;
|
||||||
|
|
||||||
|
// Fetch the Ids of the related SObjectType
|
||||||
|
Map<Id, Id> parentIdByChildId = relatedDomain.getParentIdById(domainsByRelationshipField);
|
||||||
|
|
||||||
|
// Replace the maps value (ParentId) with the grand parent Id
|
||||||
|
return fflib_ArrayUtils.replaceValue(result, parentIdByChildId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** DEPRECATED **/
|
||||||
public virtual Map<Id, Id> getGrandParentIdById(List<fflib_ISObjects2> relatedDomains)
|
public virtual Map<Id, Id> getGrandParentIdById(List<fflib_ISObjects2> relatedDomains)
|
||||||
{
|
{
|
||||||
|
System.debug(LoggingLevel.WARN,
|
||||||
|
'The \'getGrandParentIdById(List<fflib_ISObjects2> relatedDomains)\' method is deprecated,' +
|
||||||
|
'please refactor to \'getParentIdById(Map<Schema.SObjectField, fflib_ISObjects2> relatedDomains)\'');
|
||||||
|
|
||||||
fflib_ISObjects2 relatedDomain = relatedDomains.remove(0);
|
fflib_ISObjects2 relatedDomain = relatedDomains.remove(0);
|
||||||
SObjectType relatedDomainType = relatedDomain.getSObjectType();
|
SObjectType relatedDomainType = relatedDomain.getSObjectType();
|
||||||
Map<SObjectType, SObjectField> relatedFieldByDomainType = getRelatedFieldByDomainType();
|
Map<SObjectType, SObjectField> relatedFieldByDomainType = getRelatedFieldByDomainType();
|
||||||
@@ -136,30 +160,55 @@ public virtual class fflib_SObjects2
|
|||||||
* This method is using getRelatedFieldByDomainType to determine which SObjectField
|
* This method is using getRelatedFieldByDomainType to determine which SObjectField
|
||||||
* is related to the given parent domain
|
* is related to the given parent domain
|
||||||
*
|
*
|
||||||
* @param relatedDomains A List of domains in hierarchical order from first child to grandchild
|
* @param domainsByRelationshipField A Map of domains in hierarchical order from first child to grandchild
|
||||||
*
|
*
|
||||||
* @return Returns a map with KEY: The Ids of the records in this domain,
|
* @return Returns a map with KEY: The Ids of the records in this domain,
|
||||||
* to the VALUE: The record Ids of the lowest child related record listed in the relatedDomains,
|
* to the VALUE: The record Ids of the lowest child related record listed in the relatedDomains,
|
||||||
* null if no grandchild exists.
|
* null if no grandchild exists.
|
||||||
*
|
*
|
||||||
* @see getRelatedFieldByDomainType
|
|
||||||
*
|
|
||||||
* @example
|
* @example
|
||||||
* IInvoiceLines invoiceLineDomain = InvoiceLines.newInstance(invoiceLineRecords);
|
* ICases casesDomain = Cases.newInstance(caseRecords);
|
||||||
* IInvoices invoicesDomain = Invoices.newInstance(invoiceRecords);
|
* IContacts contactsDomain = Contacts.newInstance(contactRecords);
|
||||||
* IAccount accountDomain = Accounts.newInstance(accountRecords);
|
* IAccount accountDomain = Accounts.newInstance(accountRecords);
|
||||||
*
|
*
|
||||||
* // A map with key - Account.Id to value - InvoiceLine.Id
|
* // A map with key - Case.Id to value - Account.Id
|
||||||
* Map<Id, Set<Id>> invoiceLineIdsByAccountId =
|
* Map<Id, Set<Id>> caseIdsByAccountId =
|
||||||
* accountDomain.getChildIdsById(
|
* accountsDomain.getChildIdsById(
|
||||||
* new List<fflib_SObjects2>
|
* new Map<Schema.SObjectField, fflib_SObjects2>
|
||||||
* {
|
* {
|
||||||
* invoicesDomain,
|
* Schema.Contact.AccountId => contactsDomain
|
||||||
* invoiceLineDomain
|
* Schema.Case.ContactId => casesDomain,
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
|
public virtual Map<Id, Set<Id>> getChildIdsById(Map<Schema.SObjectField, fflib_SObjects2> domainsByRelationshipField)
|
||||||
|
{
|
||||||
|
// Takes the highest related domain from the domainsByRelationshipField
|
||||||
|
Schema.SObjectField relationshipField =
|
||||||
|
new List<Schema.SObjectField>(domainsByRelationshipField.keySet())
|
||||||
|
.get(0);
|
||||||
|
fflib_SObjects2 relatedDomain = domainsByRelationshipField.remove(relationshipField);
|
||||||
|
|
||||||
|
Map<Id, Set<Id>> result = relatedDomain.getIdFieldsByIdField(
|
||||||
|
relatedDomain.getSObjectType().getDescribe().fields.getMap().get('Id'),
|
||||||
|
relationshipField);
|
||||||
|
|
||||||
|
// Check if we need to resolve another child relation, if not return the results
|
||||||
|
if (domainsByRelationshipField.isEmpty()) return result;
|
||||||
|
|
||||||
|
Map<Id, Set<Id>> childIdsById = relatedDomain.getChildIdsById(domainsByRelationshipField);
|
||||||
|
|
||||||
|
// Replace the maps value (childIds) with the grand child Id
|
||||||
|
return fflib_ArrayUtils.replaceValues(result, childIdsById);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** DEPRECATED **/
|
||||||
public virtual Map<Id, Set<Id>> getChildIdsById(List<fflib_SObjects2> relatedDomains)
|
public virtual Map<Id, Set<Id>> getChildIdsById(List<fflib_SObjects2> relatedDomains)
|
||||||
{
|
{
|
||||||
|
System.debug(LoggingLevel.WARN,
|
||||||
|
'The \'getChildIdsById(List<fflib_ISObjects2> relatedDomains)\' method is deprecated,' +
|
||||||
|
'please refactor to \'getChildIdsById(Map<Schema.SObjectField, fflib_ISObjects2> relatedDomains)\'');
|
||||||
|
|
||||||
|
|
||||||
SObjectType thisDomainType = getSObjectType();
|
SObjectType thisDomainType = getSObjectType();
|
||||||
fflib_SObjects2 relatedDomain = relatedDomains.remove(0);
|
fflib_SObjects2 relatedDomain = relatedDomains.remove(0);
|
||||||
Map<SObjectType, SObjectField> relatedFieldByDomainType = relatedDomain.getRelatedFieldByDomainType();
|
Map<SObjectType, SObjectField> relatedFieldByDomainType = relatedDomain.getRelatedFieldByDomainType();
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ private class fflib_SObjects2Test
|
|||||||
}
|
}
|
||||||
|
|
||||||
@IsTest
|
@IsTest
|
||||||
static void itShouldReturnTheRelatedChildDomainId()
|
static void itShouldReturnTheRelatedChildDomainId_deprecated()
|
||||||
{
|
{
|
||||||
// GIVEN a case A & Z related to contact A related to Account,
|
// GIVEN a case A & Z related to contact A related to Account,
|
||||||
Id caseIdA = fflib_IDGenerator.generate(Schema.Case.SObjectType);
|
Id caseIdA = fflib_IDGenerator.generate(Schema.Case.SObjectType);
|
||||||
@@ -161,6 +161,47 @@ private class fflib_SObjects2Test
|
|||||||
System.Assert.areEqual(2, result.get(accountId).size(), 'Incorrect amount of related cases to the account');
|
System.Assert.areEqual(2, result.get(accountId).size(), 'Incorrect amount of related cases to the account');
|
||||||
System.Assert.isTrue(result.get(accountId).containsAll(new Set<Id>{ caseIdA, caseIdZ }));
|
System.Assert.isTrue(result.get(accountId).containsAll(new Set<Id>{ caseIdA, caseIdZ }));
|
||||||
}
|
}
|
||||||
|
@IsTest
|
||||||
|
static void itShouldReturnTheRelatedChildDomainId()
|
||||||
|
{
|
||||||
|
// GIVEN a case A & Z related to contact A related to Account,
|
||||||
|
Id caseIdA = fflib_IDGenerator.generate(Schema.Case.SObjectType);
|
||||||
|
Id caseIdZ = fflib_IDGenerator.generate(Schema.Case.SObjectType);
|
||||||
|
Id caseIdB = fflib_IDGenerator.generate(Schema.Case.SObjectType);
|
||||||
|
Id caseIdC = fflib_IDGenerator.generate(Schema.Case.SObjectType);
|
||||||
|
Id contactIdA = fflib_IDGenerator.generate(Schema.Contact.SObjectType);
|
||||||
|
Id contactIdB = fflib_IDGenerator.generate(Schema.Contact.SObjectType);
|
||||||
|
Id accountId = fflib_IDGenerator.generate(Schema.Account.SObjectType);
|
||||||
|
Account accountRecord = new Account(Id = accountId);
|
||||||
|
Contact contactRecordA = new Contact(Id = contactIdA, AccountId = accountId);
|
||||||
|
Contact contactRecordB = new Contact(Id = contactIdB);
|
||||||
|
Case caseRecordA = new Case(Id = caseIdA, ContactId = contactIdA);
|
||||||
|
Case caseRecordZ = new Case(Id = caseIdZ, ContactId = contactIdA);
|
||||||
|
Case caseRecordB = new Case(Id = caseIdB, ContactId = contactIdB);
|
||||||
|
Case caseRecordC = new Case(Id = caseIdC);
|
||||||
|
|
||||||
|
DomainAccounts accountDomain = new DomainAccounts(new List<Account> {accountRecord});
|
||||||
|
DomainContacts contactDomain = new DomainContacts(new List<Contact> {contactRecordA, contactRecordB});
|
||||||
|
DomainCases caseDomain = new DomainCases(new List<Case> {caseRecordA, caseRecordB, caseRecordC, caseRecordZ});
|
||||||
|
|
||||||
|
// WHEN we request the relation between Case and Account
|
||||||
|
System.Test.startTest();
|
||||||
|
Map<Id, Set<Id>> result = accountDomain.getChildIdsById(
|
||||||
|
new Map<Schema.SObjectField, fflib_SObjects2>
|
||||||
|
{
|
||||||
|
Contact.AccountId => contactDomain,
|
||||||
|
Case.ContactId => caseDomain
|
||||||
|
}
|
||||||
|
);
|
||||||
|
System.Test.stopTest();
|
||||||
|
System.debug('result: ' + JSON.serializePretty(result));
|
||||||
|
|
||||||
|
// THEN it should return the AccountId By CaseId
|
||||||
|
System.Assert.areEqual(1, result.size(), 'Expected one account');
|
||||||
|
System.Assert.isTrue(result.containsKey(accountId), 'Account Id should be the main key');
|
||||||
|
System.Assert.areEqual(2, result.get(accountId).size(), 'Incorrect amount of related cases to the account');
|
||||||
|
System.Assert.isTrue(result.get(accountId).containsAll(new Set<Id>{ caseIdA, caseIdZ }));
|
||||||
|
}
|
||||||
|
|
||||||
@IsTest
|
@IsTest
|
||||||
static void itShouldReturnTheRelatedParentDomainId()
|
static void itShouldReturnTheRelatedParentDomainId()
|
||||||
@@ -186,6 +227,52 @@ private class fflib_SObjects2Test
|
|||||||
DomainContacts contactDomain = new DomainContacts(new List<Contact> {contactRecordA, contactRecordB});
|
DomainContacts contactDomain = new DomainContacts(new List<Contact> {contactRecordA, contactRecordB});
|
||||||
DomainCases caseDomain = new DomainCases(new List<Case> {caseRecordA, caseRecordB, caseRecordC});
|
DomainCases caseDomain = new DomainCases(new List<Case> {caseRecordA, caseRecordB, caseRecordC});
|
||||||
|
|
||||||
|
// WHEN we request the relation between Case and Account
|
||||||
|
System.Test.startTest();
|
||||||
|
Map<Id, Id> result = caseDomain.getParentIdById(
|
||||||
|
new Map<Schema.SObjectField, fflib_SObjects2>
|
||||||
|
{
|
||||||
|
Schema.Case.ContactId => contactDomain,
|
||||||
|
Schema.Contact.AccountId => accountDomain
|
||||||
|
}
|
||||||
|
);
|
||||||
|
System.Test.stopTest();
|
||||||
|
|
||||||
|
// THEN it should return the AccountId By CaseId
|
||||||
|
System.Assert.areEqual(3, result.size(), 'Expected one related account to the case');
|
||||||
|
System.Assert.isTrue(result.containsKey(caseIdA));
|
||||||
|
System.Assert.isTrue(result.containsKey(caseIdB));
|
||||||
|
System.Assert.isTrue(result.containsKey(caseIdC));
|
||||||
|
System.Assert.areEqual(accountId, result.get(caseIdA), 'Account Id should be related to the Case Id A');
|
||||||
|
System.Assert.isNull(result.get(caseIdB), 'Case Id B should have no related Account Id');
|
||||||
|
System.Assert.isNull(result.get(caseIdC), 'Case Id B should have no related Account Id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unit test for the deprecated method **/
|
||||||
|
@IsTest
|
||||||
|
static void itShouldReturnTheRelatedParentDomainId_deprecated()
|
||||||
|
{
|
||||||
|
// GIVEN a case related to contact related to Account ,
|
||||||
|
// a case record related to contact but not to Account,
|
||||||
|
// and a case record related to nothing.
|
||||||
|
// All encapsulated in domains.
|
||||||
|
Id caseIdA = fflib_IDGenerator.generate(Schema.Case.SObjectType);
|
||||||
|
Id caseIdB = fflib_IDGenerator.generate(Schema.Case.SObjectType);
|
||||||
|
Id caseIdC = fflib_IDGenerator.generate(Schema.Case.SObjectType);
|
||||||
|
Id contactIdA = fflib_IDGenerator.generate(Schema.Contact.SObjectType);
|
||||||
|
Id contactIdB = fflib_IDGenerator.generate(Schema.Contact.SObjectType);
|
||||||
|
Id accountId = fflib_IDGenerator.generate(Schema.Account.SObjectType);
|
||||||
|
Account accountRecord = new Account(Id = accountId);
|
||||||
|
Contact contactRecordA = new Contact(Id = contactIdA, AccountId = accountId);
|
||||||
|
Contact contactRecordB = new Contact(Id = contactIdB);
|
||||||
|
Case caseRecordA = new Case(Id = caseIdA, ContactId = contactIdA);
|
||||||
|
Case caseRecordB = new Case(Id = caseIdB, ContactId = contactIdB);
|
||||||
|
Case caseRecordC = new Case(Id = caseIdC);
|
||||||
|
|
||||||
|
DomainAccounts accountDomain = new DomainAccounts(new List<Account> {accountRecord});
|
||||||
|
DomainContacts contactDomain = new DomainContacts(new List<Contact> {contactRecordA, contactRecordB});
|
||||||
|
DomainCases caseDomain = new DomainCases(new List<Case> {caseRecordA, caseRecordB, caseRecordC});
|
||||||
|
|
||||||
// WHEN we request the relation between Case and Account
|
// WHEN we request the relation between Case and Account
|
||||||
System.Test.startTest();
|
System.Test.startTest();
|
||||||
Map<Id, Id> result = caseDomain.getGrandParentIdById(
|
Map<Id, Id> result = caseDomain.getGrandParentIdById(
|
||||||
|
|||||||
Reference in New Issue
Block a user