Classic implementations for Application Factories

Adds additional functionality while maintaining backwards compatibility
This commit is contained in:
Wim Velzeboer
2021-06-25 16:04:43 +01:00
parent d28dbb6385
commit 67ef732925
13 changed files with 660 additions and 0 deletions
+1
View File
@@ -9,6 +9,7 @@ This extension package is dependent on the following packages:
## Contents ## Contents
This extension pack includes the following features This extension pack includes the following features
- [Application Class](.docs/application-factories.md) based on interface structure
- [Primitive domains](./docs/primitive-domains.md) - [Primitive domains](./docs/primitive-domains.md)
- [A common criteria based filter](./docs/criteria-based-filter.md) for Domains and Selector - [A common criteria based filter](./docs/criteria-based-filter.md) for Domains and Selector
+182
View File
@@ -0,0 +1,182 @@
# fflib-apex-extensions
## Application Factory Interface Structure
1. [Interface structure](#interface-structure)
1. [Classic](#classic), a backwards compatible implementation
1. Dependency Injection, a dynamic factory that can be configured instead of using hard reference maps
### Interface structure
The existing Application factories of the
[apex-commons](https://github.com/apex-enterprise-patterns/fflib-apex-common)
do not have interfaces, therefore it is hard to replace their implementations. The fflib-apex-extensions add an interface structure and includes multiple implementations for you to choose from.
The [classic](#classic) implementation is fully backward compatible and in the well known familiar structure.
The interfaces adds the following added features
- fflib_IServiceFactory
- [replaceWith](#fflib_iservicefactory---replacewith)
- fflib_ISelectorFactory
- [selectById](#fflib_iselectorfactory---selectbyid) _(method overload)_
- [replaceWith](#fflib_iselectorfactory---replacewith)
- [setMock](#fflib_iselectorfactory---setmock) _(method overload)_
- fflib_IDomainFactory
- [newInstance](#fflib_idomainfactory---newinstance) _(method overload)_
- [replaceWith](#fflib_idomainfactory---replacewith)
- [setMock](#fflib_idomainfactory---setmock) _(method overload)_
##### fflib_IServiceFactory - replaceWith
This will create or replaces an existing binding for another.
###### Syntax
`void replaceWith(Type serviceInterfaceType, Type replacementImplType)`
###### Example
Let's assume we have two implementation for AccountsService `AccountsServiceImpl` and `AlternativeAccountsServiceImpl`.
In the Service Factory `IAccountsService` is bound to the `AccountsServiceImpl` implementation.
```apex
IAccountsService accountsService = (IAccountsService) Application.Service.newInstance();
System.assert(accountsService instanceof AccountsServiceImpl);
// Replace the implementation binding
Application.Service.replaceWith(IAccountsService.class, MyAlternateAccountsServiceImpl.class);
IAccountsService accountsService = (IAccountsService) Application.Service.newInstance();
System.assert(accountsService instanceof AlternativeAccountsServiceImpl);
```
##### fflib_ISelectorFactory - selectById
This method overload accepts an extra argument named `sObjectType`.
By providing the SObjectType, the method assumes that all the provided Ids are of the given SObjectType.
Thereby executing faster as the original method doesn't need to iterate over all the ids
to validate that they are all from the same SObjectType.
###### Syntax
`List<SObject> selectById(Set<Id> recordIds, SObjectType sObjectType)`
##### fflib_ISelectorFactory - replaceWith
This will create or replaces an existing binding for another.
###### Syntax
`void replaceWith(SObjectType sObjectType, Type replacementImplType)`
##### fflib_ISelectorFactory - setMock
This method overload avoids the need to stub the selector mock to return its SObjectType
###### Syntax
`void setMock(SObjectType sObjectType, fflib_ISObjectSelector selectorInstance)`
###### Example
Instead of doing this:
```apex
fflib_ApexMocks mocks = new fflib_ApexMocks();
AccountsSelector serviceMock = (AccountsSelector) mocks.mock(AccountsSelector.class);
mocks.startStubbing();
mocks.when(selectorMock.sObjectType()).thenReturn(Schema.Account.SObjectType);
mocks.stopStubbing();
Application.Selector.setMock(serviceMock);
```
You can now do the same without the need to stub it:
```apex
fflib_ApexMocks mocks = new fflib_ApexMocks();
AccountsSelector serviceMock = (AccountsSelector) mocks.mock(AccountsSelector.class);
Application.Selector.setMock(Schema.Account.SObjectType, serviceMock);
```
##### fflib_IDomainFactory - newInstance
The added argument `sObjectType` avoids the selector to iterate over the given record Ids to validate them.
###### Syntax
`fflib_IDomain newInstance(Set<Id> recordIds, Schema.SObjectType sObjectType)`
##### fflib_IDomainFactory - replaceWith
This will create or replaces an existing binding for another.
###### Syntax
`void replaceWith(Schema.SObjectType sObjectType, Type replacementImplType)`
##### fflib_IDomainFactory - setMock
This method overload avoids the need to stub the selector mock to return its SObjectType
###### Syntax
`void setMock(Schema.SObjectType sObjectType, fflib_ISObjectDomain mockDomain)`
###### Example
Instead of doing this:
```apex
fflib_ApexMocks mocks = new fflib_ApexMocks();
IAccounts domainMock = (IAccounts) mocks.mock(IAccounts.class);
mocks.startStubbing();
mocks.when(domainMock.getType()).thenReturn(Schema.Account.SObjectType);
mocks.stopStubbing();
Application.Domain.setMock(domainMock);
```
You can now do the same without the need to stub it:
```apex
fflib_ApexMocks mocks = new fflib_ApexMocks();
IAccounts domainMock = (IAccounts) mocks.mock(IAccounts.class);
Application.Domain.setMock(Schema.Account.SObjectType, domainMock);
```
### Classic
This is the implementation you are looking for when you are used to the
[Application Factories](https://github.com/apex-enterprise-patterns/fflib-apex-common/blob/master/sfdx-source/apex-common/main/classes/fflib_Application.cls)
of the
[apex-commons](https://github.com/apex-enterprise-patterns/fflib-apex-common)
and you do not want to change anything about the structure based on maps,
but do like to use the added features of fflib-apex-extensions.
It is fully backwards compatible, and you only need to make a few small changes to your existing Application class, to use the added features.
#### Application Class
The Application class is slightly different than the stafactories in the fflib_Application are replaced by an interface structure.
To use the backwards compatible version of the factories, change your Application class into the example below.
Pay special attention to the interface types and implementation classes of the factories.
**Example**
```apex
public class Application
{
public static final fflib_IUnitOfWorkFactory UnitOfWork =
new fflib_ClassicUnitOfWorkFactory(
new List<SObjectType>
{
Schema.Account.SObjectType,
Schema.Contact.SObjectType,
...
}
);
public static final fflib_IServiceFactory Service =
new fflib_ClassicServiceFactory(
new Map<Type, Type>
{
IAccountsService.class => AccountsServiceImpl.class,
IContactsService.class => ContactsServiceImpl.class,
...
}
);
public static final fflib_ISelectorFactory Selector =
new fflib_ClassicSelectorFactory(
new Map<SObjectType, Type>
{
Schema.Account.SObjectType => AccountsSelector.class,
Schema.Contact.SObjectType => ContactsSelector.class,
...
}
);
public static final fflib_IDomainFactory Domain =
new fflib_ClassicDomainFactory(
Application.Selector,
new Map<SObjectType, Type>
{
Schema.Account.SObjectType => Accounts.Constructor.class,
Schema.Contact.SObjectType => Contacts.Constructor.class,
...
}
);
}
```
+57
View File
@@ -3,6 +3,63 @@
## How to adapt ## How to adapt
When you are familiar with using fflib-apex-common, then you need to be aware of a few differences that you will encounter when adopting this extension package. When you are familiar with using fflib-apex-common, then you need to be aware of a few differences that you will encounter when adopting this extension package.
### Contents
1. [The Application class](#changes-to-the-application)
1. [Domain class changes](#changes-to-the-domain)
### Changes to the Application
The factories in the fflib_Application are replaced by an interface structure.
To use the backwards compatible version of the factories, change your Application class into the example below.
Pay special attention to the interface types and implementation classes of the factories.
```apex
public class Application
{
public static final fflib_IUnitOfWorkFactory UnitOfWork =
new fflib_ClassicUnitOfWorkFactory(
new List<SObjectType>
{
Schema.Account.SObjectType,
Schema.Contact.SObjectType,
...
}
);
public static final fflib_IServiceFactory Service =
new fflib_ClassicServiceFactory(
new Map<Type, Type>
{
IAccountsService.class => AccountsServiceImpl.class,
IContactsService.class => ContactsServiceImpl.class,
...
}
);
public static final fflib_ISelectorFactory Selector =
new fflib_ClassicSelectorFactory(
new Map<SObjectType, Type>
{
Schema.Account.SObjectType => AccountsSelector.class,
Schema.Contact.SObjectType => ContactsSelector.class,
...
}
);
public static final fflib_IDomainFactory Domain =
new fflib_ClassicDomainFactory(
Application.Selector,
new Map<SObjectType, Type>
{
Schema.Account.SObjectType => Accounts.Constructor.class,
Schema.Contact.SObjectType => Contacts.Constructor.class,
...
}
);
}
```
### Changes to the domain ### Changes to the domain
A Domain class is extended from the domain class `SObjects` instead of `fflib_SObjects`. A Domain class is extended from the domain class `SObjects` instead of `fflib_SObjects`.
@@ -0,0 +1,157 @@
/**
* File Name: fflib_ClassicDomainFactory
* Description:
*
* @author : architect ir. Wilhelmus G.J. Velzeboer
*
* Copyright (c), W.G.J. Velzeboer,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above author notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the author nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
public virtual class fflib_ClassicDomainFactory
extends fflib_Application.DomainFactory
implements fflib_IDomainFactory
{
protected fflib_ISelectorFactory selectorFactory;
/**
* Constructs a Domain factory
**/
public fflib_ClassicDomainFactory() {}
/**
* Constructs a Domain factory, using an instance of the Selector Factory
* and a map of Apex classes implementing fflib_ISObjectDomain by SObjectType
* Note this will not check the Apex classes provided actually implement the interfaces
* since this is not possible in the Apex runtime at present
*
* @param selectorFactory , e.g. Application.Selector
* @param constructorTypeByObject Map of Domain classes by ObjectType
**/
public fflib_ClassicDomainFactory(
fflib_ISelectorFactory selectorFactory,
Map<Object, Type> constructorTypeByObject)
{
selectorFactory = selectorFactory;
this.constructorTypeByObject = constructorTypeByObject;
this.mockDomainByObject = new Map<Object, fflib_IDomain>();
}
/**
* Constructs a Domain factory, using an instance of the Selector Factory
* and a map of Apex classes implementing fflib_ISObjectDomain by SObjectType
* Note this will not check the Apex classes provided actually implement the interfaces
* since this is not possible in the Apex runtime at present
*
* @param selectorFactory , e.g. Application.Selector
* @param sObjectByDomainConstructorType Map of Apex classes by SObjectType
**/
public fflib_ClassicDomainFactory(fflib_ISelectorFactory selectorFactory,
Map<SObjectType, Type> sObjectByDomainConstructorType)
{
selectorFactory = selectorFactory;
this.constructorTypeByObject = getConstructorTypeByObject(sObjectByDomainConstructorType);
this.mockDomainByObject = new Map<Object, fflib_IDomain>();
}
/**
* Dynamically constructs an instance of a Domain class for the given record Ids
* Internally uses the Selector Factory to query the records before passing to a
* dynamically constructed instance of the application Apex Domain class
*
* @param recordIds A list of Id's of the same type
*
* @return Instance of a Domain containing the queried records
* @exception Throws an exception via the Selector Factory if the Ids are not all of the same SObjectType
**/
public virtual override fflib_IDomain newInstance(Set<Id> recordIds)
{
return newInstance(selectorFactory.selectById(recordIds));
}
/**
* Dynamically constructs an instance of a Domain class for the given record Ids
* Internally uses the Selector Factory to query the records before passing to a
* dynamically constructed instance of the application Apex Domain class
*
* @param recordIds A list of Id's of the same type
* @param sObjectType The SObjectType of the given record Ids
*
* @return Instance of a Domain containing the queried records
* @exception Throws an exception via the Selector Factory if the Ids are not all of the same SObjectType
**/
public virtual fflib_IDomain newInstance(Set<Id> recordIds, Schema.SObjectType sObjectType)
{
return newInstance(selectorFactory.selectById(recordIds, sObjectType));
}
/**
* Creates or replaces an existing binding for another
*
* @param sObjectType The SObjectType of the selector to replace
* @param replacementImplType The implementation type of the replacement
*/
public virtual void replaceWith(Schema.SObjectType sObjectType, Type replacementImplType)
{
this.constructorTypeByObject.put(
(Object) sObjectType,
replacementImplType
);
}
/**
* @param mockDomain The instance of the Domain mock
*/
public virtual override void setMock(fflib_ISObjectDomain mockDomain)
{
super.setMock(mockDomain);
}
/**
* @param sObjectType The SObjectType of the Domain mock,
* avoids the need to stub the mock to return its SObjectType
* @param mockDomain The instance of the Domain mock
*/
public virtual void setMock(Schema.SObjectType sObjectType, fflib_ISObjectDomain mockDomain)
{
mockDomainByObject.put((Object) sObjectType, mockDomain);
}
/**
* @param mockDomain The instance of the Domain mock
*/
public virtual override void setMock(fflib_IDomain mockDomain)
{
super.setMock(mockDomain);
}
/**
* @param domainType The ObjectType of the Domain mock,
* avoids the need to stub the mock to return its ObjectType
* @param mockDomain The instance of the Domain mock
*/
public virtual void setMock(Type domainType, fflib_IDomain mockDomain)
{
mockDomainByObject.put(domainType, mockDomain);
}
}
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>51.0</apiVersion>
<status>Active</status>
</ApexClass>
@@ -0,0 +1,101 @@
/**
* File Name: fflib_ClassicSelectorFactory
* Description:
*
* @author : architect ir. Wilhelmus G.J. Velzeboer
*
* Copyright (c), W.G.J. Velzeboer,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above author notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the author nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
public virtual class fflib_ClassicSelectorFactory
extends fflib_Application.SelectorFactory
implements fflib_ISelectorFactory
{
/**
* Constructs a simple Selector Factory
**/
public fflib_ClassicSelectorFactory() {}
/**
* Constructs a Selector Factory linking SObjectType's with Apex Classes implement the fflib_ISObjectSelector interface
* Note that the factory does not check the given Apex Classes implement the interface
* currently this is not possible in Apex.
*
* @param sObjectBySelectorType Map of SObjectType's to Selector Apex Classes
**/
public fflib_ClassicSelectorFactory(Map<SObjectType, Type> sObjectBySelectorType)
{
super(sObjectBySelectorType);
}
/**
* Helper method to query the given SObject records
* Internally creates an instance of the registered Selector and calls its
* selectSObjectById method.
* It assumes that all Ids are of the given SObjectType, no additional validation is done.
*
* @param recordIds The recordIds to query
* @param sObjectType The SObjectType of the Ids
*
* @return The queried records
* @exception fflib_Application.DeveloperException is thrown if the Ids set is empty
*/
public virtual List<SObject> selectById(Set<Id> recordIds, SObjectType sObjectType)
{
if (recordIds == null || recordIds.size() == 0)
throw new fflib_Application.DeveloperException('Invalid record Id\'s set');
return newInstance(sObjectType)
.selectSObjectsById(recordIds);
}
/**
* Creates or replaces an existing binding for another
*
* @param sObjectType The SObjectType of the selector to replace
* @param replacementImplType The implementation type of the replacement
*/
public virtual void replaceWith(SObjectType sObjectType, Type replacementImplType)
{
this.m_sObjectBySelectorType.put(sObjectType, replacementImplType);
}
/**
* @param selectorInstance The instance of the mocked selector
*/
public virtual override void setMock(fflib_ISObjectSelector selectorInstance)
{
super.setMock(selectorInstance);
}
/**
* @param sObjectType The SObjectType of the selector mock,
* avoids the need to stub the mock to return its SObjectType
* @param selectorInstance The instance of the mocked selector
*/
public virtual void setMock(SObjectType sObjectType, fflib_ISObjectSelector selectorInstance)
{
this.m_sObjectByMockSelector.put(sObjectType, selectorInstance);
}
}
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>51.0</apiVersion>
<status>Active</status>
</ApexClass>
@@ -0,0 +1,75 @@
/**
* File Name: fflib_ClassicServiceFactory
* Description:
*
* @author : architect ir. Wilhelmus G.J. Velzeboer
*
* Copyright (c), W.G.J. Velzeboer,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above author notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the author nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
public virtual class fflib_ClassicServiceFactory
extends fflib_Application.ServiceFactory
implements fflib_IServiceFactory
{
/**
* Constructs a simple Service Factory
**/
public fflib_ClassicServiceFactory() {}
/**
* Constructs a simple Service Factory,
* using a Map of Apex Interfaces to Apex Classes implementing the interface
* Note that this will not check the Apex Classes given actually implement the interfaces
* as this information is not presently available via the Apex runtime
*
* @param serviceInterfaceTypeByServiceImplType Map ofi interfaces to classes
**/
public fflib_ClassicServiceFactory(Map<Type, Type> serviceInterfaceTypeByServiceImplType)
{
super(serviceInterfaceTypeByServiceImplType);
}
/**
* Creates or replaces an existing binding for another
*
* @param serviceInterfaceType The Interface type to replace its implementation
* @param replacementImplType The implementation type of the replacement
*/
public virtual void replaceWith(Type serviceInterfaceType, Type replacementImplType)
{
this.m_serviceInterfaceTypeByServiceImplType.put(
serviceInterfaceType,
replacementImplType
);
}
/**
* @param serviceInterfaceType The interface type to mock
* @param serviceImpl The mock implementation
*/
public virtual override void setMock(Type serviceInterfaceType, Object serviceImpl)
{
super.setMock(serviceInterfaceType, serviceImpl);
}
}
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>51.0</apiVersion>
<status>Active</status>
</ApexClass>
@@ -0,0 +1,57 @@
/**
* File Name: fflib_ClassicUnitOfWorkFactory
* Description:
*
* @author : architect ir. Wilhelmus G.J. Velzeboer
*
* Copyright (c), W.G.J. Velzeboer,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above author notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the author nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
public virtual class fflib_ClassicUnitOfWorkFactory
extends fflib_Application.UnitOfWorkFactory
implements fflib_IUnitOfWorkFactory
{
/**
* Constructs a Unit Of Work factory
**/
public fflib_ClassicUnitOfWorkFactory()
{
super();
}
/**
* Constructs a Unit Of Work factory
*
* @param objectTypes List of SObjectTypes in dependency order
**/
public fflib_ClassicUnitOfWorkFactory(List<SObjectType> objectTypes)
{
super(objectTypes);
}
public virtual override void setMock(fflib_ISObjectUnitOfWork mockUow)
{
super.setMock(mockUow);
}
}
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>51.0</apiVersion>
<status>Active</status>
</ApexClass>
@@ -42,6 +42,8 @@ public interface fflib_IDomainFactory
**/ **/
fflib_IDomain newInstance(Set<Id> recordIds); fflib_IDomain newInstance(Set<Id> recordIds);
fflib_IDomain newInstance(Set<Id> recordIds, Schema.SObjectType objectType);
/** /**
* Dynamically constructs an instance of the Domain class for the given records * Dynamically constructs an instance of the Domain class for the given records
* Will return a Mock implementation if one has been provided via setMock * Will return a Mock implementation if one has been provided via setMock
@@ -81,6 +81,14 @@ public interface fflib_ISelectorFactory
**/ **/
List<SObject> selectByRelationship(List<SObject> relatedRecords, SObjectField relationshipField); List<SObject> selectByRelationship(List<SObject> relatedRecords, SObjectField relationshipField);
/**
* Creates or replaces an existing binding for another
*
* @param sObjectType The SObjectType of the selector to replace
* @param replacementImplType The implementation type of the replacement
*/
void replaceWith(Schema.SObjectType sObjectType, Type replacementImplType);
/** /**
* @param selectorInstance The instance of the mocked selector * @param selectorInstance The instance of the mocked selector
*/ */