From 67ef73292597dc124b2ef74174a552b5b8c26824 Mon Sep 17 00:00:00 2001 From: Wim Velzeboer Date: Fri, 25 Jun 2021 16:04:43 +0100 Subject: [PATCH] Classic implementations for Application Factories Adds additional functionality while maintaining backwards compatibility --- README.md | 1 + docs/domains/application-factories.md | 182 ++++++++++++++++++ docs/how-to-adapt.md | 57 ++++++ .../classic/fflib_ClassicDomainFactory.cls | 157 +++++++++++++++ .../fflib_ClassicDomainFactory.cls-meta.xml | 5 + .../classic/fflib_ClassicSelectorFactory.cls | 101 ++++++++++ .../fflib_ClassicSelectorFactory.cls-meta.xml | 5 + .../classic/fflib_ClassicServiceFactory.cls | 75 ++++++++ .../fflib_ClassicServiceFactory.cls-meta.xml | 5 + .../fflib_ClassicUnitOfWorkFactory.cls | 57 ++++++ ...flib_ClassicUnitOfWorkFactory.cls-meta.xml | 5 + .../interfaces/fflib_IDomainFactory.cls | 2 + .../interfaces/fflib_ISelectorFactory.cls | 8 + 13 files changed, 660 insertions(+) create mode 100644 docs/domains/application-factories.md create mode 100644 sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicDomainFactory.cls create mode 100644 sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicDomainFactory.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicSelectorFactory.cls create mode 100644 sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicSelectorFactory.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicServiceFactory.cls create mode 100644 sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicServiceFactory.cls-meta.xml create mode 100644 sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicUnitOfWorkFactory.cls create mode 100644 sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicUnitOfWorkFactory.cls-meta.xml diff --git a/README.md b/README.md index cbd7efd..60862ad 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ This extension package is dependent on the following packages: ## Contents This extension pack includes the following features +- [Application Class](.docs/application-factories.md) based on interface structure - [Primitive domains](./docs/primitive-domains.md) - [A common criteria based filter](./docs/criteria-based-filter.md) for Domains and Selector diff --git a/docs/domains/application-factories.md b/docs/domains/application-factories.md new file mode 100644 index 0000000..5e43472 --- /dev/null +++ b/docs/domains/application-factories.md @@ -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 selectById(Set 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 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 + { + Schema.Account.SObjectType, + Schema.Contact.SObjectType, + ... + } + ); + + public static final fflib_IServiceFactory Service = + new fflib_ClassicServiceFactory( + new Map + { + IAccountsService.class => AccountsServiceImpl.class, + IContactsService.class => ContactsServiceImpl.class, + ... + } + ); + + public static final fflib_ISelectorFactory Selector = + new fflib_ClassicSelectorFactory( + new Map + { + Schema.Account.SObjectType => AccountsSelector.class, + Schema.Contact.SObjectType => ContactsSelector.class, + ... + } + ); + + public static final fflib_IDomainFactory Domain = + new fflib_ClassicDomainFactory( + Application.Selector, + new Map + { + Schema.Account.SObjectType => Accounts.Constructor.class, + Schema.Contact.SObjectType => Contacts.Constructor.class, + ... + } + ); +} +``` \ No newline at end of file diff --git a/docs/how-to-adapt.md b/docs/how-to-adapt.md index 76f66ab..b89926f 100644 --- a/docs/how-to-adapt.md +++ b/docs/how-to-adapt.md @@ -3,6 +3,63 @@ ## 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. +### 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 + { + Schema.Account.SObjectType, + Schema.Contact.SObjectType, + ... + } + ); + + public static final fflib_IServiceFactory Service = + new fflib_ClassicServiceFactory( + new Map + { + IAccountsService.class => AccountsServiceImpl.class, + IContactsService.class => ContactsServiceImpl.class, + ... + } + ); + + public static final fflib_ISelectorFactory Selector = + new fflib_ClassicSelectorFactory( + new Map + { + Schema.Account.SObjectType => AccountsSelector.class, + Schema.Contact.SObjectType => ContactsSelector.class, + ... + } + ); + + public static final fflib_IDomainFactory Domain = + new fflib_ClassicDomainFactory( + Application.Selector, + new Map + { + Schema.Account.SObjectType => Accounts.Constructor.class, + Schema.Contact.SObjectType => Contacts.Constructor.class, + ... + } + ); +} +``` + + ### Changes to the domain A Domain class is extended from the domain class `SObjects` instead of `fflib_SObjects`. diff --git a/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicDomainFactory.cls b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicDomainFactory.cls new file mode 100644 index 0000000..bd6ab05 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicDomainFactory.cls @@ -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 constructorTypeByObject) + { + selectorFactory = selectorFactory; + this.constructorTypeByObject = constructorTypeByObject; + this.mockDomainByObject = new Map(); + } + + /** + * 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 sObjectByDomainConstructorType) + { + selectorFactory = selectorFactory; + this.constructorTypeByObject = getConstructorTypeByObject(sObjectByDomainConstructorType); + this.mockDomainByObject = new Map(); + } + + /** + * 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 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 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); + } +} \ No newline at end of file diff --git a/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicDomainFactory.cls-meta.xml b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicDomainFactory.cls-meta.xml new file mode 100644 index 0000000..d75b058 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicDomainFactory.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + diff --git a/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicSelectorFactory.cls b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicSelectorFactory.cls new file mode 100644 index 0000000..091050b --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicSelectorFactory.cls @@ -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 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 selectById(Set 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); + } +} \ No newline at end of file diff --git a/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicSelectorFactory.cls-meta.xml b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicSelectorFactory.cls-meta.xml new file mode 100644 index 0000000..d75b058 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicSelectorFactory.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + diff --git a/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicServiceFactory.cls b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicServiceFactory.cls new file mode 100644 index 0000000..e7854a0 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicServiceFactory.cls @@ -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 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); + } +} \ No newline at end of file diff --git a/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicServiceFactory.cls-meta.xml b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicServiceFactory.cls-meta.xml new file mode 100644 index 0000000..d75b058 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicServiceFactory.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + diff --git a/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicUnitOfWorkFactory.cls b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicUnitOfWorkFactory.cls new file mode 100644 index 0000000..11d77d1 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicUnitOfWorkFactory.cls @@ -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 objectTypes) + { + super(objectTypes); + } + + public virtual override void setMock(fflib_ISObjectUnitOfWork mockUow) + { + super.setMock(mockUow); + } +} \ No newline at end of file diff --git a/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicUnitOfWorkFactory.cls-meta.xml b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicUnitOfWorkFactory.cls-meta.xml new file mode 100644 index 0000000..d75b058 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/application/classic/fflib_ClassicUnitOfWorkFactory.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + diff --git a/sfdx-source/apex-extensions/main/default/classes/application/interfaces/fflib_IDomainFactory.cls b/sfdx-source/apex-extensions/main/default/classes/application/interfaces/fflib_IDomainFactory.cls index 3951574..cc49b84 100644 --- a/sfdx-source/apex-extensions/main/default/classes/application/interfaces/fflib_IDomainFactory.cls +++ b/sfdx-source/apex-extensions/main/default/classes/application/interfaces/fflib_IDomainFactory.cls @@ -42,6 +42,8 @@ public interface fflib_IDomainFactory **/ fflib_IDomain newInstance(Set recordIds); + fflib_IDomain newInstance(Set recordIds, Schema.SObjectType objectType); + /** * Dynamically constructs an instance of the Domain class for the given records * Will return a Mock implementation if one has been provided via setMock diff --git a/sfdx-source/apex-extensions/main/default/classes/application/interfaces/fflib_ISelectorFactory.cls b/sfdx-source/apex-extensions/main/default/classes/application/interfaces/fflib_ISelectorFactory.cls index 5af07b7..f83514c 100644 --- a/sfdx-source/apex-extensions/main/default/classes/application/interfaces/fflib_ISelectorFactory.cls +++ b/sfdx-source/apex-extensions/main/default/classes/application/interfaces/fflib_ISelectorFactory.cls @@ -81,6 +81,14 @@ public interface fflib_ISelectorFactory **/ List selectByRelationship(List 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 */