@@ -272,9 +272,26 @@ public virtual class fflib_Application
272272 {
273273 protected fflib_Application.SelectorFactory m_selectorFactory ;
274274
275- protected Map <SObjectType , Type > m_sObjectByDomainConstructorType ;
275+ protected Map <Object , Type > constructorTypeByObject ;
276276
277- protected Map <SObjectType , fflib_ISObjectDomain > m_sObjectByMockDomain ;
277+ protected Map <Object , fflib_IDomain > mockDomainByObject ;
278+
279+ /**
280+ * Constructs a Domain factory, using an instance of the Selector Factory
281+ * and a map of Apex classes implementing fflib_ISObjectDomain by SObjectType
282+ * Note this will not check the Apex classes provided actually implement the interfaces
283+ * since this is not possible in the Apex runtime at present
284+ *
285+ * @param selectorFactory , e.g. Application.Selector
286+ * @param constructorTypeByObject Map of Domain classes by ObjectType
287+ **/
288+ public DomainFactory (fflib_Application.SelectorFactory selectorFactory ,
289+ Map <Object , Type > constructorTypeByObject )
290+ {
291+ m_selectorFactory = selectorFactory ;
292+ this .constructorTypeByObject = constructorTypeByObject ;
293+ this .mockDomainByObject = new Map <Object , fflib_IDomain >();
294+ }
278295
279296 /**
280297 * Constructs a Domain factory, using an instance of the Selector Factory
@@ -289,9 +306,9 @@ public virtual class fflib_Application
289306 Map <SObjectType , Type > sObjectByDomainConstructorType )
290307 {
291308 m_selectorFactory = selectorFactory ;
292- m_sObjectByDomainConstructorType = sObjectByDomainConstructorType ;
293- m_sObjectByMockDomain = new Map <SObjectType , fflib_ISObjectDomain >();
294- }
309+ this . constructorTypeByObject = getConstructorTypeByObject ( sObjectByDomainConstructorType ) ;
310+ this . mockDomainByObject = new Map <Object , fflib_IDomain >();
311+ }
295312
296313 /**
297314 * Dynamically constructs an instance of a Domain class for the given record Ids
@@ -301,40 +318,60 @@ public virtual class fflib_Application
301318 * @param recordIds A list of Id's of the same type
302319 * @exception Throws an exception via the Selector Factory if the Ids are not all of the same SObjectType
303320 **/
304- public virtual fflib_ISObjectDomain newInstance (Set <Id > recordIds )
321+ public virtual fflib_IDomain newInstance (Set <Id > recordIds )
305322 {
306323 return newInstance (m_selectorFactory .selectById (recordIds ));
307324
308- }
325+ }
309326
310327 /**
311328 * Dynamically constructs an instance of the Domain class for the given records
312329 * Will return a Mock implementation if one has been provided via setMock
313330 *
314331 * @param records A concrete list (e.g. List<Account> vs List<SObject>) of records
315- * @exception Throws an exception if the SObjectType cannot be determined from the list
332+ * @exception Throws an exception if the SObjectType cannot be determined from the list
316333 * or the constructor for Domain class was not registered for the SObjectType
317334 **/
318- public virtual fflib_ISObjectDomain newInstance (List <SObject > records )
335+ public virtual fflib_IDomain newInstance (List <SObject > records )
319336 {
320337 SObjectType domainSObjectType = records .getSObjectType ();
321338 if (domainSObjectType == null )
322339 throw new DeveloperException (' Unable to determine SObjectType' );
323340
341+ return newInstance ((List <Object >) records , (Object ) domainSObjectType );
342+ }
343+
344+ public virtual fflib_IDomain newInstance (List <Object > objects , Object objectType )
345+ {
324346 // Mock implementation?
325- if ( m_sObjectByMockDomain .containsKey (domainSObjectType ))
326- return m_sObjectByMockDomain .get (domainSObjectType );
347+ if ( mockDomainByObject .containsKey (objectType ))
348+ return mockDomainByObject .get (objectType );
327349
328350 // Determine SObjectType and Apex classes for Domain class
329- Type domainConstructorClass = m_sObjectByDomainConstructorType .get (domainSObjectType );
351+ Type domainConstructorClass = constructorTypeByObject .get (objectType );
330352 if (domainConstructorClass == null )
331- throw new DeveloperException (' Domain constructor class not found for SObjectType ' + domainSObjectType );
353+ throw new DeveloperException (' Domain constructor class not found for SObjectType ' + objectType );
332354
333355 // Construct Domain class passing in the queried records
334- fflib_SObjectDomain .IConstructable domainConstructor =
335- (fflib_SObjectDomain .IConstructable ) domainConstructorClass .newInstance ();
336- return (fflib_ISObjectDomain ) domainConstructor .construct (records );
337- }
356+ Object domainConstructor = domainConstructorClass .newInstance ();
357+
358+ // for backwards compatibility
359+ if (domainConstructor instanceof fflib_SObjectDomain .IConstructable2 )
360+ {
361+ return (fflib_IDomain )
362+ ((fflib_SObjectDomain .IConstructable2 ) domainConstructor )
363+ .construct ((List <SObject >) objects , (SObjectType ) objectType );
364+ }
365+ else if (domainConstructor instanceof fflib_SObjectDomain .IConstructable )
366+ {
367+ return (fflib_IDomain )
368+ ((fflib_SObjectDomain .IConstructable ) domainConstructor )
369+ .construct ((List <SObject >) objects );
370+ }
371+
372+ return ((fflib_IDomainConstructor ) domainConstructor )
373+ .construct (objects );
374+ }
338375
339376 /**
340377 * Dynamically constructs an instance of the Domain class for the given records and SObjectType
@@ -347,30 +384,40 @@ public virtual class fflib_Application
347384 * @remark Will support List<SObject> but all records in the list will be assumed to be of
348385 * the type specified in sObjectType
349386 **/
350- public virtual fflib_ISObjectDomain newInstance (List <SObject > records , SObjectType domainSObjectType )
387+ public virtual fflib_IDomain newInstance (List <SObject > records , SObjectType domainSObjectType )
351388 {
352389 if (domainSObjectType == null )
353390 throw new DeveloperException (' Must specify sObjectType' );
354391
355- // Mock implementation?
356- if (m_sObjectByMockDomain .containsKey (domainSObjectType ))
357- return m_sObjectByMockDomain .get (domainSObjectType );
358-
359- // Determine SObjectType and Apex classes for Domain class
360- Type domainConstructorClass = m_sObjectByDomainConstructorType .get (domainSObjectType );
361- if (domainConstructorClass == null )
362- throw new DeveloperException (' Domain constructor class not found for SObjectType ' + domainSObjectType );
363-
364- // Construct Domain class passing in the queried records
365- fflib_SObjectDomain .IConstructable2 domainConstructor =
366- (fflib_SObjectDomain .IConstructable2 ) domainConstructorClass .newInstance ();
367- return (fflib_ISObjectDomain ) domainConstructor .construct (records , domainSObjectType );
392+ return newInstance (
393+ (List <Object >) records ,
394+ (Object ) domainSObjectType
395+ );
368396 }
369397
370398 @TestVisible
371399 private virtual void setMock (fflib_ISObjectDomain mockDomain )
372400 {
373- m_sObjectByMockDomain .put (mockDomain .sObjectType (), mockDomain );
401+ mockDomainByObject .put ((Object ) mockDomain .sObjectType (), (fflib_IDomain ) mockDomain );
402+ }
403+
404+ @TestVisible
405+ private virtual void setMock (fflib_IDomain mockDomain )
406+ {
407+ mockDomainByObject .put (mockDomain .getType (), mockDomain );
408+ }
409+
410+ private Map <Object , Type > getConstructorTypeByObject (Map <SObjectType , Type > constructorTypeBySObjectType )
411+ {
412+ Map <Object , Type > result = new Map <Object , Type >();
413+ for (SObjectType sObjectType : constructorTypeBySObjectType .keySet ())
414+ {
415+ result .put (
416+ (Object ) sObjectType ,
417+ constructorTypeBySObjectType .get (sObjectType )
418+ );
419+ }
420+ return result ;
374421 }
375422 }
376423
0 commit comments