diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 92c0956aeba..2c803b9b1cc 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -4,7 +4,6 @@ about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
-
---
**Describe the bug**
@@ -15,6 +14,7 @@ assignees: ''
(Please provide a public github repo with a full SFDX project that demonstrates the problem. If the repro case can be followed with a single example Apex class against a scratch org with just the fflib-apex-common and fflib-apex-mocks project deployed into it, you don't need to provide a github repo)
Steps to reproduce the behavior:
+
1. Create a scratch org as follows....
2. Run the following Anonymous Apex....
3. See error
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index bbcbbe7d615..2f28cead039 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -4,7 +4,6 @@ about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
-
---
**Is your feature request related to a problem? Please describe.**
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 00000000000..bbc9198ea85
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,19 @@
+{
+ "printWidth": 120,
+ "tabWidth": 4,
+ "useTabs": true,
+ "semi": true,
+ "singleQuote": true,
+ "bracketSpacing": true,
+ "bracketSameLine": false,
+ "endOfLine": "lf",
+ "plugins": ["prettier-plugin-apex"],
+ "overrides": [
+ {
+ "files": "*.{cls,apex}",
+ "options": {
+ "parser": "apex"
+ }
+ }
+ ]
+}
diff --git a/README.md b/README.md
index f048e626413..fa37afb5f7d 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,7 @@
-FFLib Apex Common
-=================
+# FFLib Apex Common

-
**Dependencies:** Must deploy [ApexMocks](https://github.com/apex-enterprise-patterns/fflib-apex-mocks) before deploying this library
@@ -11,29 +9,25 @@ FFLib Apex Common
src="https://raw.githubusercontent.com/afawcett/githubsfdeploy/master/src/main/webapp/resources/img/deploy.png">
-Updates
-=======
+# Updates
- **December 2022**, **IMPORTANT CHANGE** - Support for native Apex User Mode was added to the library (see [discussion](https://github.com/apex-enterprise-patterns/fflib-apex-common/discussions/419)). For new projects, the old `enforceCRUD` and `enforceFLS` flags on `fflib_SObjectSelector` should be considered deprecated and the constructors that take `dataAccess` arguments should be used instead. Additionally, the introduction of `fflib_SObjectUnitOfWork.UserModeDML` provides an `IDML` implementation that supports `USER_MODE` or `SYSTEM_MODE`. `fflib_SObjectUnitOfWork.SimpleDML` (the default `IDML` implementation) should be considered deprecated. There are measurable performance benefits to using `SYSTEM_MODE` and `USER_MODE` (Apex CPU usage reduction). Additionally, the use of explicit `USER_MODE` and `SYSTEM_MODE` overrides the `with sharing` and `without sharing` class declaration and makes the expected behavior of DML and SOQL easier to understand.
-- **April 2020**, **IMPORTANT CHANGE**, the directory format of this project repo was converted to [Salesforce DX Source Format](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_source_file_format.htm). While the GIT commit history was maintained, it is not visible on GitHub. If you need to see the history, either clone the repo and execute `git log --follow` from the command line or refer to this [tag](https://github.com/apex-enterprise-patterns/fflib-apex-common/tree/metadata-format-prior-to-dx-source-format-conversion) of the codebase prior to conversion.
+- **April 2020**, **IMPORTANT CHANGE**, the directory format of this project repo was converted to [Salesforce DX Source Format](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_source_file_format.htm). While the GIT commit history was maintained, it is not visible on GitHub. If you need to see the history, either clone the repo and execute `git log --follow` from the command line or refer to this [tag](https://github.com/apex-enterprise-patterns/fflib-apex-common/tree/metadata-format-prior-to-dx-source-format-conversion) of the codebase prior to conversion.
- **September 2014**, **IMPORTANT CHANGE**, changes applied to support Dreamforce 2014 advanced presentation, library now provides Application factories for major layers and support for ApexMocks. More details to follow! As a result [ApexMocks](https://github.com/apex-enterprise-patterns/fflib-apex-mocks) must be deployed to the org before deploying this library. The sample application [here](https://github.com/apex-enterprise-patterns/fflib-apex-common-samplecode) has also been updated to demonstrate the new features!
-- **July 2014**, **IMPORTANT CHANGE**, prior **23rd July 2014**, both the ``fflib_SObjectDomain.onValidate()`` and ``fflib_SObjectDomain.onValidate(Map existingRecords)`` methods where called during an on **after update** trigger event. From this point on the ``onValidate()`` method will only be called during on **after insert**. If you still require the orignal behaviour add the line ``Configuration.enableOldOnUpdateValidateBehaviour();`` into your constructor.
+- **July 2014**, **IMPORTANT CHANGE**, prior **23rd July 2014**, both the `fflib_SObjectDomain.onValidate()` and `fflib_SObjectDomain.onValidate(Map existingRecords)` methods where called during an on **after update** trigger event. From this point on the `onValidate()` method will only be called during on **after insert**. If you still require the orignal behaviour add the line `Configuration.enableOldOnUpdateValidateBehaviour();` into your constructor.
- **June 2014**, New classes providing utilities to support security and dynamic queries, in addition to improvements to existing Apex Enterprise Pattern base classes. Read more [here](http://andyinthecloud.com/2014/06/28/financialforce-apex-common-updates/).
-This Library
-============
+# This Library
Is derived from the **Dreamforce 2012** presentation on [Apex Enterprise Patterns](https://github.com/financialforcedev/df12-apex-enterprise-patterns) and progresses the patterns further with a more general ongoing home for them. It also adds some form of namespace qualification from the previous version. So that classes are grouped together more easily in the IDE's and packages. Below you can find comprehensive articles and videos on the use of these patterns. There is also a **working sample application** illustrating the patterns [here](https://github.com/apex-enterprise-patterns/fflib-apex-common-samplecode).
-
+
-Application Enterprise Patterns on Force.com
-============================================
+# Application Enterprise Patterns on Force.com
Design patterns are an invaluable tool for developers and architects looking to build enterprise solutions. Here are presented some tried and tested enterprise application engineering patterns that have been used in other platforms and languages. We will discuss and illustrate how patterns such as Data Mapper, Service Layer, Unit of Work and of course Model View Controller can be applied to Force.com. Applying these patterns can help manage governed resources (such as DML) better, encourage better separation-of-concerns in your logic and enforce Force.com coding best practices.
-Documentation
--------------
+## Documentation
- [Apex Sharing and applying to Apex Enterprise Patterns](http://andyinthecloud.com/2016/01/10/apex-sharing-and-applying-to-apex-enterprise-patterns/)
- [Tips for Migrating to Apex Enterprise Patterns](http://andyinthecloud.com/2015/09/30/tips-for-migrating-to-apex-enterprise-patterns/)
@@ -44,14 +38,16 @@ Documentation
- [Apex Enterprise Patterns - Service Layer](http://wiki.developerforce.com/page/Apex_Enterprise_Patterns_-_Service_Layer)
- [Apex Enterprise Patterns - Domain Layer](http://wiki.developerforce.com/page/Apex_Enterprise_Patterns_-_Domain_Layer)
- [Apex Enterprise Patterns - Selector Layer](https://github.com/financialforcedev/df12-apex-enterprise-patterns#data-mapper-selector)
-- View slides for the **Dreamforce 2013** session [here](https://docs.google.com/file/d/0B6brfGow3cD8RVVYc1dCX2s0S1E/edit)
+- View slides for the **Dreamforce 2013** session [here](https://docs.google.com/file/d/0B6brfGow3cD8RVVYc1dCX2s0S1E/edit)
- View slides for the **Dreamforce 2015** session [here](http://www.slideshare.net/andyinthecloud/building-strong-foundations-apex-enterprise-patterns)
**Related Webinars**
+
- [Advanced Apex Enterprise Patterns](https://www.youtube.com/watch?v=BLXp0ZP0cF0)
- [Apex Hours (August 2020): Apex Enterprise Patterns](https://www.apexhours.com/apex-enterprise-patterns/)
**Related Book**
+
- [Salesforce Platform Enterprise Architecture, 4th Edition, by Andrew Fawcett](https://www.amazon.com/Salesforce-Platform-Enterprise-Architecture-applications-ebook/dp/B0BD8TBT75/)
**Other Related Blogs**
@@ -59,4 +55,3 @@ Documentation
- [Preview of Advanced Apex Patterns Session (Application Factory and ApexMocks Features)](http://andyinthecloud.com/2014/08/26/preview-of-advanced-apex-enterprise-patterns-session/)
- [Unit Testing with the Domain Layer](http://andyinthecloud.com/2014/03/23/unit-testing-with-the-domain-layer/)
- [FinancialForce Apex Common Updates](http://andyinthecloud.com/2014/06/28/financialforce-apex-common-updates/)
-
diff --git a/config/multicurrency-scratch-def.json b/config/multicurrency-scratch-def.json
index 13823162894..4e2926adf69 100644
--- a/config/multicurrency-scratch-def.json
+++ b/config/multicurrency-scratch-def.json
@@ -1,15 +1,13 @@
{
- "orgName": "apex-common",
- "edition": "Developer",
- "features": [
- "MultiCurrency"
- ],
- "settings": {
- "currencySettings":{
- "enableMultiCurrency": true
- },
- "lightningExperienceSettings": {
- "enableS1DesktopEnabled": true
- }
- }
+ "orgName": "apex-common",
+ "edition": "Developer",
+ "features": ["MultiCurrency"],
+ "settings": {
+ "currencySettings": {
+ "enableMultiCurrency": true
+ },
+ "lightningExperienceSettings": {
+ "enableS1DesktopEnabled": true
+ }
+ }
}
diff --git a/config/project-scratch-def.json b/config/project-scratch-def.json
index 020b6b8e0a4..329a21020a1 100644
--- a/config/project-scratch-def.json
+++ b/config/project-scratch-def.json
@@ -1,9 +1,9 @@
{
- "orgName": "apex-common",
- "edition": "Developer",
- "settings": {
- "lightningExperienceSettings": {
- "enableS1DesktopEnabled": true
- }
- }
+ "orgName": "apex-common",
+ "edition": "Developer",
+ "settings": {
+ "lightningExperienceSettings": {
+ "enableS1DesktopEnabled": true
+ }
+ }
}
diff --git a/sfdx-project.json b/sfdx-project.json
index f2b03860daf..90be09e4de1 100644
--- a/sfdx-project.json
+++ b/sfdx-project.json
@@ -1,11 +1,11 @@
{
- "packageDirectories": [
- {
- "path": "sfdx-source/apex-common",
- "default": true
- }
- ],
- "namespace": "",
- "sfdcLoginUrl": "https://login.salesforce.com",
- "sourceApiVersion": "63.0"
+ "packageDirectories": [
+ {
+ "path": "sfdx-source/apex-common",
+ "default": true
+ }
+ ],
+ "namespace": "",
+ "sfdcLoginUrl": "https://login.salesforce.com",
+ "sourceApiVersion": "63.0"
}
diff --git a/sfdx-source/apex-common/main/classes/fflib_Application.cls b/sfdx-source/apex-common/main/classes/fflib_Application.cls
index d957ca1d511..41d2cab2204 100644
--- a/sfdx-source/apex-common/main/classes/fflib_Application.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_Application.cls
@@ -2,67 +2,64 @@
* Copyright (c), FinancialForce.com, inc
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification,
+ * 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 copyright notice,
+ * - Redistributions of source code must retain the above copyright 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
+ * - 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 FinancialForce.com, inc nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
+ * - Neither the name of the FinancialForce.com, inc 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,
+ * 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.
-**/
+ **/
/**
* Class provides inner classes implementing factories for the main components
* of the Apex Enterprise Patterns, Service, Unit Of Work, Selector and Domain.
* See the sample applications Application.cls file for an example
**/
-public virtual class fflib_Application
-{
+public virtual class fflib_Application {
/**
* Class implements a Unit of Work factory
**/
- public virtual class UnitOfWorkFactory implements fflib_IUnitOfWorkFactory
- {
+ public virtual class UnitOfWorkFactory implements fflib_IUnitOfWorkFactory {
protected List m_objectTypes;
protected fflib_ISObjectUnitOfWork m_mockUow;
/**
* Constructs a Unit Of Work factory
**/
- public UnitOfWorkFactory() { }
+ public UnitOfWorkFactory() {
+ }
/**
* Constructs a Unit Of Work factory
*
* @param objectTypes List of SObjectTypes in dependency order
**/
- public UnitOfWorkFactory(List objectTypes)
- {
+ public UnitOfWorkFactory(List objectTypes) {
m_objectTypes = objectTypes.clone();
}
/**
- * Returns a new fflib_SObjectUnitOfWork configured with the
+ * Returns a new fflib_SObjectUnitOfWork configured with the
* SObjectType list provided in the constructor, returns a Mock implementation
* if set via the setMock method
**/
- public virtual fflib_ISObjectUnitOfWork newInstance()
- {
+ public virtual fflib_ISObjectUnitOfWork newInstance() {
// Mock?
- if(m_mockUow!=null)
+ if (m_mockUow != null)
return m_mockUow;
return new fflib_SObjectUnitOfWork(m_objectTypes);
}
@@ -72,10 +69,9 @@ public virtual class fflib_Application
* SObjectType list provided in the constructor, returns a Mock implementation
* if set via the setMock method
**/
- public virtual fflib_ISObjectUnitOfWork newInstance(fflib_SObjectUnitOfWork.IDML dml)
- {
+ public virtual fflib_ISObjectUnitOfWork newInstance(fflib_SObjectUnitOfWork.IDML dml) {
// Mock?
- if(m_mockUow!=null)
+ if (m_mockUow != null)
return m_mockUow;
return new fflib_SObjectUnitOfWork(m_objectTypes, dml);
}
@@ -88,13 +84,12 @@ public virtual class fflib_Application
* @remark If mock is set, the list of SObjectType in the mock could be different
* than the list of SObjectType specified in this method call
**/
- public virtual fflib_ISObjectUnitOfWork newInstance(List objectTypes)
- {
+ public virtual fflib_ISObjectUnitOfWork newInstance(List objectTypes) {
// Mock?
- if(m_mockUow!=null)
+ if (m_mockUow != null)
return m_mockUow;
return new fflib_SObjectUnitOfWork(objectTypes);
- }
+ }
/**
* Returns a new fflib_SObjectUnitOfWork configured with the
@@ -104,17 +99,18 @@ public virtual class fflib_Application
* @remark If mock is set, the list of SObjectType in the mock could be different
* than the list of SObjectType specified in this method call
**/
- public virtual fflib_ISObjectUnitOfWork newInstance(List objectTypes, fflib_SObjectUnitOfWork.IDML dml)
- {
+ public virtual fflib_ISObjectUnitOfWork newInstance(
+ List objectTypes,
+ fflib_SObjectUnitOfWork.IDML dml
+ ) {
// Mock?
- if(m_mockUow!=null)
+ if (m_mockUow != null)
return m_mockUow;
return new fflib_SObjectUnitOfWork(objectTypes, dml);
}
@TestVisible
- protected virtual void setMock(fflib_ISObjectUnitOfWork mockUow)
- {
+ protected virtual void setMock(fflib_ISObjectUnitOfWork mockUow) {
m_mockUow = mockUow;
}
}
@@ -122,8 +118,7 @@ public virtual class fflib_Application
/**
* Simple Service Factory implementation
**/
- public virtual class ServiceFactory implements fflib_IServiceFactory
- {
+ public virtual class ServiceFactory implements fflib_IServiceFactory {
protected Map m_serviceInterfaceTypeByServiceImplType;
protected Map m_serviceInterfaceTypeByMockService;
@@ -131,18 +126,18 @@ public virtual class fflib_Application
/**
* Constructs a simple Service Factory
**/
- public ServiceFactory() { }
+ public ServiceFactory() {
+ }
/**
- * Constructs a simple Service Factory,
+ * 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 of interfaces to classes
**/
- public ServiceFactory(Map serviceInterfaceTypeByServiceImplType)
- {
+ public ServiceFactory(Map serviceInterfaceTypeByServiceImplType) {
m_serviceInterfaceTypeByServiceImplType = serviceInterfaceTypeByServiceImplType;
m_serviceInterfaceTypeByMockService = new Map();
}
@@ -155,22 +150,22 @@ public virtual class fflib_Application
* @param serviceInterfaceType Apex interface type
* @exception Is thrown if there is no registered Apex class for the interface type
**/
- public virtual Object newInstance(Type serviceInterfaceType)
- {
+ public virtual Object newInstance(Type serviceInterfaceType) {
// Mock implementation?
- if(m_serviceInterfaceTypeByMockService.containsKey(serviceInterfaceType))
+ if (m_serviceInterfaceTypeByMockService.containsKey(serviceInterfaceType))
return m_serviceInterfaceTypeByMockService.get(serviceInterfaceType);
// Create an instance of the type implementing the given interface
Type serviceImpl = m_serviceInterfaceTypeByServiceImplType.get(serviceInterfaceType);
- if(serviceImpl==null)
- throw new DeveloperException('No implementation registered for service interface ' + serviceInterfaceType.getName());
+ if (serviceImpl == null)
+ throw new DeveloperException(
+ 'No implementation registered for service interface ' + serviceInterfaceType.getName()
+ );
return serviceImpl.newInstance();
}
@TestVisible
- protected virtual void setMock(Type serviceInterfaceType, Object serviceImpl)
- {
+ protected virtual void setMock(Type serviceInterfaceType, Object serviceImpl) {
m_serviceInterfaceTypeByMockService.put(serviceInterfaceType, serviceImpl);
}
}
@@ -178,15 +173,15 @@ public virtual class fflib_Application
/**
* Class implements a Selector class factory
**/
- public virtual class SelectorFactory implements fflib_ISelectorFactory
- {
+ public virtual class SelectorFactory implements fflib_ISelectorFactory {
protected Map m_sObjectBySelectorType;
protected Map m_sObjectByMockSelector;
/**
* Constructs a simple Selector Factory
**/
- public SelectorFactory() { }
+ public SelectorFactory() {
+ }
/**
* Constructs a Selector Factory linking SObjectType's with Apex Classes implement the fflib_ISObjectSelector interface
@@ -195,10 +190,9 @@ public virtual class fflib_Application
*
* @param sObjectBySelectorType Map of SObjectType's to Selector Apex Classes
**/
- public SelectorFactory(Map sObjectBySelectorType)
- {
+ public SelectorFactory(Map sObjectBySelectorType) {
m_sObjectBySelectorType = sObjectBySelectorType;
- m_sObjectByMockSelector = new Map();
+ m_sObjectByMockSelector = new Map();
}
/**
@@ -207,19 +201,18 @@ public virtual class fflib_Application
*
* @param sObjectType An SObjectType token, e.g. Account.SObjectType
**/
- public virtual fflib_ISObjectSelector newInstance(SObjectType sObjectType)
- {
+ public virtual fflib_ISObjectSelector newInstance(SObjectType sObjectType) {
// Mock implementation?
- if(m_sObjectByMockSelector.containsKey(sObjectType))
+ if (m_sObjectByMockSelector.containsKey(sObjectType))
return m_sObjectByMockSelector.get(sObjectType);
- // Determine Apex class for Selector class
+ // Determine Apex class for Selector class
Type selectorClass = m_sObjectBySelectorType.get(sObjectType);
- if(selectorClass==null)
+ if (selectorClass == null)
throw new DeveloperException('Selector class not found for SObjectType ' + sObjectType);
// Construct Selector class and query by Id for the records
- return (fflib_ISObjectSelector) selectorClass.newInstance();
+ return (fflib_ISObjectSelector) selectorClass.newInstance();
}
/**
@@ -230,17 +223,18 @@ public virtual class fflib_Application
* @param recordIds The SObject record Ids, must be all the same SObjectType
* @exception Is thrown if the record Ids are not all the same or the SObjectType is not registered
**/
- public virtual List selectById(Set recordIds)
- {
+ public virtual List selectById(Set recordIds) {
// No point creating an empty Domain class, nor can we determine the SObjectType anyway
- if(recordIds==null || recordIds.size()==0)
- throw new DeveloperException('Invalid record Id\'s set');
+ if (recordIds == null || recordIds.size() == 0)
+ throw new DeveloperException('Invalid record Id\'s set');
// Determine SObjectType
SObjectType domainSObjectType = new List(recordIds)[0].getSObjectType();
- for(Id recordId : recordIds)
- if(recordId.getSobjectType()!=domainSObjectType)
- throw new DeveloperException('Unable to determine SObjectType, Set contains Id\'s from different SObject types');
+ for (Id recordId : recordIds)
+ if (recordId.getSobjectType() != domainSObjectType)
+ throw new DeveloperException(
+ 'Unable to determine SObjectType, Set contains Id\'s from different SObject types'
+ );
// Construct Selector class and query by Id for the records
return newInstance(domainSObjectType).selectSObjectsById(recordIds);
@@ -249,49 +243,49 @@ public virtual class fflib_Application
/**
* Helper method to query related records to those provided, for example
* if passed a list of Opportunity records and the Account Id field will
- * construct internally a list of Account Ids and call the registered
+ * construct internally a list of Account Ids and call the registered
* Account selector to query the related Account records, e.g.
*
- * List accounts =
+ * List accounts =
* (List) Application.Selector.selectByRelationship(myOpps, Opportunity.AccountId);
*
* @param relatedRecords used to extract the related record Ids, e.g. Opportunity records
* @param relationshipField field in the passed records that contains the relationship records to query, e.g. Opportunity.AccountId
**/
- public virtual List selectByRelationship(List relatedRecords, SObjectField relationshipField)
- {
+ public virtual List selectByRelationship(
+ List relatedRecords,
+ SObjectField relationshipField
+ ) {
Set relatedIds = new Set();
- for(SObject relatedRecord : relatedRecords)
- {
+ for (SObject relatedRecord : relatedRecords) {
Id relatedId = (Id) relatedRecord.get(relationshipField);
- if(relatedId!=null)
+ if (relatedId != null)
relatedIds.add(relatedId);
}
return selectById(relatedIds);
}
@TestVisible
- protected virtual void setMock(fflib_ISObjectSelector selectorInstance)
- {
+ protected virtual void setMock(fflib_ISObjectSelector selectorInstance) {
m_sObjectByMockSelector.put(selectorInstance.sObjectType(), selectorInstance);
- }
+ }
}
/**
* Class implements a Domain class factory
**/
- public virtual class DomainFactory implements fflib_IDomainFactory
- {
+ public virtual class DomainFactory implements fflib_IDomainFactory {
protected fflib_Application.SelectorFactory m_selectorFactory;
protected Map constructorTypeByObject;
protected Map mockDomainByObject;
- /**
+ /**
* Constructs a Domain factory
**/
- public DomainFactory() { }
+ public DomainFactory() {
+ }
/**
* Constructs a Domain factory, using an instance of the Selector Factory
@@ -302,9 +296,10 @@ public virtual class fflib_Application
* @param selectorFactory , e.g. Application.Selector
* @param constructorTypeByObject Map of Domain classes by ObjectType
**/
- public DomainFactory(fflib_Application.SelectorFactory selectorFactory,
- Map constructorTypeByObject)
- {
+ public DomainFactory(
+ fflib_Application.SelectorFactory selectorFactory,
+ Map constructorTypeByObject
+ ) {
m_selectorFactory = selectorFactory;
this.constructorTypeByObject = constructorTypeByObject;
this.mockDomainByObject = new Map();
@@ -319,9 +314,10 @@ public virtual class fflib_Application
* @param selectorFactory, e.g. Application.Selector
* @param sObjectByDomainConstructorType Map of Apex classes by SObjectType
**/
- public DomainFactory(fflib_Application.SelectorFactory selectorFactory,
- Map sObjectByDomainConstructorType)
- {
+ public DomainFactory(
+ fflib_Application.SelectorFactory selectorFactory,
+ Map sObjectByDomainConstructorType
+ ) {
m_selectorFactory = selectorFactory;
this.constructorTypeByObject = getConstructorTypeByObject(sObjectByDomainConstructorType);
this.mockDomainByObject = new Map();
@@ -335,10 +331,8 @@ public virtual class fflib_Application
* @param recordIds A list of Id's of the same type
* @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)
- {
+ public virtual fflib_IDomain newInstance(Set recordIds) {
return newInstance(m_selectorFactory.selectById(recordIds));
-
}
/**
@@ -349,45 +343,37 @@ public virtual class fflib_Application
* @exception Throws an exception if the SObjectType cannot be determined from the list
* or the constructor for Domain class was not registered for the SObjectType
**/
- public virtual fflib_IDomain newInstance(List records)
- {
+ public virtual fflib_IDomain newInstance(List records) {
SObjectType domainSObjectType = records.getSObjectType();
- if(domainSObjectType==null)
+ if (domainSObjectType == null)
throw new DeveloperException('Unable to determine SObjectType');
return newInstance((List) records, (Object) domainSObjectType);
}
- public virtual fflib_IDomain newInstance(List objects, Object objectType)
- {
+ public virtual fflib_IDomain newInstance(List objects, Object objectType) {
// Mock implementation?
if (mockDomainByObject.containsKey(objectType))
return mockDomainByObject.get(objectType);
// Determine SObjectType and Apex classes for Domain class
Type domainConstructorClass = constructorTypeByObject.get(objectType);
- if(domainConstructorClass==null)
+ if (domainConstructorClass == null)
throw new DeveloperException('Domain constructor class not found for SObjectType ' + objectType);
// Construct Domain class passing in the queried records
Object domainConstructor = domainConstructorClass.newInstance();
// for backwards compatibility
- if (domainConstructor instanceof fflib_SObjectDomain.IConstructable2)
- {
- return (fflib_IDomain)
- ((fflib_SObjectDomain.IConstructable2) domainConstructor)
- .construct((List) objects, (SObjectType) objectType);
- }
- else if (domainConstructor instanceof fflib_SObjectDomain.IConstructable)
- {
- return (fflib_IDomain)
- ((fflib_SObjectDomain.IConstructable) domainConstructor)
- .construct((List) objects);
+ if (domainConstructor instanceof fflib_SObjectDomain.IConstructable2) {
+ return (fflib_IDomain) ((fflib_SObjectDomain.IConstructable2) domainConstructor)
+ .construct((List) objects, (SObjectType) objectType);
+ } else if (domainConstructor instanceof fflib_SObjectDomain.IConstructable) {
+ return (fflib_IDomain) ((fflib_SObjectDomain.IConstructable) domainConstructor)
+ .construct((List) objects);
}
- return ((fflib_IDomainConstructor) domainConstructor)
- .construct(objects);
+ return ((fflib_IDomainConstructor) domainConstructor).construct(objects);
}
/**
@@ -401,47 +387,40 @@ public virtual class fflib_Application
* @remark Will support List but all records in the list will be assumed to be of
* the type specified in sObjectType
**/
- public virtual fflib_IDomain newInstance(List records, SObjectType domainSObjectType)
- {
- if(domainSObjectType==null)
+ public virtual fflib_IDomain newInstance(List records, SObjectType domainSObjectType) {
+ if (domainSObjectType == null)
throw new DeveloperException('Must specify sObjectType');
- return newInstance(
- (List) records,
- (Object) domainSObjectType
- );
+ return newInstance((List) records, (Object) domainSObjectType);
}
@TestVisible
- protected virtual void setMock(fflib_ISObjectDomain mockDomain)
- {
+ protected virtual void setMock(fflib_ISObjectDomain mockDomain) {
mockDomainByObject.put((Object) mockDomain.sObjectType(), (fflib_IDomain) mockDomain);
}
@TestVisible
- protected virtual void setMock(fflib_IDomain mockDomain)
- {
+ protected virtual void setMock(fflib_IDomain mockDomain) {
mockDomainByObject.put(mockDomain.getType(), mockDomain);
}
- protected virtual Map getConstructorTypeByObject(Map constructorTypeBySObjectType)
- {
+ protected virtual Map getConstructorTypeByObject(
+ Map constructorTypeBySObjectType
+ ) {
Map result = new Map();
- for (SObjectType sObjectType : constructorTypeBySObjectType.keySet())
- {
- result.put(
- (Object) sObjectType,
- constructorTypeBySObjectType.get(sObjectType)
- );
+ for (SObjectType sObjectType : constructorTypeBySObjectType.keySet()) {
+ result.put((Object) sObjectType, constructorTypeBySObjectType.get(sObjectType));
}
return result;
}
}
- public class ApplicationException extends Exception { }
+ public class ApplicationException extends Exception {
+ }
/**
* Exception representing a developer coding error, not intended for end user eyes
**/
- public class DeveloperException extends Exception { }
-}
\ No newline at end of file
+ public class DeveloperException extends Exception {
+ }
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_IDomain.cls b/sfdx-source/apex-common/main/classes/fflib_IDomain.cls
index 298f5b8ed42..5941000761d 100644
--- a/sfdx-source/apex-common/main/classes/fflib_IDomain.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_IDomain.cls
@@ -22,9 +22,8 @@
* 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 interface fflib_IDomain
-{
+ **/
+public interface fflib_IDomain {
Object getType();
List getObjects();
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_IDomainConstructor.cls b/sfdx-source/apex-common/main/classes/fflib_IDomainConstructor.cls
index c4096d1d00a..e362fc196d3 100644
--- a/sfdx-source/apex-common/main/classes/fflib_IDomainConstructor.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_IDomainConstructor.cls
@@ -22,8 +22,7 @@
* 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 interface fflib_IDomainConstructor
-{
+ **/
+public interface fflib_IDomainConstructor {
fflib_IDomain construct(List objects);
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_IDomainFactory.cls b/sfdx-source/apex-common/main/classes/fflib_IDomainFactory.cls
index 1e0f982d5ae..e5545fa3ce9 100644
--- a/sfdx-source/apex-common/main/classes/fflib_IDomainFactory.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_IDomainFactory.cls
@@ -22,11 +22,10 @@
* 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 interface fflib_IDomainFactory
-{
+ **/
+public interface fflib_IDomainFactory {
fflib_IDomain newInstance(Set recordIds);
fflib_IDomain newInstance(List records);
fflib_IDomain newInstance(List objects, Object objectType);
fflib_IDomain newInstance(List records, SObjectType domainSObjectType);
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_IObjects.cls b/sfdx-source/apex-common/main/classes/fflib_IObjects.cls
index 80358b22dd7..0dd74358a8f 100644
--- a/sfdx-source/apex-common/main/classes/fflib_IObjects.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_IObjects.cls
@@ -22,9 +22,8 @@
* 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 interface fflib_IObjects extends fflib_IDomain
-{
+ **/
+public interface fflib_IObjects extends fflib_IDomain {
/**
* @param value Values to check if they are part of the domain
*
@@ -81,4 +80,4 @@ public interface fflib_IObjects extends fflib_IDomain
* @return Returns the amount of records contained in the domain
*/
Integer size();
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_ISObjectDomain.cls b/sfdx-source/apex-common/main/classes/fflib_ISObjectDomain.cls
index 3dfadce34d4..95e600ff8e3 100644
--- a/sfdx-source/apex-common/main/classes/fflib_ISObjectDomain.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_ISObjectDomain.cls
@@ -2,37 +2,36 @@
* Copyright (c), FinancialForce.com, inc
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification,
+ * 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 copyright notice,
+ * - Redistributions of source code must retain the above copyright 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
+ * - 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 FinancialForce.com, inc nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
+ * - Neither the name of the FinancialForce.com, inc 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,
+ * 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 interface fflib_ISObjectDomain extends fflib_IDomain
-{
- /**
- * Returns the SObjectType this Domain class represents
- **/
+public interface fflib_ISObjectDomain extends fflib_IDomain {
+ /**
+ * Returns the SObjectType this Domain class represents
+ **/
Schema.SObjectType sObjectType();
- /**
- * Alternative to the Records property, provided to support mocking of Domain classes
- **/
+ /**
+ * Alternative to the Records property, provided to support mocking of Domain classes
+ **/
List getRecords();
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_ISObjectSelector.cls b/sfdx-source/apex-common/main/classes/fflib_ISObjectSelector.cls
index 6cc8a3baddc..b12f271dc16 100644
--- a/sfdx-source/apex-common/main/classes/fflib_ISObjectSelector.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_ISObjectSelector.cls
@@ -2,30 +2,29 @@
* Copyright (c), FinancialForce.com, inc
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification,
+ * 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 copyright notice,
+ * - Redistributions of source code must retain the above copyright 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
+ * - 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 FinancialForce.com, inc nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
+ * - Neither the name of the FinancialForce.com, inc 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,
+ * 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 interface fflib_ISObjectSelector
-{
+public interface fflib_ISObjectSelector {
/**
* Provides the SObjectType for the object the given Selector is providing query logic for
**/
@@ -34,5 +33,5 @@ public interface fflib_ISObjectSelector
/**
* Selects by Id records using the fields defined by the Selector configuration
**/
- List selectSObjectsById(Set idSet);
-}
\ No newline at end of file
+ List selectSObjectsById(Set idSet);
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_ISObjectUnitOfWork.cls b/sfdx-source/apex-common/main/classes/fflib_ISObjectUnitOfWork.cls
index 164920c9c45..1f1b4bd861a 100644
--- a/sfdx-source/apex-common/main/classes/fflib_ISObjectUnitOfWork.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_ISObjectUnitOfWork.cls
@@ -2,228 +2,232 @@
* Copyright (c), FinancialForce.com, inc
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification,
+ * 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 copyright notice,
+ * - Redistributions of source code must retain the above copyright 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
+ * - 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 FinancialForce.com, inc nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
+ * - Neither the name of the FinancialForce.com, inc 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,
+ * 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.
-**/
+ **/
/**
* @see fflib_SObjectUnitOfWork
**/
-public interface fflib_ISObjectUnitOfWork
-{
- /**
- * Register a newly created SObject instance to be inserted when commitWork is called
- *
- * @param record A newly created SObject instance to be inserted during commitWork
- **/
- void registerNew(SObject record);
- /**
- * Register a list of newly created SObject instances to be inserted when commitWork is called
- *
- * @param records A list of newly created SObject instances to be inserted during commitWork
- **/
- void registerNew(List records);
- /**
- * Register a newly created SObject instance to be inserted when commitWork is called,
- * you may also provide a reference to the parent record instance (should also be registered as new separately)
- *
- * @param record A newly created SObject instance to be inserted during commitWork
- * @param relatedToParentField A SObjectField reference to the child field that associates the child record with its parent
- * @param relatedToParentRecord A SObject instance of the parent record (should also be registered as new separately)
- **/
- void registerNew(SObject record, Schema.SObjectField relatedToParentField, SObject relatedToParentRecord);
- /**
- * Register a relationship between two records that have yet to be inserted to the database. This information will be
- * used during the commitWork phase to make the references only when related records have been inserted to the database.
- *
- * @param record An existing or newly created record
- * @param relatedToField A SObjectField reference to the lookup field that relates the two records together
- * @param relatedTo A SObject instance (yet to be committed to the database)
- */
- void registerRelationship(SObject record, Schema.SObjectField relatedToField, SObject relatedTo);
- /**
- * Registers a relationship between a record and a Messaging.Email where the record has yet to be inserted
- * to the database. This information will be
- * used during the commitWork phase to make the references only when related records have been inserted to the database.
- *
- * @param email a single email message instance
- * @param relatedTo A SObject instance (yet to be committed to the database)
- */
- void registerRelationship(Messaging.SingleEmailMessage email, SObject relatedTo);
- /**
- * Registers a relationship between a record and a lookup value using an external ID field and a provided value. This
- * information will be used during the commitWork phase to make the lookup reference requested when inserted to the database.
- *
- * @param record An existing or newly created record
- * @param relatedToField A SObjectField reference to the lookup field that relates the two records together
- * @param externalIdField A SObjectField reference to a field on the target SObject that is marked as isExternalId
- * @param externalId A Object representing the targeted value of the externalIdField in said lookup
- *
- * Usage Example: uow.registerRelationship(recordSObject, record_sobject__c.relationship_field__c, lookup_sobject__c.external_id__c, 'abc123');
- *
- * Wraps putSObject, creating a new instance of the lookup sobject using the external id field and value.
- */
- void registerRelationship(SObject record, Schema.SObjectField relatedToField, Schema.SObjectField externalIdField, Object externalId);
- /**
- * Register an existing record to be updated during the commitWork method
- *
- * @param record An existing record
- **/
- void registerDirty(SObject record);
- /**
- * Register specific fields on records to be updated when work is committed
- *
- * If the records are previously registered as dirty, the dirty fields on the records in this call will overwrite
- * the values of the previously registered dirty records
- *
- * @param records A list of existing records
- * @param dirtyFields The fields to update if record is already registered
- **/
- void registerDirty(List records, List dirtyFields);
- /**
- * Register specific fields on record to be updated when work is committed
- *
- * If the record has previously been registered as dirty, the dirty fields on the record in this call will overwrite
- * the values of the previously registered dirty record
- *
- * @param record An existing record
- * @param dirtyFields The fields to update if record is already registered
- **/
- void registerDirty(SObject record, List dirtyFields);
- /**
- * Register an existing record to be updated when commitWork is called,
- * you may also provide a reference to the parent record instance (should also be registered as new separately)
- *
- * @param record A newly created SObject instance to be inserted during commitWork
- * @param relatedToParentField A SObjectField reference to the child field that associates the child record with its parent
- * @param relatedToParentRecord A SObject instance of the parent record (should also be registered as new separately)
- **/
- void registerDirty(SObject record, Schema.SObjectField relatedToParentField, SObject relatedToParentRecord);
- /**
- * Register a list of existing records to be updated during the commitWork method
- *
- * @param records A list of existing records
- **/
- void registerDirty(List records);
- /**
+public interface fflib_ISObjectUnitOfWork {
+ /**
+ * Register a newly created SObject instance to be inserted when commitWork is called
+ *
+ * @param record A newly created SObject instance to be inserted during commitWork
+ **/
+ void registerNew(SObject record);
+ /**
+ * Register a list of newly created SObject instances to be inserted when commitWork is called
+ *
+ * @param records A list of newly created SObject instances to be inserted during commitWork
+ **/
+ void registerNew(List records);
+ /**
+ * Register a newly created SObject instance to be inserted when commitWork is called,
+ * you may also provide a reference to the parent record instance (should also be registered as new separately)
+ *
+ * @param record A newly created SObject instance to be inserted during commitWork
+ * @param relatedToParentField A SObjectField reference to the child field that associates the child record with its parent
+ * @param relatedToParentRecord A SObject instance of the parent record (should also be registered as new separately)
+ **/
+ void registerNew(SObject record, Schema.SObjectField relatedToParentField, SObject relatedToParentRecord);
+ /**
+ * Register a relationship between two records that have yet to be inserted to the database. This information will be
+ * used during the commitWork phase to make the references only when related records have been inserted to the database.
+ *
+ * @param record An existing or newly created record
+ * @param relatedToField A SObjectField reference to the lookup field that relates the two records together
+ * @param relatedTo A SObject instance (yet to be committed to the database)
+ */
+ void registerRelationship(SObject record, Schema.SObjectField relatedToField, SObject relatedTo);
+ /**
+ * Registers a relationship between a record and a Messaging.Email where the record has yet to be inserted
+ * to the database. This information will be
+ * used during the commitWork phase to make the references only when related records have been inserted to the database.
+ *
+ * @param email a single email message instance
+ * @param relatedTo A SObject instance (yet to be committed to the database)
+ */
+ void registerRelationship(Messaging.SingleEmailMessage email, SObject relatedTo);
+ /**
+ * Registers a relationship between a record and a lookup value using an external ID field and a provided value. This
+ * information will be used during the commitWork phase to make the lookup reference requested when inserted to the database.
+ *
+ * @param record An existing or newly created record
+ * @param relatedToField A SObjectField reference to the lookup field that relates the two records together
+ * @param externalIdField A SObjectField reference to a field on the target SObject that is marked as isExternalId
+ * @param externalId A Object representing the targeted value of the externalIdField in said lookup
+ *
+ * Usage Example: uow.registerRelationship(recordSObject, record_sobject__c.relationship_field__c, lookup_sobject__c.external_id__c, 'abc123');
+ *
+ * Wraps putSObject, creating a new instance of the lookup sobject using the external id field and value.
+ */
+ void registerRelationship(
+ SObject record,
+ Schema.SObjectField relatedToField,
+ Schema.SObjectField externalIdField,
+ Object externalId
+ );
+ /**
+ * Register an existing record to be updated during the commitWork method
+ *
+ * @param record An existing record
+ **/
+ void registerDirty(SObject record);
+ /**
+ * Register specific fields on records to be updated when work is committed
+ *
+ * If the records are previously registered as dirty, the dirty fields on the records in this call will overwrite
+ * the values of the previously registered dirty records
+ *
+ * @param records A list of existing records
+ * @param dirtyFields The fields to update if record is already registered
+ **/
+ void registerDirty(List records, List dirtyFields);
+ /**
+ * Register specific fields on record to be updated when work is committed
+ *
+ * If the record has previously been registered as dirty, the dirty fields on the record in this call will overwrite
+ * the values of the previously registered dirty record
+ *
+ * @param record An existing record
+ * @param dirtyFields The fields to update if record is already registered
+ **/
+ void registerDirty(SObject record, List dirtyFields);
+ /**
+ * Register an existing record to be updated when commitWork is called,
+ * you may also provide a reference to the parent record instance (should also be registered as new separately)
+ *
+ * @param record A newly created SObject instance to be inserted during commitWork
+ * @param relatedToParentField A SObjectField reference to the child field that associates the child record with its parent
+ * @param relatedToParentRecord A SObject instance of the parent record (should also be registered as new separately)
+ **/
+ void registerDirty(SObject record, Schema.SObjectField relatedToParentField, SObject relatedToParentRecord);
+ /**
+ * Register a list of existing records to be updated during the commitWork method
+ *
+ * @param records A list of existing records
+ **/
+ void registerDirty(List records);
+ /**
* Register an deleted record to be removed from the recycle bin during the commitWork method
*
* @param record An deleted record
**/
- void registerEmptyRecycleBin(SObject record);
- /**
+ void registerEmptyRecycleBin(SObject record);
+ /**
* Register deleted records to be removed from the recycle bin during the commitWork method
*
* @param records Deleted records
**/
- void registerEmptyRecycleBin(List records);
- /**
- * Register a new or existing record to be inserted or updated during the commitWork method
- *
- * @param record An new or existing record
- **/
- void registerUpsert(SObject record);
- /**
- * Register a list of mix of new and existing records to be upserted during the commitWork method
- *
- * @param records A list of mix of existing and new records
- **/
- void registerUpsert(List records);
- /**
- * Register an existing record to be deleted during the commitWork method
- *
- * @param record An existing record
- **/
- void registerDeleted(SObject record);
- /**
- * Register a list of existing records to be deleted during the commitWork method
- *
- * @param records A list of existing records
- **/
- void registerDeleted(List records);
- /**
- * Register a list of existing records to be deleted and removed from the recycle bin during the commitWork method
- *
- * @param records A list of existing records
- **/
- void registerPermanentlyDeleted(List records);
- /**
- * Register a list of existing records to be deleted and removed from the recycle bin during the commitWork method
- *
- * @param record A list of existing records
- **/
- void registerPermanentlyDeleted(SObject record);
- /**
- * Register a newly created SObject (Platform Event) instance to be published when commitWork is called
- *
- * @param record A newly created SObject (Platform Event) instance to be inserted during commitWork
- **/
- void registerPublishBeforeTransaction(SObject record);
- /**
- * Register a list of newly created SObject (Platform Event) instance to be published when commitWork is called
- *
- * @param records A list of existing records
- **/
- void registerPublishBeforeTransaction(List records);
- /**
- * Register a newly created SObject (Platform Event) instance to be published when commitWork has successfully
- * completed
- *
- * @param record A newly created SObject (Platform Event) instance to be inserted during commitWork
- **/
- void registerPublishAfterSuccessTransaction(SObject record);
- /**
- * Register a list of newly created SObject (Platform Event) instance to be published when commitWork has successfully
- * completed
- *
- * @param records A list of existing records
- **/
- void registerPublishAfterSuccessTransaction(List records);
- /**
- * Register a newly created SObject (Platform Event) instance to be published when commitWork has caused an error
- *
- * @param record A newly created SObject (Platform Event) instance to be inserted during commitWork
- **/
- void registerPublishAfterFailureTransaction(SObject record);
- /**
- * Register a list of newly created SObject (Platform Event) instance to be published when commitWork has caused an
- * error
- *
- * @param records A list of existing records
- **/
- void registerPublishAfterFailureTransaction(List records);
- /**
- * Takes all the work that has been registered with the UnitOfWork and commits it to the database
- **/
- void commitWork();
- /**
- * Register a generic piece of work to be invoked during the commitWork phase
- *
- * @param work Work to be registered
- **/
- void registerWork(fflib_SObjectUnitOfWork.IDoWork work);
- /**
- * Registers the given email to be sent during the commitWork
- *
- * @param email Email to be sent
- **/
- void registerEmail(Messaging.Email email);
-}
\ No newline at end of file
+ void registerEmptyRecycleBin(List records);
+ /**
+ * Register a new or existing record to be inserted or updated during the commitWork method
+ *
+ * @param record An new or existing record
+ **/
+ void registerUpsert(SObject record);
+ /**
+ * Register a list of mix of new and existing records to be upserted during the commitWork method
+ *
+ * @param records A list of mix of existing and new records
+ **/
+ void registerUpsert(List records);
+ /**
+ * Register an existing record to be deleted during the commitWork method
+ *
+ * @param record An existing record
+ **/
+ void registerDeleted(SObject record);
+ /**
+ * Register a list of existing records to be deleted during the commitWork method
+ *
+ * @param records A list of existing records
+ **/
+ void registerDeleted(List records);
+ /**
+ * Register a list of existing records to be deleted and removed from the recycle bin during the commitWork method
+ *
+ * @param records A list of existing records
+ **/
+ void registerPermanentlyDeleted(List records);
+ /**
+ * Register a list of existing records to be deleted and removed from the recycle bin during the commitWork method
+ *
+ * @param record A list of existing records
+ **/
+ void registerPermanentlyDeleted(SObject record);
+ /**
+ * Register a newly created SObject (Platform Event) instance to be published when commitWork is called
+ *
+ * @param record A newly created SObject (Platform Event) instance to be inserted during commitWork
+ **/
+ void registerPublishBeforeTransaction(SObject record);
+ /**
+ * Register a list of newly created SObject (Platform Event) instance to be published when commitWork is called
+ *
+ * @param records A list of existing records
+ **/
+ void registerPublishBeforeTransaction(List records);
+ /**
+ * Register a newly created SObject (Platform Event) instance to be published when commitWork has successfully
+ * completed
+ *
+ * @param record A newly created SObject (Platform Event) instance to be inserted during commitWork
+ **/
+ void registerPublishAfterSuccessTransaction(SObject record);
+ /**
+ * Register a list of newly created SObject (Platform Event) instance to be published when commitWork has successfully
+ * completed
+ *
+ * @param records A list of existing records
+ **/
+ void registerPublishAfterSuccessTransaction(List records);
+ /**
+ * Register a newly created SObject (Platform Event) instance to be published when commitWork has caused an error
+ *
+ * @param record A newly created SObject (Platform Event) instance to be inserted during commitWork
+ **/
+ void registerPublishAfterFailureTransaction(SObject record);
+ /**
+ * Register a list of newly created SObject (Platform Event) instance to be published when commitWork has caused an
+ * error
+ *
+ * @param records A list of existing records
+ **/
+ void registerPublishAfterFailureTransaction(List records);
+ /**
+ * Takes all the work that has been registered with the UnitOfWork and commits it to the database
+ **/
+ void commitWork();
+ /**
+ * Register a generic piece of work to be invoked during the commitWork phase
+ *
+ * @param work Work to be registered
+ **/
+ void registerWork(fflib_SObjectUnitOfWork.IDoWork work);
+ /**
+ * Registers the given email to be sent during the commitWork
+ *
+ * @param email Email to be sent
+ **/
+ void registerEmail(Messaging.Email email);
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_ISObjects.cls b/sfdx-source/apex-common/main/classes/fflib_ISObjects.cls
index bf30d9a276e..287e4f2e609 100644
--- a/sfdx-source/apex-common/main/classes/fflib_ISObjects.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_ISObjects.cls
@@ -22,9 +22,8 @@
* 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 interface fflib_ISObjects extends fflib_IObjects
-{
+ **/
+public interface fflib_ISObjects extends fflib_IObjects {
/**
* @return Return the SObject records contained in the domain
*/
@@ -39,4 +38,4 @@ public interface fflib_ISObjects extends fflib_IObjects
* @return Return the SObjectType of the SObjects contained in the domain
*/
SObjectType getSObjectType();
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_ISelectorFactory.cls b/sfdx-source/apex-common/main/classes/fflib_ISelectorFactory.cls
index a39095b289b..481f54106d9 100644
--- a/sfdx-source/apex-common/main/classes/fflib_ISelectorFactory.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_ISelectorFactory.cls
@@ -22,10 +22,9 @@
* 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 interface fflib_ISelectorFactory
-{
+ **/
+public interface fflib_ISelectorFactory {
fflib_ISObjectSelector newInstance(SObjectType sObjectType);
List selectById(Set recordIds);
List selectByRelationship(List relatedRecords, SObjectField relationshipField);
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_IServiceFactory.cls b/sfdx-source/apex-common/main/classes/fflib_IServiceFactory.cls
index 93fa4124cc7..0c1c1e14d63 100644
--- a/sfdx-source/apex-common/main/classes/fflib_IServiceFactory.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_IServiceFactory.cls
@@ -22,8 +22,7 @@
* 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 interface fflib_IServiceFactory
-{
+ **/
+public interface fflib_IServiceFactory {
Object newInstance(Type serviceInterfaceType);
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_IUnitOfWorkFactory.cls b/sfdx-source/apex-common/main/classes/fflib_IUnitOfWorkFactory.cls
index 371ab1ccde9..19db88bb78f 100644
--- a/sfdx-source/apex-common/main/classes/fflib_IUnitOfWorkFactory.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_IUnitOfWorkFactory.cls
@@ -22,11 +22,10 @@
* 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 interface fflib_IUnitOfWorkFactory
-{
+ **/
+public interface fflib_IUnitOfWorkFactory {
fflib_ISObjectUnitOfWork newInstance();
fflib_ISObjectUnitOfWork newInstance(fflib_SObjectUnitOfWork.IDML dml);
fflib_ISObjectUnitOfWork newInstance(List objectTypes);
fflib_ISObjectUnitOfWork newInstance(List objectTypes, fflib_SObjectUnitOfWork.IDML dml);
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_Objects.cls b/sfdx-source/apex-common/main/classes/fflib_Objects.cls
index 44c4f069eaf..7fff341946e 100644
--- a/sfdx-source/apex-common/main/classes/fflib_Objects.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_Objects.cls
@@ -22,92 +22,86 @@
* 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_Objects implements fflib_IObjects
-{
- protected List objects { get; private set;} { objects = new List(); }
+ **/
+public virtual class fflib_Objects implements fflib_IObjects {
+ protected List objects { get; private set; }
+
+ {
+ objects = new List();
+ }
/**
* Class constructor
*/
- public fflib_Objects(List objects)
- {
+ public fflib_Objects(List objects) {
this.objects = objects.clone();
}
- public virtual Object getType()
- {
+ public virtual Object getType() {
return Object.class;
}
- public List getObjects()
- {
+ public List getObjects() {
return this.objects;
}
- public Boolean contains(Object value)
- {
+ public Boolean contains(Object value) {
return getObjects()?.contains(value);
}
- public Boolean containsAll(List values)
- {
- if (values == null) return false;
+ public Boolean containsAll(List values) {
+ if (values == null)
+ return false;
return containsAll(new Set(values));
}
- public Boolean containsAll(Set values)
- {
- if (values == null) return false;
+ public Boolean containsAll(Set values) {
+ if (values == null)
+ return false;
- for (Object value : values)
- {
- if (!getObjects()?.contains(value)) return false;
+ for (Object value : values) {
+ if (!getObjects()?.contains(value))
+ return false;
}
return true;
}
- public Boolean containsNot(Object value)
- {
+ public Boolean containsNot(Object value) {
return !contains(value);
}
- public Boolean containsNot(List values)
- {
- if (values == null) return true;
+ public Boolean containsNot(List values) {
+ if (values == null)
+ return true;
return containsNot(new Set(values));
}
- public Boolean containsNot(Set values)
- {
- if (values == null) return true;
+ public Boolean containsNot(Set values) {
+ if (values == null)
+ return true;
- for (Object value : values)
- {
- if (getObjects()?.contains(value)) return false;
+ for (Object value : values) {
+ if (getObjects()?.contains(value))
+ return false;
}
return true;
}
- public Boolean isEmpty()
- {
+ public Boolean isEmpty() {
return (getObjects() == null || getObjects().isEmpty());
}
- public Boolean isNotEmpty()
- {
+ public Boolean isNotEmpty() {
return !isEmpty();
}
- public Integer size()
- {
+ public Integer size() {
return getObjects().size();
}
- protected void setObjects(List objects)
- {
+ protected void setObjects(List objects) {
this.objects = objects;
}
-}
\ No newline at end of file
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_QueryFactory.cls b/sfdx-source/apex-common/main/classes/fflib_QueryFactory.cls
index cf31cc0e40c..595bc898387 100644
--- a/sfdx-source/apex-common/main/classes/fflib_QueryFactory.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_QueryFactory.cls
@@ -2,44 +2,44 @@
* Copyright (c), FinancialForce.com, inc
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification,
+ * 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 copyright notice,
+ * - Redistributions of source code must retain the above copyright 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
+ * - 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 FinancialForce.com, inc nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
+ * - Neither the name of the FinancialForce.com, inc 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,
+ * 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.
-**/
+ **/
/**
* QueryFactory provides an object-oriented way of building SOQL queries without resorting to string manipulation.
* This class is not meant to be used as a replacement for all SOQL queries, and due to the relatively high overhead in both CPU and describe calls
* should be used in places where highly dynamic queries, such as those that include field sets or are mutated heavily
* in multiple locations are a good fit for use with fflib_QueryFactory.
- *
+ *
* To use call construct a new instance for each query you intend to make.
* To add additional fields to the query make use of the selectField(s) methods.
*
* Currently the WHERE clause of the query is manipulated as a single string, and is decidedly less OO-styled than other methods.
* This is expected to be expanded upon in the future.
- *
+ *
* To include one or more ORDER BY clause(s), use one of the addOrdering methods. If not specified, the "NULLS FIRST" keywords
* will be included by default. Constructing Ordering instances manually is discouraged.
- *
- * Subselect Queries are supported with the subselectQuery methods.
+ *
+ * Subselect Queries are supported with the subselectQuery methods.
* More than one sub-query can be added to a single query.
* An exception will thrown from the subselectQuery method when there is an attempt to add a subquery to a query with an invalid relationship.
*
@@ -50,59 +50,67 @@
*
* There is a google doc providing additional guidance on the use of this class with field sets at
* https://docs.google.com/a/financialforce.com/document/d/1I4cxN4xHT4UJj_3Oi0YBL_MJ5chm-KG8kMN1D1un8-g/edit?usp=sharing
-**/
+ **/
public class fflib_QueryFactory { //No explicit sharing declaration - inherit from caller
- public enum SortOrder {ASCENDING, DESCENDING}
- public enum FLSEnforcement{NONE, LEGACY, USER_MODE, SYSTEM_MODE}
+ public enum SortOrder {
+ ASCENDING,
+ DESCENDING
+ }
+ public enum FLSEnforcement {
+ NONE,
+ LEGACY,
+ USER_MODE,
+ SYSTEM_MODE
+ }
/**
* This property is read-only and may not be set after instantiation.
* The {@link Schema.SObjectType} token of the SObject that will be used in the FROM clause of the resultant query.
- **/
- public Schema.SObjectType table {get; private set;}
+ **/
+ public Schema.SObjectType table { get; private set; }
@TestVisible
- private Set fields;
+ private Set fields;
private String conditionExpression;
private Integer limitCount;
private Integer offsetCount;
private List order;
/**
* Integrate checking for READ Field Level Security within the selectField(s) methods
- * This can optionally be enforced (or not) by calling the setEnforceFLS method prior to calling
+ * This can optionally be enforced (or not) by calling the setEnforceFLS method prior to calling
* one of the selectField or selectFieldset methods.
- **/
+ **/
private FLSEnforcement mFlsEnforcement;
private Boolean sortSelectFields = true;
private Boolean allRows = false;
-
+
/**
- * The relationship and subselectQueryMap variables are used to support subselect queries. Subselects can be added to
+ * The relationship and subselectQueryMap variables are used to support subselect queries. Subselects can be added to
* a query, as long as it isn't a subselect query itself. You may have many subselects inside
* a query, but they may only be 1 level deep (no subselect inside a subselect)
* to add a subselect, call the subselectQuery method, passing in the ChildRelationship.
- **/
+ **/
private Schema.ChildRelationship relationship;
private Map subselectQueryMap;
- private String getFieldPath(String fieldName, Schema.sObjectType relatedSObjectType){
-
+ private String getFieldPath(String fieldName, Schema.sObjectType relatedSObjectType) {
//Enforcing FLS using the legacy heuristic requires resolving the full field path to its respective
//Describe result to test for isAccessible on the DescribeFieldResult
//This is computationally expensive and should be bypassed if the QueryFactory instance is not
//enforcing FLS
//Starting in Summer '22, Apex can natively enforce CRUD and FLS with User Mode Operations
//Someday, the LEGACY FLSEnforcement heuristic will be removed
- if(mFlsEnforcement == FLSEnforcement.USER_MODE || mFlsEnforcement == FLSEnforcement.SYSTEM_MODE){
+ if (mFlsEnforcement == FLSEnforcement.USER_MODE || mFlsEnforcement == FLSEnforcement.SYSTEM_MODE) {
return fieldName;
}
- if(!fieldName.contains('.')){ //single field
+ if (!fieldName.contains('.')) {
+ //single field
Schema.SObjectField token = fflib_SObjectDescribe.getDescribe(table).getField(fieldName.toLowerCase());
- if(token == null) {
+ if (token == null) {
throw new InvalidFieldException(fieldName, this.table);
}
- if(mFlsEnforcement == FLSEnforcement.LEGACY) {
+ if (mFlsEnforcement == FLSEnforcement.LEGACY) {
fflib_SecurityUtils.checkFieldIsReadable(this.table, token);
}
@@ -113,11 +121,12 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
List fieldPath = new List();
Schema.SObjectType lastSObjectType = table;
Iterator i = fieldName.split('\\.').iterator();
- while(i.hasNext()){
+ while (i.hasNext()) {
String field = i.next();
- Schema.SObjectField token = fflib_SObjectDescribe.getDescribe(lastSObjectType).getField(field.toLowerCase());
+ Schema.SObjectField token = fflib_SObjectDescribe.getDescribe(lastSObjectType)
+ .getField(field.toLowerCase());
DescribeFieldResult tokenDescribe = token != null ? token.getDescribe() : null;
-
+
if (token != null && mFlsEnforcement == FLSEnforcement.LEGACY) {
fflib_SecurityUtils.checkFieldIsReadable(lastSObjectType, token);
}
@@ -127,10 +136,11 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
if (relatedObjs.size() == 1 || relatedSObjectType == null) {
lastSObjectType = relatedObjs[0]; //caller did not specify the one to use or there's only one so use the first one
- }
- else{
+ } else {
for (Schema.sObjectType sot : relatedObjs) {
- if (fflib_SObjectDescribe.getDescribe(sot).getDescribe().getSObjectType() == relatedSObjectType) {
+ if (
+ fflib_SObjectDescribe.getDescribe(sot).getDescribe().getSObjectType() == relatedSObjectType
+ ) {
lastSObjectType = sot;
break;
}
@@ -138,27 +148,32 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
}
fieldPath.add(tokenDescribe.getRelationshipName());
- }else if(token != null && !i.hasNext()){
+ } else if (token != null && !i.hasNext()) {
fieldPath.add(tokenDescribe.getName());
- }else{
- if(token == null)
- throw new InvalidFieldException(field,lastSObjectType);
+ } else {
+ if (token == null)
+ throw new InvalidFieldException(field, lastSObjectType);
else
- throw new NonReferenceFieldException(lastSObjectType+'.'+field+' is not a lookup or master-detail field but is used in a cross-object query field.');
+ throw new NonReferenceFieldException(
+ lastSObjectType +
+ '.' +
+ field +
+ ' is not a lookup or master-detail field but is used in a cross-object query field.'
+ );
}
}
- return String.join(fieldPath,'.');
+ return String.join(fieldPath, '.');
}
-
+
private String getFieldPath(String fieldName) {
return this.getFieldPath(fieldName, null);
}
@TestVisible
- private static String getFieldTokenPath(Schema.SObjectField field){
- if(field == null){
- throw new InvalidFieldException('Invalid field: null');
+ private static String getFieldTokenPath(Schema.SObjectField field) {
+ if (field == null) {
+ throw new InvalidFieldException('Invalid field: null');
}
return field.getDescribe().getLocalName();
}
@@ -166,21 +181,25 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
/**
* fflib_QueryFactory instances will be considered equal if they produce the same SOQL query.
* A faster comparison will first be attempted to check if they apply to the same table, and contain the same number of fields selected.
- * This method will never return true if the provided object is not an instance of fflib_QueryFactory.
+ * This method will never return true if the provided object is not an instance of fflib_QueryFactory.
* @param obj the object to check equality of.
- **/
- public Boolean equals(Object obj){
- if( !(obj instanceof fflib_QueryFactory) || ((fflib_QueryFactory)obj).table != this.table || ((fflib_QueryFactory)obj).fields.size() != this.fields.size() )
+ **/
+ public Boolean equals(Object obj) {
+ if (
+ !(obj instanceof fflib_QueryFactory) ||
+ ((fflib_QueryFactory) obj).table != this.table ||
+ ((fflib_QueryFactory) obj).fields.size() != this.fields.size()
+ )
return false;
- return ((fflib_QueryFactory)obj).toSOQL() == this.toSOQL();
+ return ((fflib_QueryFactory) obj).toSOQL() == this.toSOQL();
}
/**
* Construct a new fflib_QueryFactory instance with no options other than the FROM clause.
* You *must* call selectField(s) before {@link #toSOQL} will return a valid, runnable query.
* @param table the SObject to be used in the FROM clause of the resultant query. This sets the value of {@link #table}.
- **/
- public fflib_QueryFactory(Schema.SObjectType table){
+ **/
+ public fflib_QueryFactory(Schema.SObjectType table) {
this.table = table;
fields = new Set();
order = new List();
@@ -189,21 +208,21 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
/**
* Construct a new fflib_QueryFactory instance with no options other than the FROM clause and the relationship.
- * This should be used when constructing a subquery query for addition to a parent query.
+ * This should be used when constructing a subquery query for addition to a parent query.
* Objects created with this constructor cannot be added to another object using the subselectQuery method.
* You *must* call selectField(s) before {@link #toSOQL} will return a valid, runnable query.
* @param relationship the ChildRelationship to be used in the FROM Clause of the resultant Query (when set overrides value of table). This sets the value of {@link #relationship} and {@link #table}.
- **/
- private fflib_QueryFactory(Schema.ChildRelationship relationship){
- this(relationship.getChildSObject());
+ **/
+ private fflib_QueryFactory(Schema.ChildRelationship relationship) {
+ this(relationship.getChildSObject());
this.relationship = relationship;
}
/**
- * This method checks to see if the User has Read Access on {@link #table}.
+ * This method checks to see if the User has Read Access on {@link #table}.
* Asserts true if User has access.
**/
- public fflib_QueryFactory assertIsAccessible(){
+ public fflib_QueryFactory assertIsAccessible() {
fflib_SecurityUtils.checkObjectIsReadable(table);
return this;
}
@@ -215,23 +234,22 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
* @param enforce whether to enforce field level security (read)
* @deprecated - use the setEnforceFLS overload that specifies Legacy or Native FLS enforcement
**/
- public fflib_QueryFactory setEnforceFLS(Boolean enforce){
+ public fflib_QueryFactory setEnforceFLS(Boolean enforce) {
return setEnforceFLS(enforce ? FLSEnforcement.LEGACY : FLSEnforcement.NONE);
}
- public fflib_QueryFactory setEnforceFLS(FLSEnforcement enforcement){
+ public fflib_QueryFactory setEnforceFLS(FLSEnforcement enforcement) {
this.mFlsEnforcement = enforcement;
return this;
}
-
/**
* Sets a flag to indicate that this query should have ordered
* query fields in the select statement (this at a small cost to performance).
* If you are processing large query sets, you should switch this off.
* @param doSort whether or not select fields should be sorted in the soql statement.
**/
- public fflib_QueryFactory setSortSelectFields(Boolean doSort){
+ public fflib_QueryFactory setSortSelectFields(Boolean doSort) {
this.sortSelectFields = doSort;
return this;
}
@@ -240,165 +258,168 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
* Selecting fields is idempotent, if this field is already selected calling this method will have no additional impact.
* @param fieldName the API name of the field to add to the query's SELECT clause.
**/
- public fflib_QueryFactory selectField(String fieldName){
- return selectFields(new Set{fieldName});
+ public fflib_QueryFactory selectField(String fieldName) {
+ return selectFields(new Set{ fieldName });
}
/**
- * Selects a single field from the SObject specified in {@link #table}.
- * Selecting fields is idempotent, if this field is already selected calling this method will have no additional impact.
- * @param fieldName the API name of the field to add to the query's SELECT clause.
- * @param relatedSObjectType the related sObjectType to resolve polymorphic object fields.
+ * Selects a single field from the SObject specified in {@link #table}.
+ * Selecting fields is idempotent, if this field is already selected calling this method will have no additional impact.
+ * @param fieldName the API name of the field to add to the query's SELECT clause.
+ * @param relatedSObjectType the related sObjectType to resolve polymorphic object fields.
**/
public fflib_QueryFactory selectField(String fieldName, Schema.sObjectType relatedObjectType) {
addField(getFieldPath(fieldName, relatedObjectType));
return this;
}
-
+
/**
* Selects a field, avoiding the possible ambiguity of String API names.
* @see #selectField(String)
* @param field the {@link Schema.SObjectField} to select with this query.
* @exception InvalidFieldException If the field is null {@code field}.
- **/
- public fflib_QueryFactory selectField(Schema.SObjectField field){
- return selectFields(new Set{field});
+ **/
+ public fflib_QueryFactory selectField(Schema.SObjectField field) {
+ return selectFields(new Set{ field });
}
/**
* Selects multiple fields. This acts the same as calling {@link #selectField(String)} multiple times.
* @param fieldNames the Set of field API names to select.
- **/
- public fflib_QueryFactory selectFields(Set fieldNames){
+ **/
+ public fflib_QueryFactory selectFields(Set fieldNames) {
return selectStringField(fieldNames.iterator());
}
/**
* Selects multiple fields. This acts the same as calling {@link #selectField(String)} multiple times.
* @param fieldNames the List of field API names to select.
- **/
- public fflib_QueryFactory selectFields(List fieldNames){
+ **/
+ public fflib_QueryFactory selectFields(List fieldNames) {
return selectStringField(fieldNames.iterator());
}
-
- private fflib_QueryFactory selectStringField(Iterator iter){
- while( iter.hasNext() ) {
+
+ private fflib_QueryFactory selectStringField(Iterator iter) {
+ while (iter.hasNext()) {
addField(getFieldPath(iter.next()));
}
return this;
}
-
+
/**
* Selects multiple fields. This acts the same as calling {@link #selectField(Schema.SObjectField)} multiple times.
* @param fields the Set of {@link Schema.SObjectField}s to select.
* @exception InvalidFieldException if the fields are null {@code fields}.
- **/
- public fflib_QueryFactory selectFields(Set fields){
+ **/
+ public fflib_QueryFactory selectFields(Set fields) {
return selectSObjectFields(fields.iterator());
}
/**
* Selects multiple fields. This acts the same as calling {@link #selectField(Schema.SObjectField)} multiple times.
* @param fields the List of {@link Schema.SObjectField}s to select.
- * @exception InvalidFieldException if the fields are null {@code fields}.
- **/
+ * @exception InvalidFieldException if the fields are null {@code fields}.
+ **/
public fflib_QueryFactory selectFields(List fields) {
return selectSObjectFields(fields.iterator());
}
- private fflib_QueryFactory selectSObjectFields(Iterator iter){
-
- while( iter.hasNext() ){
+ private fflib_QueryFactory selectSObjectFields(Iterator iter) {
+ while (iter.hasNext()) {
Schema.SObjectField token = iter.next();
- if(token == null) {
+ if (token == null) {
throw new InvalidFieldException();
}
if (mFlsEnforcement == FLSEnforcement.LEGACY) {
fflib_SecurityUtils.checkFieldIsReadable(table, token);
}
- addField( getFieldTokenPath(token) );
+ addField(getFieldTokenPath(token));
}
return this;
}
/**
* @see #selectFieldSet(Schema.FieldSet,Boolean)
- **/
- public fflib_QueryFactory selectFieldSet(Schema.FieldSet fieldSet){
- return selectFieldSet(fieldSet,true);
+ **/
+ public fflib_QueryFactory selectFieldSet(Schema.FieldSet fieldSet) {
+ return selectFieldSet(fieldSet, true);
}
/**
* This is equivalent to iterating the fields in the field set and calling {@link #selectField(String)} on each.
- * @param fieldSet Select all fields included in the field set.
+ * @param fieldSet Select all fields included in the field set.
* @param allowCrossObject if false this method will throw an exception if any fields in the field set reference fields on a related record.
- * @exception InvalidFieldSetException if the fieldset is invalid for table {@code fields}.
- **/
- public fflib_QueryFactory selectFieldSet(Schema.FieldSet fieldSet, Boolean allowCrossObject){
- if(fieldSet.getSObjectType() != table)
- throw new InvalidFieldSetException('Field set "'+fieldSet.getName()+'" is not for SObject type "'+table+'"');
- for(Schema.FieldSetMember field: fieldSet.getFields()){
- if(!allowCrossObject && field.getFieldPath().contains('.'))
- throw new InvalidFieldSetException('Cross-object fields not allowed and field "'+field.getFieldPath()+'"" is a cross-object field.');
- addField( getFieldPath(field.getFieldPath()) );
+ * @exception InvalidFieldSetException if the fieldset is invalid for table {@code fields}.
+ **/
+ public fflib_QueryFactory selectFieldSet(Schema.FieldSet fieldSet, Boolean allowCrossObject) {
+ if (fieldSet.getSObjectType() != table)
+ throw new InvalidFieldSetException(
+ 'Field set "' + fieldSet.getName() + '" is not for SObject type "' + table + '"'
+ );
+ for (Schema.FieldSetMember field : fieldSet.getFields()) {
+ if (!allowCrossObject && field.getFieldPath().contains('.'))
+ throw new InvalidFieldSetException(
+ 'Cross-object fields not allowed and field "' + field.getFieldPath() + '"" is a cross-object field.'
+ );
+ addField(getFieldPath(field.getFieldPath()));
}
return this;
}
-
- private void addField(String fieldPath){
+
+ private void addField(String fieldPath) {
/** With the introduction of SYSTEM_MODE and USER_MODE, it no longer became necessary to
- * use DescribeFieldResult methods to resolve a selected field back to its canonical case-preserving
+ * use DescribeFieldResult methods to resolve a selected field back to its canonical case-preserving
* field definition. The consequence is that duplicate fields could be introduced into the SELECT
* clause if, for instance, the Apex code called "selectField('annualrevenue')" but that same AnnualRevenue
* field were included via a Field Set and the FieldSetMember.getFieldPath() returns "AnnualRevenue"
* So, in the cases where we're using USER_MODE or SYSTEM_MODE, we need to downcase all of the fields in the Set
*/
- if(mFlsEnforcement == FLSEnforcement.SYSTEM_MODE || mFlsEnforcement == FLSEnforcement.USER_MODE){
+ if (mFlsEnforcement == FLSEnforcement.SYSTEM_MODE || mFlsEnforcement == FLSEnforcement.USER_MODE) {
fieldPath = fieldPath.toLowerCase();
}
this.fields.add(fieldPath);
}
-
+
/**
* @param conditionExpression Sets the WHERE clause to the string provided. Do not include the "WHERE".
- **/
- public fflib_QueryFactory setCondition(String conditionExpression){
+ **/
+ public fflib_QueryFactory setCondition(String conditionExpression) {
this.conditionExpression = conditionExpression;
return this;
}
/**
* @returns the current value of the WHERE clause, if any, as set by {@link #setCondition}
- **/
- public String getCondition(){
+ **/
+ public String getCondition() {
return this.conditionExpression;
}
/**
* @param limitCount if not null causes a LIMIT clause to be added to the resulting query.
- **/
- public fflib_QueryFactory setLimit(Integer limitCount){
+ **/
+ public fflib_QueryFactory setLimit(Integer limitCount) {
this.limitCount = limitCount;
return this;
}
/**
* @returns the current value of the LIMIT clause, if any.
- **/
- public Integer getLimit(){
+ **/
+ public Integer getLimit() {
return this.limitCount;
}
/**
* @param offsetCount if not null causes a OFFSET clause to be added to the resulting query.
- **/
- public fflib_QueryFactory setOffset(Integer offsetCount){
+ **/
+ public fflib_QueryFactory setOffset(Integer offsetCount) {
this.offsetCount = offsetCount;
return this;
}
/**
* @returns the current value of the OFFSET clause, if any.
- **/
- public Integer getOffset(){
+ **/
+ public Integer getOffset() {
return this.offsetCount;
}
/**
* @param o an instance of {@link fflib_QueryFactory.Ordering} to be added to the query's ORDER BY clause.
- **/
- public fflib_QueryFactory addOrdering(Ordering o){
+ **/
+ public fflib_QueryFactory addOrdering(Ordering o) {
this.order.add(o);
return this;
}
@@ -406,21 +427,21 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
/**
* @param o an instance of {@link fflib_QueryFactory.Ordering} to remove all existing (for instance defaults) and be added to the query's ORDER BY clause.
**/
- public fflib_QueryFactory setOrdering(Ordering o){
+ public fflib_QueryFactory setOrdering(Ordering o) {
this.order = new List{ o };
return this;
}
/**
* @returns the list of orderings that will be used as the query's ORDER BY clause. You may remove elements from the returned list, or otherwise mutate it, to remove previously added orderings.
- **/
- public List getOrderings(){
+ **/
+ public List getOrderings() {
return this.order;
}
/**
* @returns the selected fields
**/
- public Set getSelectedFields() {
+ public Set getSelectedFields() {
return this.fields;
}
@@ -428,11 +449,14 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
* If not, a new one will be created and returned.
* @deprecated Replaced by {@link #subselectQuery(String relationshipName)} and {@link #subselectQuery(ChildRelationship relationship)}
- * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
+ * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
* @param related The related object type
- **/
- public fflib_QueryFactory subselectQuery(SObjectType related){
- System.debug(LoggingLevel.WARN, 'fflib_QueryFactory.subselectQuery(Schema.SObjectType) is deprecated and will be removed in a future release. Use fflib_QueryFactory.subselectQuery(String) or fflib_QueryFactory.subselectQuery(ChildRelationship) instead.');
+ **/
+ public fflib_QueryFactory subselectQuery(SObjectType related) {
+ System.debug(
+ LoggingLevel.WARN,
+ 'fflib_QueryFactory.subselectQuery(Schema.SObjectType) is deprecated and will be removed in a future release. Use fflib_QueryFactory.subselectQuery(String) or fflib_QueryFactory.subselectQuery(ChildRelationship) instead.'
+ );
return setSubselectQuery(getChildRelationship(related), false);
}
@@ -440,81 +464,89 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
* If not, a new one will be created and returned.
* @deprecated Replaced by {@link #subselectQuery(String relationshipName, Boolean assertIsAccessible)} and {@link #subselectQuery(ChildRelationship relationship, Boolean assertIsAccessible)}
- * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
+ * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
* @param related The related object type
* @param assertIsAccessible indicates whether to check if the user has access to the subquery object
- **/
- public fflib_QueryFactory subselectQuery(SObjectType related, Boolean assertIsAccessible){
- System.debug(LoggingLevel.WARN, 'fflib_QueryFactory.subselectQuery(Schema.SObjectType, Boolean) is deprecated and will be removed in a future release. Use fflib_QueryFactory.subselectQuery(String, Boolean) or fflib_QueryFactory.subselectQuery(ChildRelationship, Boolean) instead.');
+ **/
+ public fflib_QueryFactory subselectQuery(SObjectType related, Boolean assertIsAccessible) {
+ System.debug(
+ LoggingLevel.WARN,
+ 'fflib_QueryFactory.subselectQuery(Schema.SObjectType, Boolean) is deprecated and will be removed in a future release. Use fflib_QueryFactory.subselectQuery(String, Boolean) or fflib_QueryFactory.subselectQuery(ChildRelationship, Boolean) instead.'
+ );
return setSubselectQuery(getChildRelationship(related), assertIsAccessible);
}
/**
* Add a subquery query to this query. If a subquery for this relationshipName already exists, it will be returned.
* If not, a new one will be created and returned.
- * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
+ * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
* @param relationshipName The relationshipName to be added as a subquery
- **/
- public fflib_QueryFactory subselectQuery(String relationshipName){
+ **/
+ public fflib_QueryFactory subselectQuery(String relationshipName) {
return subselectQuery(relationshipName, false);
}
/**
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
* If not, a new one will be created and returned.
- * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
+ * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
* @param relationshipName The relationshipName to be added as a subquery
* @param assertIsAccessible indicates whether to check if the user has access to the subquery object
- **/
- public fflib_QueryFactory subselectQuery(String relationshipName, Boolean assertIsAccessible){
+ **/
+ public fflib_QueryFactory subselectQuery(String relationshipName, Boolean assertIsAccessible) {
Schema.ChildRelationship relationship = getChildRelationship(relationshipName);
if (relationship != null) {
return setSubselectQuery(relationship, assertIsAccessible);
}
- throw new InvalidSubqueryRelationshipException('Invalid call to subselectQuery with relationshipName = '+relationshipName +'. Relationship does not exist for ' + table.getDescribe().getName());
+ throw new InvalidSubqueryRelationshipException(
+ 'Invalid call to subselectQuery with relationshipName = ' +
+ relationshipName +
+ '. Relationship does not exist for ' +
+ table.getDescribe().getName()
+ );
}
/**
* Add a subquery query to this query. If a subquery for this relationshipName already exists, it will be returned.
* If not, a new one will be created and returned.
- * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
+ * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
* @param relationship The ChildRelationship to be added as a subquery
- **/
- public fflib_QueryFactory subselectQuery(Schema.ChildRelationship relationship){
+ **/
+ public fflib_QueryFactory subselectQuery(Schema.ChildRelationship relationship) {
return subselectQuery(relationship, false);
}
/**
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
* If not, a new one will be created and returned.
- * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
+ * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
* @param relationship The ChildRelationship to be added as a subquery
* @param assertIsAccessible indicates whether to check if the user has access to the subquery object
- **/
- public fflib_QueryFactory subselectQuery(Schema.ChildRelationship relationship, Boolean assertIsAccessible){
+ **/
+ public fflib_QueryFactory subselectQuery(Schema.ChildRelationship relationship, Boolean assertIsAccessible) {
return setSubselectQuery(relationship, assertIsAccessible);
}
/**
* Add a subquery query to this query. If a subquery for this relationship already exists, it will be returned.
* If not, a new one will be created and returned.
- * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
+ * @exception InvalidSubqueryRelationshipException If this method is called on a subselectQuery or with an invalid relationship
* @param relationship The ChildRelationship to be added as a subquery
- **/
- private fflib_QueryFactory setSubselectQuery(Schema.ChildRelationship relationship, Boolean assertIsAccessible){
- if (this.subselectQueryMap == null){
+ **/
+ private fflib_QueryFactory setSubselectQuery(Schema.ChildRelationship relationship, Boolean assertIsAccessible) {
+ if (this.subselectQueryMap == null) {
this.subselectQueryMap = new Map();
}
- if (this.subselectQueryMap.containsKey(relationship)){
+ if (this.subselectQueryMap.containsKey(relationship)) {
return subselectQueryMap.get(relationship);
}
-
+
fflib_QueryFactory subSelectQuery = new fflib_QueryFactory(relationship);
-
+
//The child queryFactory should be configured in the same way as the parent by default - can override after if required
subSelectQuery.setSortSelectFields(sortSelectFields);
- if(assertIsAccessible){
+ if (assertIsAccessible) {
subSelectQuery.assertIsAccessible();
}
subselectQueryMap.put(relationship, subSelectQuery);
@@ -523,115 +555,109 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
/**
* @returns the list of subquery instances of fflib_QueryFactory which will be added to the SOQL as relationship/child/sub-queries.
- **/
- public List getSubselectQueries(){
+ **/
+ public List getSubselectQueries() {
if (subselectQueryMap != null) {
return subselectQueryMap.values();
- }
+ }
return null;
}
/**
* Get the ChildRelationship from the Table for the object type passed in.
* @param objType The object type of the child relationship to get
- **/
- private Schema.ChildRelationship getChildRelationship(SObjectType objType){
- for (Schema.ChildRelationship childRow : table.getDescribe().getChildRelationships()){
- //occasionally on some standard objects (Like Contact child of Contact) do not have a relationship name.
- //if there is no relationship name, we cannot query on it, so throw an exception.
- if (childRow.getChildSObject() == objType && childRow.getRelationshipName() != null){
- return childRow;
- }
- }
- throw new InvalidSubqueryRelationshipException('Invalid call to subselectQuery. Invalid relationship for table '+table + ' and objtype='+objType);
- }
+ **/
+ private Schema.ChildRelationship getChildRelationship(SObjectType objType) {
+ for (Schema.ChildRelationship childRow : table.getDescribe().getChildRelationships()) {
+ //occasionally on some standard objects (Like Contact child of Contact) do not have a relationship name.
+ //if there is no relationship name, we cannot query on it, so throw an exception.
+ if (childRow.getChildSObject() == objType && childRow.getRelationshipName() != null) {
+ return childRow;
+ }
+ }
+ throw new InvalidSubqueryRelationshipException(
+ 'Invalid call to subselectQuery. Invalid relationship for table ' + table + ' and objtype=' + objType
+ );
+ }
/**
* Get the ChildRelationship from the Table for the relationship name passed in.
* @param relationshipName The name of the object's ChildRelationship on get
- **/
- private Schema.ChildRelationship getChildRelationship(String relationshipName){
- for (Schema.ChildRelationship childRow : table.getDescribe().getChildRelationships()){
- if (childRow.getRelationshipName() == relationshipName){
- return childRow;
- }
- }
- return null;
- }
-
- /**
- * Add a field to be sorted on. This may be a direct field or a field
+ **/
+ private Schema.ChildRelationship getChildRelationship(String relationshipName) {
+ for (Schema.ChildRelationship childRow : table.getDescribe().getChildRelationships()) {
+ if (childRow.getRelationshipName() == relationshipName) {
+ return childRow;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Add a field to be sorted on. This may be a direct field or a field
* related through an object lookup or master-detail relationship.
* Use the set to store unique field names, since we only want to sort
* by the same field one time. The sort expressions are stored in a list
* so that they are applied to the SOQL in the same order that they
- * were added in.
+ * were added in.
* @param fieldName The string value of the field to be sorted on
* @param direction the direction to be sorted on (ASCENDING or DESCENDING)
* @param nullsLast whether to sort null values last (NULLS LAST keyword included).
- **/
- public fflib_QueryFactory addOrdering(String fieldName, SortOrder direction, Boolean nullsLast){
- order.add(
- new Ordering(getFieldPath(fieldName), direction, nullsLast)
- );
+ **/
+ public fflib_QueryFactory addOrdering(String fieldName, SortOrder direction, Boolean nullsLast) {
+ order.add(new Ordering(getFieldPath(fieldName), direction, nullsLast));
return this;
- }
+ }
- /**
- * Add a field to be sorted on. This may be a direct field or a field
+ /**
+ * Add a field to be sorted on. This may be a direct field or a field
* related through an object lookup or master-detail relationship.
* Use the set to store unique field names, since we only want to sort
* by the same field one time. The sort expressions are stored in a list
* so that they are applied to the SOQL in the same order that they
- * were added in.
+ * were added in.
* @param field The SObjectField to sort. This can only be a direct reference.
* @param direction the direction to be sorted on (ASCENDING or DESCENDING)
* @param nullsLast whether to sort null values last (NULLS LAST keyword included).
- **/
- public fflib_QueryFactory addOrdering(SObjectField field, SortOrder direction, Boolean nullsLast){
- order.add(
- new Ordering(getFieldTokenPath(field), direction, nullsLast)
- );
+ **/
+ public fflib_QueryFactory addOrdering(SObjectField field, SortOrder direction, Boolean nullsLast) {
+ order.add(new Ordering(getFieldTokenPath(field), direction, nullsLast));
return this;
- }
+ }
- /**
- * Add a field to be sorted on. This may be a direct field or a field
+ /**
+ * Add a field to be sorted on. This may be a direct field or a field
* related through an object lookup or master-detail relationship.
* Use the set to store unique field names, since we only want to sort
* by the same field one time. The sort expressions are stored in a list
* so that they are applied to the SOQL in the same order that they
- * were added in.
- * The "NULLS FIRST" keywords will be included by default. If "NULLS LAST"
+ * were added in.
+ * The "NULLS FIRST" keywords will be included by default. If "NULLS LAST"
* is required, use one of the overloaded addOrdering methods which include this parameter.
* @param fieldName The string value of the field to be sorted on
* @param direction the direction to be sorted on (ASCENDING or DESCENDING)
- **/
- public fflib_QueryFactory addOrdering(String fieldName, SortOrder direction){
- order.add(
- new Ordering(getFieldPath(fieldName), direction)
- );
+ **/
+ public fflib_QueryFactory addOrdering(String fieldName, SortOrder direction) {
+ order.add(new Ordering(getFieldPath(fieldName), direction));
return this;
- }
+ }
- /**
- * Add a field to be sorted on. This may be a direct field or a field
+ /**
+ * Add a field to be sorted on. This may be a direct field or a field
* related through an object lookup or master-detail relationship.
* Use the set to store unique field names, since we only want to sort
* by the same field one time. The sort expressions are stored in a list
* so that they are applied to the SOQL in the same order that they
- * were added in.
- * The "NULLS FIRST" keywords will be included by default. If "NULLS LAST"
+ * were added in.
+ * The "NULLS FIRST" keywords will be included by default. If "NULLS LAST"
* is required, use one of the overloaded addOrdering methods which include this parameter.
* @param field The SObjectField to sort. This can only be a direct reference.
* @param direction the direction to be sorted on (ASCENDING or DESCENDING)
- **/
- public fflib_QueryFactory addOrdering(SObjectField field, SortOrder direction){
- order.add(
- new Ordering(getFieldTokenPath(field), direction)
- );
+ **/
+ public fflib_QueryFactory addOrdering(SObjectField field, SortOrder direction) {
+ order.add(new Ordering(getFieldTokenPath(field), direction));
return this;
- }
+ }
/**
* Remove existing ordering and set a field to be sorted on. This may be a direct field or a field
@@ -643,8 +669,8 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
* @param fieldName The string value of the field to be sorted on
* @param direction the direction to be sorted on (ASCENDING or DESCENDING)
* @param nullsLast whether to sort null values last (NULLS LAST keyword included).
- **/
- public fflib_QueryFactory setOrdering(String fieldName, SortOrder direction, Boolean nullsLast){
+ **/
+ public fflib_QueryFactory setOrdering(String fieldName, SortOrder direction, Boolean nullsLast) {
Ordering ordr = new Ordering(getFieldPath(fieldName), direction, nullsLast);
return setOrdering(ordr);
}
@@ -659,8 +685,8 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
* @param field The SObjectField to sort. This can only be a direct reference.
* @param direction the direction to be sorted on (ASCENDING or DESCENDING)
* @param nullsLast whether to sort null values last (NULLS LAST keyword included).
- **/
- public fflib_QueryFactory setOrdering(SObjectField field, SortOrder direction, Boolean nullsLast){
+ **/
+ public fflib_QueryFactory setOrdering(SObjectField field, SortOrder direction, Boolean nullsLast) {
Ordering ordr = new Ordering(getFieldTokenPath(field), direction, nullsLast);
return setOrdering(ordr);
}
@@ -674,8 +700,8 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
* were added in.
* @param fieldName The string value of the field to be sorted on
* @param direction the direction to be sorted on (ASCENDING or DESCENDING)
- **/
- public fflib_QueryFactory setOrdering(String fieldName, SortOrder direction){
+ **/
+ public fflib_QueryFactory setOrdering(String fieldName, SortOrder direction) {
Ordering ordr = new Ordering(getFieldPath(fieldName), direction);
return setOrdering(ordr);
}
@@ -689,16 +715,16 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
* were added in.
* @param field The SObjectField to sort. This can only be a direct reference.
* @param direction the direction to be sorted on (ASCENDING or DESCENDING)
- **/
- public fflib_QueryFactory setOrdering(SObjectField field, SortOrder direction){
+ **/
+ public fflib_QueryFactory setOrdering(SObjectField field, SortOrder direction) {
Ordering ordr = new Ordering(getFieldTokenPath(field), direction);
return setOrdering(ordr);
}
/**
* whether an ALL ROWS clause will be added to the resulting query
- **/
- public fflib_QueryFactory setAllRows(){
+ **/
+ public fflib_QueryFactory setAllRows() {
this.allRows = true;
return this;
}
@@ -706,58 +732,58 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
/**
* Convert the values provided to this instance into a full SOQL string for use with Database.query
* Check to see if subqueries queries need to be added after the field list.
- **/
- public String toSOQL(){
+ **/
+ public String toSOQL() {
String result = 'SELECT ';
//if no fields have been added, just add the Id field so that the query or subquery will not just fail
- if (fields.size() == 0){
- if (mFlsEnforcement == FLSEnforcement.LEGACY){
+ if (fields.size() == 0) {
+ if (mFlsEnforcement == FLSEnforcement.LEGACY) {
fflib_SecurityUtils.checkFieldIsReadable(table, 'Id');
}
result += 'Id';
- }else {
+ } else {
List fieldsToQuery = new List(fields);
-
- if(sortSelectFields){
- fieldsToQuery.sort();
- }
-
- result += String.join(fieldsToQuery,', ');
+
+ if (sortSelectFields) {
+ fieldsToQuery.sort();
+ }
+
+ result += String.join(fieldsToQuery, ', ');
}
-
- if(subselectQueryMap != null && !subselectQueryMap.isEmpty()){
- for (fflib_QueryFactory childRow : subselectQueryMap.values()){
+
+ if (subselectQueryMap != null && !subselectQueryMap.isEmpty()) {
+ for (fflib_QueryFactory childRow : subselectQueryMap.values()) {
result += ', (' + childRow.toSOQL() + ') ';
- }
+ }
}
- result += ' FROM ' + (relationship != null ? relationship.getRelationshipName() : table.getDescribe().getName());
+ result +=
+ ' FROM ' + (relationship != null ? relationship.getRelationshipName() : table.getDescribe().getName());
- if(conditionExpression != null) {
+ if (conditionExpression != null) {
result += ' WHERE ' + conditionExpression;
}
//Subselects can't specify USER_MODE or SYSTEM_MODE -- only the top-level query can do so
- if(relationship == null && mFlsEnforcement == FLSEnforcement.USER_MODE){
+ if (relationship == null && mFlsEnforcement == FLSEnforcement.USER_MODE) {
result += ' WITH USER_MODE';
- }
- else if(relationship == null && mFlsEnforcement == FLSEnforcement.SYSTEM_MODE){
+ } else if (relationship == null && mFlsEnforcement == FLSEnforcement.SYSTEM_MODE) {
result += ' WITH SYSTEM_MODE';
}
- if(order.size() > 0){
+ if (order.size() > 0) {
result += ' ORDER BY ';
- for(Ordering o:order)
- result += o.toSOQL() +', ';
- result = result.substring(0,result.length()-2);
+ for (Ordering o : order)
+ result += o.toSOQL() + ', ';
+ result = result.substring(0, result.length() - 2);
}
-
- if(limitCount != null)
- result += ' LIMIT '+limitCount;
-
- if(offsetCount != null)
- result += ' OFFSET '+offsetCount;
-
- if(allRows) {
+
+ if (limitCount != null)
+ result += ' LIMIT ' + limitCount;
+
+ if (offsetCount != null)
+ result += ' OFFSET ' + offsetCount;
+
+ if (allRows) {
result += ' ALL ROWS';
}
@@ -767,9 +793,8 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
/**
* Create a "deep" clone of this object that can be safely mutated without affecting the cloned instance
* @return a deep clone of this fflib_QueryFactory
- **/
- public fflib_QueryFactory deepClone(){
-
+ **/
+ public fflib_QueryFactory deepClone() {
fflib_QueryFactory clone = new fflib_QueryFactory(this.table)
.setLimit(this.limitCount)
.setOffset(this.offsetCount)
@@ -777,9 +802,9 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
.setEnforceFLS(this.mFlsEnforcement);
Map subqueries = this.subselectQueryMap;
- if(subqueries != null) {
+ if (subqueries != null) {
Map clonedSubqueries = new Map();
- for(Schema.ChildRelationship key : subqueries.keySet()) {
+ for (Schema.ChildRelationship key : subqueries.keySet()) {
clonedSubqueries.put(key, subqueries.get(key).deepClone());
}
clone.subselectQueryMap = clonedSubqueries;
@@ -791,62 +816,63 @@ public class fflib_QueryFactory { //No explicit sharing declaration - inherit fr
return clone;
}
-
- public class Ordering{
+
+ public class Ordering {
private SortOrder direction;
private boolean nullsLast;
private String field;
- public Ordering(String sobjType, String fieldName, SortOrder direction){
- this(
- fflib_SObjectDescribe.getDescribe(sobjType).getField(fieldName),
- direction
- );
+ public Ordering(String sobjType, String fieldName, SortOrder direction) {
+ this(fflib_SObjectDescribe.getDescribe(sobjType).getField(fieldName), direction);
}
/**
* Construct a new ordering instance for use with {@link fflib_QueryFactory#addOrdering}
* Once constructed it's properties may not be modified.
- **/
- public Ordering(Schema.SObjectField field, SortOrder direction){
+ **/
+ public Ordering(Schema.SObjectField field, SortOrder direction) {
this(fflib_QueryFactory.getFieldTokenPath(field), direction, false); //SOQL docs state NULLS FIRST is default behavior
}
- public Ordering(Schema.SObjectField field, SortOrder direction, Boolean nullsLast){
+ public Ordering(Schema.SObjectField field, SortOrder direction, Boolean nullsLast) {
this(fflib_QueryFactory.getFieldTokenPath(field), direction, nullsLast);
}
@TestVisible
- private Ordering(String field, SortOrder direction){
+ private Ordering(String field, SortOrder direction) {
this(field, direction, false);
}
@TestVisible
- private Ordering(String field, SortOrder direction, Boolean nullsLast){
+ private Ordering(String field, SortOrder direction, Boolean nullsLast) {
this.direction = direction;
this.field = field;
this.nullsLast = nullsLast;
}
- public String getField(){
+ public String getField() {
return this.field;
}
- public SortOrder getDirection(){
+ public SortOrder getDirection() {
return direction;
}
- public String toSOQL(){
- return field + ' ' + (direction == SortOrder.ASCENDING ? 'ASC' : 'DESC') + (nullsLast ? ' NULLS LAST ' : ' NULLS FIRST ');
+ public String toSOQL() {
+ return field +
+ ' ' +
+ (direction == SortOrder.ASCENDING ? 'ASC' : 'DESC') +
+ (nullsLast ? ' NULLS LAST ' : ' NULLS FIRST ');
}
}
-
-
- public class InvalidFieldException extends Exception{
+ public class InvalidFieldException extends Exception {
private String fieldName;
private Schema.SObjectType objectType;
- public InvalidFieldException(String fieldName, Schema.SObjectType objectType){
+ public InvalidFieldException(String fieldName, Schema.SObjectType objectType) {
this.objectType = objectType;
this.fieldName = fieldName;
- this.setMessage( 'Invalid field \''+fieldName+'\' for object \''+objectType+'\'' );
+ this.setMessage('Invalid field \'' + fieldName + '\' for object \'' + objectType + '\'');
}
}
- public class InvalidFieldSetException extends Exception{}
- public class NonReferenceFieldException extends Exception{}
- public class InvalidSubqueryRelationshipException extends Exception{}
+ public class InvalidFieldSetException extends Exception {
+ }
+ public class NonReferenceFieldException extends Exception {
+ }
+ public class InvalidSubqueryRelationshipException extends Exception {
+ }
}
diff --git a/sfdx-source/apex-common/main/classes/fflib_SObjectDescribe.cls b/sfdx-source/apex-common/main/classes/fflib_SObjectDescribe.cls
index 0eac50185f0..078f9f1b51d 100644
--- a/sfdx-source/apex-common/main/classes/fflib_SObjectDescribe.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_SObjectDescribe.cls
@@ -2,27 +2,27 @@
* Copyright (c), FinancialForce.com, inc
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification,
+ * 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 copyright notice,
+ * - Redistributions of source code must retain the above copyright 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
+ * - 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 FinancialForce.com, inc nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
+ * - Neither the name of the FinancialForce.com, inc 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,
+ * 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.
-**/
+ **/
/**
* fflib_SObjectDescribe is a semi-intelligent wrapper for standard apex Schema methods.
@@ -30,43 +30,43 @@
* as well as wrapper classes and methods to make common tasks like working with relationship field name oddities
* as well namespace handling.
*
- * Of particular note for use in contexts that may be released as managed packages are the #getFields and get #getGlobalDescribe methods
+ * Of particular note for use in contexts that may be released as managed packages are the #getFields and get #getGlobalDescribe methods
* These return special immutable wrapper objects that automatically imply the current namespace (detected as the one this class is contained in)
* and allow an older API style of omitting the namespace when working with fields or global describe maps.
* This allows both upgrading old code to APIv29 by making use of these as a nearly drop in replacement, as well as keeping
* namespace detection logic encapsulated.
-**/
+ **/
public class fflib_SObjectDescribe {
//internal implementation details
private Schema.SObjectType token;
private Schema.SObjectField nameField;
private Schema.DescribeSObjectResult describe { //lazy load - keep this lightweight until we need more data
- get{
- if(describe == null)
+ get {
+ if (describe == null)
describe = token.getDescribe();
return describe;
}
set;
}
- private Map fields {
- get{
- if(fields == null)
+ private Map fields {
+ get {
+ if (fields == null)
fields = describe.fields.getMap();
return fields;
}
set;
}
- private Map fieldSets {
- get{
- if(fieldSets == null)
+ private Map fieldSets {
+ get {
+ if (fieldSets == null)
fieldSets = describe.fieldSets.getMap();
return fieldSets;
}
set;
}
private FieldsMap wrappedFields {
- get{
- if(wrappedFields == null){
+ get {
+ if (wrappedFields == null) {
wrappedFields = new FieldsMap(this.fields);
}
return wrappedFields;
@@ -74,58 +74,56 @@ public class fflib_SObjectDescribe {
set;
}
- private fflib_SObjectDescribe(Schema.SObjectType token){
- if(token == null)
+ private fflib_SObjectDescribe(Schema.SObjectType token) {
+ if (token == null)
throw new InvalidDescribeException('Invalid SObject type: null');
this.token = token;
- instanceCache.put( String.valueOf(token).toLowerCase() , this);
+ instanceCache.put(String.valueOf(token).toLowerCase(), this);
}
//public instace methods
/**
* Returns the Schema.SObjectType this fflib_SObjectDescribe instance is based on.
- **/
- public Schema.SObjectType getSObjectType(){
+ **/
+ public Schema.SObjectType getSObjectType() {
return token;
}
/**
* This method is a convenient shorthand for calling getField(name, true)
- **/
- public Schema.SObjectField getField(String name){
+ **/
+ public Schema.SObjectField getField(String name) {
return this.getField(name, true);
}
/**
* This method provides a simplified shorthand for calling #getFields and getting the provided field.
* Additionally it handles finding the correct SObjectField for relationship notation,
* e.g. getting the Account field on Contact would fail without being referenced as AccountId - both work here.
- **/
- public Schema.SObjectField getField(String fieldName, Boolean implyNamespace){
+ **/
+ public Schema.SObjectField getField(String fieldName, Boolean implyNamespace) {
String fieldNameAdjusted = fieldName;
- if ( fieldName.endsWithIgnoreCase('__r') ) //resolve custom field cross-object (__r) syntax
- {
+ if (fieldName.endsWithIgnoreCase('__r')) {
+ //resolve custom field cross-object (__r) syntax
fieldNameAdjusted = fieldName.removeEndIgnoreCase('__r') + '__c';
- }
- else if ( fieldName.endsWithIgnoreCase('__pr') ) //resolve custom field cross-object (__pr) syntax for person accounts
- {
+ } else if (fieldName.endsWithIgnoreCase('__pr')) {
+ //resolve custom field cross-object (__pr) syntax for person accounts
fieldNameAdjusted = fieldName.removeEndIgnoreCase('__pr') + '__pc';
}
- Schema.SObjectField result = wrappedFields.get( fieldNameAdjusted, implyNamespace );
- if(result == null){
- result = wrappedFields.get(fieldName+'Id', implyNamespace); //in case it's a standard lookup in cross-object format
+ Schema.SObjectField result = wrappedFields.get(fieldNameAdjusted, implyNamespace);
+ if (result == null) {
+ result = wrappedFields.get(fieldName + 'Id', implyNamespace); //in case it's a standard lookup in cross-object format
}
return result;
}
-
+
/**
- * Returns the field where isNameField() is true (if any); otherwise returns null
- **/
- public Schema.SObjectField getNameField()
- {
- if(nameField == null) {
- for(Schema.SObjectField field : wrappedFields.values()) {
- if(field.getDescribe().isNameField()) {
+ * Returns the field where isNameField() is true (if any); otherwise returns null
+ **/
+ public Schema.SObjectField getNameField() {
+ if (nameField == null) {
+ for (Schema.SObjectField field : wrappedFields.values()) {
+ if (field.getDescribe().isNameField()) {
nameField = field;
break;
}
@@ -133,40 +131,38 @@ public class fflib_SObjectDescribe {
}
return nameField;
}
-
+
/**
* Returns the raw Schema.DescribeSObjectResult an fflib_SObjectDescribe instance wraps.
- **/
- public Schema.DescribeSObjectResult getDescribe(){
+ **/
+ public Schema.DescribeSObjectResult getDescribe() {
return describe;
}
/**
* This method returns the raw data and provides no namespace handling.
- * Due to this, __use of this method is discouraged__ in favor of getFields().
- **/
- public Map getFieldsMap(){
+ * Due to this, __use of this method is discouraged__ in favor of getFields().
+ **/
+ public Map getFieldsMap() {
return fields;
}
- public FieldsMap getFields(){
+ public FieldsMap getFields() {
return wrappedFields;
}
- public Map getFieldSetsMap(){
+ public Map getFieldSetsMap() {
return fieldSets;
}
-
-
- private static Map rawGlobalDescribe {
- get{
- if(rawGlobalDescribe == null)
+ private static Map rawGlobalDescribe {
+ get {
+ if (rawGlobalDescribe == null)
rawGlobalDescribe = Schema.getGlobalDescribe();
return rawGlobalDescribe;
}
set;
}
- private static GlobalDescribeMap wrappedGlobalDescribe{
- get{
- if(wrappedGlobalDescribe == null){
+ private static GlobalDescribeMap wrappedGlobalDescribe {
+ get {
+ if (wrappedGlobalDescribe == null) {
wrappedGlobalDescribe = new GlobalDescribeMap(rawGlobalDescribe);
}
return wrappedGlobalDescribe;
@@ -177,139 +173,144 @@ public class fflib_SObjectDescribe {
* This is used to cache fflib_SObjectDescribe instances as they're constructed
* to prevent repeatedly re-constructing the same type.
* These instances are not guaranteed to be, but typically will be, unique per sObject type due to the presence of flushCache.
- **/
- private static Map instanceCache {get{
- if(instanceCache == null)
- instanceCache = new Map();
+ **/
+ private static Map instanceCache {
+ get {
+ if (instanceCache == null)
+ instanceCache = new Map();
return instanceCache;
- }
+ }
set;
}
- public static fflib_SObjectDescribe getDescribe(String sObjectName){
- if(String.isBlank(sObjectName))
+ public static fflib_SObjectDescribe getDescribe(String sObjectName) {
+ if (String.isBlank(sObjectName))
return null;
fflib_SObjectDescribe result = instanceCache.get(sObjectName.toLowerCase());
- if(result == null){
+ if (result == null) {
Schema.SObjectType token = wrappedGlobalDescribe.get(sObjectName.toLowerCase());
- if(token == null)
+ if (token == null)
result = null;
else
result = new fflib_SObjectDescribe(token);
}
return result;
}
- public static fflib_SObjectDescribe getDescribe(Schema.SObjectType token){
- if(token == null)
+ public static fflib_SObjectDescribe getDescribe(Schema.SObjectType token) {
+ if (token == null)
return null;
fflib_SObjectDescribe result = instanceCache.get(String.valueOf(token).toLowerCase());
- if(result == null)
- result = new fflib_SObjectDescribe(token);
+ if (result == null)
+ result = new fflib_SObjectDescribe(token);
return result;
}
- public static fflib_SObjectDescribe getDescribe(Schema.DescribeSObjectResult nativeDescribe){
- if(nativeDescribe == null)
+ public static fflib_SObjectDescribe getDescribe(Schema.DescribeSObjectResult nativeDescribe) {
+ if (nativeDescribe == null)
return null;
fflib_SObjectDescribe result = instanceCache.get(nativeDescribe.getName().toLowerCase());
- if(result == null)
+ if (result == null)
result = new fflib_SObjectDescribe(nativeDescribe.getSObjectType());
return result;
}
- public static fflib_SObjectDescribe getDescribe(SObject instance){
- if(instance == null)
+ public static fflib_SObjectDescribe getDescribe(SObject instance) {
+ if (instance == null)
return null;
return getDescribe(instance.getSObjectType());
}
//returns the same results as the native method, just with caching built in to avoid limits
- public static Map getRawGlobalDescribe(){
+ public static Map getRawGlobalDescribe() {
return rawGlobalDescribe;
}
- public static GlobalDescribeMap getGlobalDescribe(){
+ public static GlobalDescribeMap getGlobalDescribe() {
return wrappedGlobalDescribe;
}
- //Useful when working in heap space constrained environments.
+ //Useful when working in heap space constrained environments.
//Existing references to SObjectDescribe instances will continue to work.
- public static void flushCache(){
+ public static void flushCache() {
rawGlobalDescribe = null;
instanceCache = null;
}
-
/**
* This class handles emulating a Map's non-mutating instance methods and helps navigate the complex topic of
* handling implicit namespace behavior like pre-APIv29 did, while also allowing fully qualified references.
* Note that this requires the API version of fflib_SObjectDescribe to be 29 or higher to function properly.
- *
+ *
* Due to the lack of language support for covariant return types subclasses are responsible for implementing the get methods.
* A minimal implementation of these would be a cast and returning getObject's result.
- **/
- private abstract class NamespacedAttributeMap{
+ **/
+ private abstract class NamespacedAttributeMap {
@TestVisible
protected String currentNamespace;
- protected Map values;
+ protected Map values;
- protected NamespacedAttributeMap(Map values){
+ protected NamespacedAttributeMap(Map values) {
//namespace detection courtesy http://salesforce.stackexchange.com/a/28977/60
- currentNamespace = fflib_SObjectDescribe.class.getName().substringBefore('fflib_SObjectDescribe').removeEnd('.').toLowerCase();
+ currentNamespace = fflib_SObjectDescribe.class
+ .getName()
+ .substringBefore('fflib_SObjectDescribe')
+ .removeEnd('.')
+ .toLowerCase();
this.values = values;
}
//A no-args constructor to allow subclasses with different constructor signatures
- protected NamespacedAttributeMap(){
- this(new Map());
+ protected NamespacedAttributeMap() {
+ this(new Map());
}
/**
* A convenient shortcut for invoking #getObject(name, true)
- **/
- protected virtual Object getObject(String name){
+ **/
+ protected virtual Object getObject(String name) {
return this.getObject(name, true);
}
/**
- *
- **/
- protected virtual Object getObject(String name, Boolean implyNamespace){
- if(name == null) //short-circuit lookup logic since null can't possibly be a valid field name, and it saves us null checking
+ *
+ **/
+ protected virtual Object getObject(String name, Boolean implyNamespace) {
+ if (
+ name ==
+ null //short-circuit lookup logic since null can't possibly be a valid field name, and it saves us null checking
+ )
return null;
- String preferredValue = ((implyNamespace ? currentNamespace+'__' : '') + name).toLowerCase();
- if(values.containsKey(preferredValue)){
+ String preferredValue = ((implyNamespace ? currentNamespace + '__' : '') + name).toLowerCase();
+ if (values.containsKey(preferredValue)) {
return values.get(preferredValue);
- }else if(implyNamespace){
+ } else if (implyNamespace) {
return values.get(name.toLowerCase());
- }else{
+ } else {
return null;
}
}
- public virtual Boolean containsKey(String name){
+ public virtual Boolean containsKey(String name) {
return this.containsKey(name, true);
}
- public virtual Boolean containsKey(String name, Boolean implyNamespace){
- if(name == null) //short-circuit lookup logic since null can't possibly be a valid field name, and it saves us null checking
+ public virtual Boolean containsKey(String name, Boolean implyNamespace) {
+ if (
+ name ==
+ null //short-circuit lookup logic since null can't possibly be a valid field name, and it saves us null checking
+ )
return null;
- String preferredValue = ((implyNamespace ? currentNamespace+'__' : '') + name).toLowerCase();
- return (
- values.containsKey(preferredValue) ||
- implyNamespace && values.containsKey(name.toLowerCase())
- );
+ String preferredValue = ((implyNamespace ? currentNamespace + '__' : '') + name).toLowerCase();
+ return (values.containsKey(preferredValue) || implyNamespace && values.containsKey(name.toLowerCase()));
}
- public virtual Integer size(){
+ public virtual Integer size() {
return values.size();
}
/**
* Returns the key set of the map.
* Note: unlike other NamespacedAttributeMap methods keySet defaults implyNamespace to false if not specified.
- **/
- public virtual Set keySet(){
+ **/
+ public virtual Set keySet() {
return this.keySet(false);
}
- public virtual Set keySet(Boolean implyNamespace){
- if(implyNamespace){
+ public virtual Set keySet(Boolean implyNamespace) {
+ if (implyNamespace) {
Set result = new Set();
- for(String key:values.keySet()){
- result.add(
- key.removeStartIgnoreCase(currentNamespace+'__')
- );
+ for (String key : values.keySet()) {
+ result.add(key.removeStartIgnoreCase(currentNamespace + '__'));
}
return result;
- }else{
+ } else {
return values.keySet();
}
}
@@ -317,47 +318,47 @@ public class fflib_SObjectDescribe {
/**
* A subclass of NamespacedAttributeMap for handling the data returned by #Schema.DescribeSObjectResult.fields.getMap
- **/
- public class FieldsMap extends NamespacedAttributeMap{
-
+ **/
+ public class FieldsMap extends NamespacedAttributeMap {
@TestVisible
- private FieldsMap(Map values){
+ private FieldsMap(Map values) {
super(values);
}
- public Schema.SObjectField get(String name){
+ public Schema.SObjectField get(String name) {
return this.get(name, true);
}
- public Schema.SObjectField get(String name, Boolean implyNamespace){
+ public Schema.SObjectField get(String name, Boolean implyNamespace) {
return (Schema.SObjectField) this.getObject(name, implyNamespace);
}
- public List values(){
+ public List values() {
return (List) values.values();
}
-
}
/**
* A subclass of NamespacedAttributeMap for handling the data returned by #Schema.getGlobalDescribe
- **/
- public class GlobalDescribeMap extends NamespacedAttributeMap{
+ **/
+ public class GlobalDescribeMap extends NamespacedAttributeMap {
@TestVisible
- private GlobalDescribeMap(Map values){
+ private GlobalDescribeMap(Map values) {
super(values);
}
- public Schema.SObjectType get(String name){
+ public Schema.SObjectType get(String name) {
return this.get(name, true);
}
- public Schema.SObjectType get(String name, Boolean implyNamespace){
+ public Schema.SObjectType get(String name, Boolean implyNamespace) {
return (Schema.SObjectType) this.getObject(name, implyNamespace);
}
- public List values(){
+ public List values() {
return (List) values.values();
}
}
-
- public abstract class DescribeException extends Exception{}
- public class DuplicateDescribeException extends DescribeException{} //Test coverage for this requires APIv28's @testVisible annotation to force exception cases.
- public class InvalidDescribeException extends DescribeException{}
-}
\ No newline at end of file
+ public abstract class DescribeException extends Exception {
+ }
+ public class DuplicateDescribeException extends DescribeException {
+ } //Test coverage for this requires APIv28's @testVisible annotation to force exception cases.
+ public class InvalidDescribeException extends DescribeException {
+ }
+}
diff --git a/sfdx-source/apex-common/main/classes/fflib_SObjectDomain.cls b/sfdx-source/apex-common/main/classes/fflib_SObjectDomain.cls
index bd982249d48..f21ec2a349e 100644
--- a/sfdx-source/apex-common/main/classes/fflib_SObjectDomain.cls
+++ b/sfdx-source/apex-common/main/classes/fflib_SObjectDomain.cls
@@ -2,127 +2,113 @@
* Copyright (c), FinancialForce.com, inc
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification,
+ * 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 copyright notice,
+ * - Redistributions of source code must retain the above copyright 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
+ * - 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 FinancialForce.com, inc nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
+ * - Neither the name of the FinancialForce.com, inc 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,
+ * 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.
-**/
+ **/
/**
* Base class aiding in the implementation of a Domain Model around SObject collections
- *
- * Domain (software engineering). “a set of common requirements, terminology, and functionality
+ *
+ * Domain (software engineering). “a set of common requirements, terminology, and functionality
* for any software program constructed to solve a problem in that field”,
* http://en.wikipedia.org/wiki/Domain_(software_engineering)
*
- * Domain Model, “An object model of the domain that incorporates both behavior and data.”,
+ * Domain Model, “An object model of the domain that incorporates both behavior and data.”,
* “At its worst business logic can be very complex. Rules and logic describe many different "
- * "cases and slants of behavior, and it's this complexity that objects were designed to work with...”
+ * "cases and slants of behavior, and it's this complexity that objects were designed to work with...”
* Martin Fowler, EAA Patterns
* http://martinfowler.com/eaaCatalog/domainModel.html
*
**/
-public virtual with sharing class fflib_SObjectDomain
- extends fflib_SObjects
- implements fflib_ISObjectDomain
-{
+public virtual with sharing class fflib_SObjectDomain extends fflib_SObjects implements fflib_ISObjectDomain {
/**
* Provides access to the data represented by this domain class
**/
public List Records {
- get
- {
+ get {
return getRecords();
}
}
-
/**
- * Provides access to Trigger.oldMap and allowing it to be mocked in unit-tests
- **/
+ * Provides access to Trigger.oldMap and allowing it to be mocked in unit-tests
+ **/
@TestVisible
- protected Map ExistingRecords
- {
- get
- {
- if (ExistingRecords == null)
- {
- if (System.Test.isRunningTest() & Test.Database.hasRecords())
- {
+ protected Map ExistingRecords {
+ get {
+ if (ExistingRecords == null) {
+ if (System.Test.isRunningTest() & Test.Database.hasRecords()) {
// If in test context and records are in the mock database use those instead of Trigger.oldMap
ExistingRecords = Test.Database.oldRecords;
- }
- else
- {
+ } else {
ExistingRecords = Trigger.oldMap;
}
}
return ExistingRecords;
-
}
private set;
}
/**
* Exposes the configuration for this domain class instance
- **/
- public Configuration Configuration {get; private set;}
-
+ **/
+ public Configuration Configuration { get; private set; }
+
/**
* DEPRECATED, This property has been moved to fflib_SObjects
**/
- public static fflib_SObjectDomain.ErrorFactory Errors {get; private set;}
-
+ public static fflib_SObjectDomain.ErrorFactory Errors { get; private set; }
+
/**
* Useful during unit testing to access mock support for database inserts and updates (testing without DML)
**/
- public static TestFactory Test {get; private set;}
-
+ public static TestFactory Test { get; private set; }
+
/**
* Retains instances of domain classes implementing trigger stateful
**/
- private static Map> TriggerStateByClass;
-
+ private static Map> TriggerStateByClass;
+
/**
* Retains the trigger tracking configuration used for each domain
**/
private static Map TriggerEventByClass;
- static
- {
+ static {
Errors = new fflib_SObjectDomain.ErrorFactory();
Test = new TestFactory();
-
+
TriggerStateByClass = new Map>();
TriggerEventByClass = new Map();
}
-
+
/**
* Constructs the domain class with the data on which to apply the behaviour implemented within
*
* @param sObjectList A concrete list (e.g. List vs List) of records
**/
- public fflib_SObjectDomain(List sObjectList)
- {
+ public fflib_SObjectDomain(List sObjectList) {
this(sObjectList, sObjectList.getSObjectType());
}
@@ -135,176 +121,172 @@ public virtual with sharing class fflib_SObjectDomain
* @remark Will support List but all records in the list will be assumed to be of
* the type specified in sObjectType
**/
- public fflib_SObjectDomain(List sObjectList, SObjectType sObjectType)
- {
+ public fflib_SObjectDomain(List sObjectList, SObjectType sObjectType) {
// Ensure the domain class has its own copy of the data
super(sObjectList, sObjectType);
// Configure the Domain object instance
- Configuration = new Configuration();
+ Configuration = new Configuration();
}
-
+
/**
* Override this to apply defaults to the records, this is called by the handleBeforeInsert method
**/
- public virtual void onApplyDefaults() { }
-
+ public virtual void onApplyDefaults() {
+ }
+
/**
* Override this to apply general validation to be performed during insert or update, called by the handleAfterInsert and handleAfterUpdate methods
**/
- public virtual void onValidate() { }
-
+ public virtual void onValidate() {
+ }
+
/**
* Override this to apply validation to be performed during insert, called by the handleAfterUpdate method
**/
- public virtual void onValidate(Map existingRecords) { }
+ public virtual void onValidate(Map existingRecords) {
+ }
/**
* Override this to perform processing during the before insert phase, this is called by the handleBeforeInsert method
**/
- public virtual void onBeforeInsert() { }
-
+ public virtual void onBeforeInsert() {
+ }
+
/**
* Override this to perform processing during the before update phase, this is called by the handleBeforeUpdate method
**/
- public virtual void onBeforeUpdate(Map existingRecords) { }
-
+ public virtual void onBeforeUpdate(Map existingRecords) {
+ }
+
/**
* Override this to perform processing during the before delete phase, this is called by the handleBeforeDelete method
**/
- public virtual void onBeforeDelete() { }
-
+ public virtual void onBeforeDelete() {
+ }
+
/**
* Override this to perform processing during the after insert phase, this is called by the handleAfterInsert method
**/
- public virtual void onAfterInsert() { }
-
+ public virtual void onAfterInsert() {
+ }
+
/**
* Override this to perform processing during the after update phase, this is called by the handleAfterUpdate method
- **/
- public virtual void onAfterUpdate(Map existingRecords) { }
-
+ **/
+ public virtual void onAfterUpdate(Map existingRecords) {
+ }
+
/**
* Override this to perform processing during the after delete phase, this is called by the handleAfterDelete method
- **/
- public virtual void onAfterDelete() { }
-
+ **/
+ public virtual void onAfterDelete() {
+ }
+
/**
* Override this to perform processing during the after undelete phase, this is called by the handleAfterDelete method
- **/
- public virtual void onAfterUndelete() { }
-
+ **/
+ public virtual void onAfterUndelete() {
+ }
+
/**
* Base handler for the Apex Trigger event Before Insert, calls the onApplyDefaults method, followed by onBeforeInsert
**/
- public virtual void handleBeforeInsert()
- {
- onApplyDefaults();
- onBeforeInsert();
- }
-
- /**
- * Base handler for the Apex Trigger event Before Update, calls the onBeforeUpdate method
- **/
- public virtual void handleBeforeUpdate(Map existingRecords)
- {
- onBeforeUpdate(existingRecords);
- }
-
- /**
- * Base handler for the Apex Trigger event Before Delete, calls the onBeforeDelete method
- **/
- public virtual void handleBeforeDelete()
- {
- onBeforeDelete();
- }
-
- /**
- * Base handler for the Apex Trigger event After Insert, checks object security and calls the onValidate and onAfterInsert methods
- *
- * @throws DomainException if the current user context is not able to create records
- **/
- public virtual void handleAfterInsert()
- {
- if(Configuration.EnforcingTriggerCRUDSecurity && !SObjectDescribe.isCreateable())
- throw new DomainException('Permission to create an ' + SObjectDescribe.getName() + ' denied.');
-
- onValidate();
- onAfterInsert();
- }
-
- /**
- * Base handler for the Apex Trigger event After Update, checks object security and calls the onValidate, onValidate(Map) and onAfterUpdate methods
- *
- * @throws DomainException if the current user context is not able to update records
- **/
- public virtual void handleAfterUpdate(Map existingRecords)
- {
- if(Configuration.EnforcingTriggerCRUDSecurity && !SObjectDescribe.isUpdateable())
- throw new DomainException('Permission to update an ' + SObjectDescribe.getName() + ' denied.');
-
- if(Configuration.OldOnUpdateValidateBehaviour)
- onValidate();
- onValidate(existingRecords);
- onAfterUpdate(existingRecords);
- }
-
- /**
- * Base handler for the Apex Trigger event After Delete, checks object security and calls the onAfterDelete method
- *
- * @throws DomainException if the current user context is not able to delete records
- **/
- public virtual void handleAfterDelete()
- {
- if(Configuration.EnforcingTriggerCRUDSecurity && !SObjectDescribe.isDeletable())
- throw new DomainException('Permission to delete an ' + SObjectDescribe.getName() + ' denied.');
-
- onAfterDelete();
- }
-
- /**
- * Base handler for the Apex Trigger event After Undelete, checks object security and calls the onAfterUndelete method
- *
- * @throws DomainException if the current user context is not able to delete records
- **/
- public virtual void handleAfterUndelete()
- {
- if(Configuration.EnforcingTriggerCRUDSecurity && !SObjectDescribe.isUndeletable())
- throw new DomainException('Permission to undelete an ' + SObjectDescribe.getName() + ' denied.');
-
- onAfterUndelete();
- }
-
- /**
- * Returns the SObjectType this Domain class represents
- **/
- public SObjectType sObjectType()
- {
- return getSObjectType();
- }
+ public virtual void handleBeforeInsert() {
+ onApplyDefaults();
+ onBeforeInsert();
+ }
+
+ /**
+ * Base handler for the Apex Trigger event Before Update, calls the onBeforeUpdate method
+ **/
+ public virtual void handleBeforeUpdate(Map existingRecords) {
+ onBeforeUpdate(existingRecords);
+ }
+
+ /**
+ * Base handler for the Apex Trigger event Before Delete, calls the onBeforeDelete method
+ **/
+ public virtual void handleBeforeDelete() {
+ onBeforeDelete();
+ }
+
+ /**
+ * Base handler for the Apex Trigger event After Insert, checks object security and calls the onValidate and onAfterInsert methods
+ *
+ * @throws DomainException if the current user context is not able to create records
+ **/
+ public virtual void handleAfterInsert() {
+ if (Configuration.EnforcingTriggerCRUDSecurity && !SObjectDescribe.isCreateable())
+ throw new DomainException('Permission to create an ' + SObjectDescribe.getName() + ' denied.');
+
+ onValidate();
+ onAfterInsert();
+ }
+
+ /**
+ * Base handler for the Apex Trigger event After Update, checks object security and calls the onValidate, onValidate(Map) and onAfterUpdate methods
+ *
+ * @throws DomainException if the current user context is not able to update records
+ **/
+ public virtual void handleAfterUpdate(Map existingRecords) {
+ if (Configuration.EnforcingTriggerCRUDSecurity && !SObjectDescribe.isUpdateable())
+ throw new DomainException('Permission to update an ' + SObjectDescribe.getName() + ' denied.');
+
+ if (Configuration.OldOnUpdateValidateBehaviour)
+ onValidate();
+ onValidate(existingRecords);
+ onAfterUpdate(existingRecords);
+ }
+
+ /**
+ * Base handler for the Apex Trigger event After Delete, checks object security and calls the onAfterDelete method
+ *
+ * @throws DomainException if the current user context is not able to delete records
+ **/
+ public virtual void handleAfterDelete() {
+ if (Configuration.EnforcingTriggerCRUDSecurity && !SObjectDescribe.isDeletable())
+ throw new DomainException('Permission to delete an ' + SObjectDescribe.getName() + ' denied.');
+
+ onAfterDelete();
+ }
+
+ /**
+ * Base handler for the Apex Trigger event After Undelete, checks object security and calls the onAfterUndelete method
+ *
+ * @throws DomainException if the current user context is not able to delete records
+ **/
+ public virtual void handleAfterUndelete() {
+ if (Configuration.EnforcingTriggerCRUDSecurity && !SObjectDescribe.isUndeletable())
+ throw new DomainException('Permission to undelete an ' + SObjectDescribe.getName() + ' denied.');
+
+ onAfterUndelete();
+ }
+
+ /**
+ * Returns the SObjectType this Domain class represents
+ **/
+ public SObjectType sObjectType() {
+ return getSObjectType();
+ }
/**
* Detects whether any values in context records have changed for given fields as strings
* Returns list of SObject records that have changes in the specified fields
**/
- public List getChangedRecords(Set fieldNames)
- {
+ public List getChangedRecords(Set fieldNames) {
List changedRecords = new List();
- for (SObject newRecord : Records)
- {
+ for (SObject newRecord : Records) {
Id recordId = (Id) newRecord.get('Id');
- if (this.ExistingRecords == null || !this.ExistingRecords.containsKey(recordId))
- {
+ if (this.ExistingRecords == null || !this.ExistingRecords.containsKey(recordId)) {
continue;
}
SObject oldRecord = this.ExistingRecords.get(recordId);
- for (String fieldName : fieldNames)
- {
- if (oldRecord.get(fieldName) != newRecord.get(fieldName))
- {
+ for (String fieldName : fieldNames) {
+ if (oldRecord.get(fieldName) != newRecord.get(fieldName)) {
changedRecords.add(newRecord);
- break; // prevents the records from being added multiple times
+ break; // prevents the records from being added multiple times
}
}
}
@@ -315,23 +297,18 @@ public virtual with sharing class fflib_SObjectDomain
* Detects whether any values in context records have changed for given fields as tokens
* Returns list of SObject records that have changes in the specified fields
**/
- public List getChangedRecords(Set fieldTokens)
- {
+ public List getChangedRecords(Set fieldTokens) {
List changedRecords = new List();
- for (SObject newRecord : Records)
- {
+ for (SObject newRecord : Records) {
Id recordId = (Id) newRecord.get('Id');
- if (this.ExistingRecords == null || !this.ExistingRecords.containsKey(recordId))
- {
+ if (this.ExistingRecords == null || !this.ExistingRecords.containsKey(recordId)) {
continue;
}
SObject oldRecord = this.ExistingRecords.get(recordId);
- for (Schema.SObjectField fieldToken : fieldTokens)
- {
- if (oldRecord.get(fieldToken) != newRecord.get(fieldToken))
- {
+ for (Schema.SObjectField fieldToken : fieldTokens) {
+ if (oldRecord.get(fieldToken) != newRecord.get(fieldToken)) {
changedRecords.add(newRecord);
- break; // prevents the records from being added multiple times
+ break; // prevents the records from being added multiple times
}
}
}
@@ -341,225 +318,278 @@ public virtual with sharing class fflib_SObjectDomain
/**
* Interface used to aid the triggerHandler in constructing instances of Domain classes
**/
- public interface IConstructable
- {
+ public interface IConstructable {
fflib_SObjectDomain construct(List sObjectList);
}
/**
* Interface used to aid the triggerHandler in constructing instances of Domain classes
**/
- public interface IConstructable2 extends IConstructable
- {
+ public interface IConstructable2 extends IConstructable {
fflib_SObjectDomain construct(List sObjectList, SObjectType sObjectType);
- }
-
+ }
+
/**
- * For Domain classes implementing the ITriggerStateful interface returns the instance
+ * For Domain classes implementing the ITriggerStateful interface returns the instance
* of the domain class being shared between trigger invocations, returns null if
* the Domain class trigger has not yet fired or the given domain class does not implement
* the ITriggerStateful interface. Note this method is sensitive to recursion, meaning
* it will return the applicable domain instance for the level of recursion
- **/
- public static fflib_SObjectDomain getTriggerInstance(Type domainClass)
- {
+ **/
+ public static fflib_SObjectDomain getTriggerInstance(Type domainClass) {
List domains = TriggerStateByClass.get(domainClass);
- if(domains==null || domains.size()==0)
+ if (domains == null || domains.size() == 0)
return null;
- return domains[domains.size()-1];
+ return domains[domains.size() - 1];
}
-
+
/**
- * Method constructs the given Domain class with the current Trigger context
+ * Method constructs the given Domain class with the current Trigger context
* before calling the applicable override methods such as beforeInsert, beforeUpdate etc.
**/
- public static void triggerHandler(Type domainClass)
- {
+ public static void triggerHandler(Type domainClass) {
// Process the trigger context
- if(System.Test.isRunningTest() & Test.Database.hasRecords())
- {
+ if (System.Test.isRunningTest() & Test.Database.hasRecords()) {
// If in test context and records in the mock database delegate initially to the mock database trigger handler
Test.Database.testTriggerHandler(domainClass);
- }
- else
- {
- // Process the runtime Apex Trigger context
- triggerHandler(domainClass,
- Trigger.isBefore,
- Trigger.isAfter,
- Trigger.isInsert,
- Trigger.isUpdate,
- Trigger.isDelete,
+ } else {
+ // Process the runtime Apex Trigger context
+ triggerHandler(
+ domainClass,
+ Trigger.isBefore,
+ Trigger.isAfter,
+ Trigger.isInsert,
+ Trigger.isUpdate,
+ Trigger.isDelete,
Trigger.isUnDelete,
- Trigger.new,
- Trigger.oldMap);
+ Trigger.new,
+ Trigger.oldMap
+ );
}
}
-
+
/**
* Calls the applicable override methods such as beforeInsert, beforeUpdate etc. based on a Trigger context
**/
- private static void triggerHandler(Type domainClass, Boolean isBefore, Boolean isAfter, Boolean isInsert, Boolean isUpdate, Boolean isDelete, Boolean isUndelete, List newRecords, Map oldRecordsMap)
- {
- // After phase of trigger will reuse prior instance of domain class if ITriggerStateful implemented
- fflib_SObjectDomain domainObject = isBefore ? null : popTriggerInstance(domainClass, isDelete ? oldRecordsMap.values() : newRecords);
- if(domainObject==null)
- {
+ private static void triggerHandler(
+ Type domainClass,
+ Boolean isBefore,
+ Boolean isAfter,
+ Boolean isInsert,
+ Boolean isUpdate,
+ Boolean isDelete,
+ Boolean isUndelete,
+ List newRecords,
+ Map oldRecordsMap
+ ) {
+ // After phase of trigger will reuse prior instance of domain class if ITriggerStateful implemented
+ fflib_SObjectDomain domainObject = isBefore
+ ? null
+ : popTriggerInstance(domainClass, isDelete ? oldRecordsMap.values() : newRecords);
+ if (domainObject == null) {
// Construct the domain class constructor class
String domainClassName = domainClass.getName();
- Type constructableClass = domainClassName.endsWith('Constructor') ? Type.forName(domainClassName) : Type.forName(domainClassName+'.Constructor');
+ Type constructableClass = domainClassName.endsWith('Constructor')
+ ? Type.forName(domainClassName)
+ : Type.forName(domainClassName + '.Constructor');
IConstructable domainConstructor = (IConstructable) constructableClass.newInstance();
-
- // Construct the domain class with the approprite record set
- if(isInsert) domainObject = domainConstructor.construct(newRecords);
- else if(isUpdate) domainObject = domainConstructor.construct(newRecords);
- else if(isDelete) domainObject = domainConstructor.construct(oldRecordsMap.values());
- else if(isUndelete) domainObject = domainConstructor.construct(newRecords);
-
- // Should this instance be reused on the next trigger invocation?
- if(domainObject.Configuration.TriggerStateEnabled)
- // Push this instance onto the stack to be popped during the after phase
- pushTriggerInstance(domainClass, domainObject);
- }
-
+
+ // Construct the domain class with the approprite record set
+ if (isInsert)
+ domainObject = domainConstructor.construct(newRecords);
+ else if (isUpdate)
+ domainObject = domainConstructor.construct(newRecords);
+ else if (isDelete)
+ domainObject = domainConstructor.construct(oldRecordsMap.values());
+ else if (isUndelete)
+ domainObject = domainConstructor.construct(newRecords);
+
+ // Should this instance be reused on the next trigger invocation?
+ if (domainObject.Configuration.TriggerStateEnabled)
+ // Push this instance onto the stack to be popped during the after phase
+ pushTriggerInstance(domainClass, domainObject);
+ }
+
// has this event been disabled?
- if(!getTriggerEvent(domainClass).isEnabled(isBefore, isAfter, isInsert, isUpdate, isDelete, isUndelete))
- {
+ if (!getTriggerEvent(domainClass).isEnabled(isBefore, isAfter, isInsert, isUpdate, isDelete, isUndelete)) {
return;
}
// Invoke the applicable handler
- if(isBefore)
- {
- if(isInsert) domainObject.handleBeforeInsert();
- else if(isUpdate) domainObject.handleBeforeUpdate(oldRecordsMap);
- else if(isDelete) domainObject.handleBeforeDelete();
- }
- else
- {
- if(isInsert) domainObject.handleAfterInsert();
- else if(isUpdate) domainObject.handleAfterUpdate(oldRecordsMap);
- else if(isDelete) domainObject.handleAfterDelete();
- else if(isUndelete) domainObject.handleAfterUndelete();
- }
+ if (isBefore) {
+ if (isInsert)
+ domainObject.handleBeforeInsert();
+ else if (isUpdate)
+ domainObject.handleBeforeUpdate(oldRecordsMap);
+ else if (isDelete)
+ domainObject.handleBeforeDelete();
+ } else {
+ if (isInsert)
+ domainObject.handleAfterInsert();
+ else if (isUpdate)
+ domainObject.handleAfterUpdate(oldRecordsMap);
+ else if (isDelete)
+ domainObject.handleAfterDelete();
+ else if (isUndelete)
+ domainObject.handleAfterUndelete();
+ }
}
-
+
/**
* Pushes to the stack of domain classes per type a domain object instance
**/
- private static void pushTriggerInstance(Type domainClass, fflib_SObjectDomain domain)
- {
+ private static void pushTriggerInstance(Type domainClass, fflib_SObjectDomain domain) {
List domains = TriggerStateByClass.get(domainClass);
- if(domains==null)
+ if (domains == null)
TriggerStateByClass.put(domainClass, domains = new List());
- domains.add(domain);
+ domains.add(domain);
}
-
+
/**
* Pops from the stack of domain classes per type a domain object instance and updates the record set
**/
- private static fflib_SObjectDomain popTriggerInstance(Type domainClass, List records)
- {
+ private static fflib_SObjectDomain popTriggerInstance(Type domainClass, List records) {
List domains = TriggerStateByClass.get(domainClass);
- if(domains==null || domains.size()==0)
- return null;
- fflib_SObjectDomain domain = domains.remove(domains.size()-1);
+ if (domains == null || domains.size() == 0)
+ return null;
+ fflib_SObjectDomain domain = domains.remove(domains.size() - 1);
domain.setObjects(records);
return domain;
}
-
- public static TriggerEvent getTriggerEvent(Type domainClass)
- {
- if(!TriggerEventByClass.containsKey(domainClass))
- {
+
+ public static TriggerEvent getTriggerEvent(Type domainClass) {
+ if (!TriggerEventByClass.containsKey(domainClass)) {
TriggerEventByClass.put(domainClass, new TriggerEvent());
}
return TriggerEventByClass.get(domainClass);
}
- public class TriggerEvent
- {
- public boolean BeforeInsertEnabled {get; private set;}
- public boolean BeforeUpdateEnabled {get; private set;}
- public boolean BeforeDeleteEnabled {get; private set;}
+ public class TriggerEvent {
+ public boolean BeforeInsertEnabled { get; private set; }
+ public boolean BeforeUpdateEnabled { get; private set; }
+ public boolean BeforeDeleteEnabled { get; private set; }
- public boolean AfterInsertEnabled {get; private set;}
- public boolean AfterUpdateEnabled {get; private set;}
- public boolean AfterDeleteEnabled {get; private set;}
- public boolean AfterUndeleteEnabled {get; private set;}
+ public boolean AfterInsertEnabled { get; private set; }
+ public boolean AfterUpdateEnabled { get; private set; }
+ public boolean AfterDeleteEnabled { get; private set; }
+ public boolean AfterUndeleteEnabled { get; private set; }
- public TriggerEvent()
- {
+ public TriggerEvent() {
this.enableAll();
}
// befores
- public TriggerEvent enableBeforeInsert() {BeforeInsertEnabled = true; return this;}
- public TriggerEvent enableBeforeUpdate() {BeforeUpdateEnabled = true; return this;}
- public TriggerEvent enableBeforeDelete() {BeforeDeleteEnabled = true; return this;}
-
- public TriggerEvent disableBeforeInsert() {BeforeInsertEnabled = false; return this;}
- public TriggerEvent disableBeforeUpdate() {BeforeUpdateEnabled = false; return this;}
- public TriggerEvent disableBeforeDelete() {BeforeDeleteEnabled = false; return this;}
-
+ public TriggerEvent enableBeforeInsert() {
+ BeforeInsertEnabled = true;
+ return this;
+ }
+ public TriggerEvent enableBeforeUpdate() {
+ BeforeUpdateEnabled = true;
+ return this;
+ }
+ public TriggerEvent enableBeforeDelete() {
+ BeforeDeleteEnabled = true;
+ return this;
+ }
+
+ public TriggerEvent disableBeforeInsert() {
+ BeforeInsertEnabled = false;
+ return this;
+ }
+ public TriggerEvent disableBeforeUpdate() {
+ BeforeUpdateEnabled = false;
+ return this;
+ }
+ public TriggerEvent disableBeforeDelete() {
+ BeforeDeleteEnabled = false;
+ return this;
+ }
+
// afters
- public TriggerEvent enableAfterInsert() {AfterInsertEnabled = true; return this;}
- public TriggerEvent enableAfterUpdate() {AfterUpdateEnabled = true; return this;}
- public TriggerEvent enableAfterDelete() {AfterDeleteEnabled = true; return this;}
- public TriggerEvent enableAfterUndelete() {AfterUndeleteEnabled = true; return this;}
-
-
- public TriggerEvent disableAfterInsert() {AfterInsertEnabled = false; return this;}
- public TriggerEvent disableAfterUpdate() {AfterUpdateEnabled = false; return this;}
- public TriggerEvent disableAfterDelete() {AfterDeleteEnabled = false; return this;}
- public TriggerEvent disableAfterUndelete(){AfterUndeleteEnabled = false; return this;}
-
- public TriggerEvent enableAll()
- {
+ public TriggerEvent enableAfterInsert() {
+ AfterInsertEnabled = true;
+ return this;
+ }
+ public TriggerEvent enableAfterUpdate() {
+ AfterUpdateEnabled = true;
+ return this;
+ }
+ public TriggerEvent enableAfterDelete() {
+ AfterDeleteEnabled = true;
+ return this;
+ }
+ public TriggerEvent enableAfterUndelete() {
+ AfterUndeleteEnabled = true;
+ return this;
+ }
+
+ public TriggerEvent disableAfterInsert() {
+ AfterInsertEnabled = false;
+ return this;
+ }
+ public TriggerEvent disableAfterUpdate() {
+ AfterUpdateEnabled = false;
+ return this;
+ }
+ public TriggerEvent disableAfterDelete() {
+ AfterDeleteEnabled = false;
+ return this;
+ }
+ public TriggerEvent disableAfterUndelete() {
+ AfterUndeleteEnabled = false;
+ return this;
+ }
+
+ public TriggerEvent enableAll() {
return this.enableAllBefore().enableAllAfter();
}
- public TriggerEvent disableAll()
- {
+ public TriggerEvent disableAll() {
return this.disableAllBefore().disableAllAfter();
}
- public TriggerEvent enableAllBefore()
- {
+ public TriggerEvent enableAllBefore() {
return this.enableBeforeInsert().enableBeforeUpdate().enableBeforeDelete();
}
- public TriggerEvent disableAllBefore()
- {
+ public TriggerEvent disableAllBefore() {
return this.disableBeforeInsert().disableBeforeUpdate().disableBeforeDelete();
}
- public TriggerEvent enableAllAfter()
- {
+ public TriggerEvent enableAllAfter() {
return this.enableAfterInsert().enableAfterUpdate().enableAfterDelete().enableAfterUndelete();
}
- public TriggerEvent disableAllAfter()
- {
+ public TriggerEvent disableAllAfter() {
return this.disableAfterInsert().disableAfterUpdate().disableAfterDelete().disableAfterUndelete();
}
- public boolean isEnabled(Boolean isBefore, Boolean isAfter, Boolean isInsert, Boolean isUpdate, Boolean isDelete, Boolean isUndelete)
- {
- if(isBefore)
- {
- if(isInsert) return BeforeInsertEnabled;
- else if(isUpdate) return BeforeUpdateEnabled;
- else if(isDelete) return BeforeDeleteEnabled;
- }
- else if(isAfter)
- {
- if(isInsert) return AfterInsertEnabled;
- else if(isUpdate) return AfterUpdateEnabled;
- else if(isDelete) return AfterDeleteEnabled;
- else if(isUndelete) return AfterUndeleteEnabled;
+ public boolean isEnabled(
+ Boolean isBefore,
+ Boolean isAfter,
+ Boolean isInsert,
+ Boolean isUpdate,
+ Boolean isDelete,
+ Boolean isUndelete
+ ) {
+ if (isBefore) {
+ if (isInsert)
+ return BeforeInsertEnabled;
+ else if (isUpdate)
+ return BeforeUpdateEnabled;
+ else if (isDelete)
+ return BeforeDeleteEnabled;
+ } else if (isAfter) {
+ if (isInsert)
+ return AfterInsertEnabled;
+ else if (isUpdate)
+ return AfterUpdateEnabled;
+ else if (isDelete)
+ return AfterDeleteEnabled;
+ else if (isUndelete)
+ return AfterUndeleteEnabled;
}
return true; // shouldnt ever get here!
}
@@ -568,55 +598,50 @@ public virtual with sharing class fflib_SObjectDomain
/**
* Fluent style Configuration system for Domain class creation
**/
- public class Configuration
- {
- /**
+ public class Configuration {
+ /**
* Backwards compatibility mode for handleAfterUpdate routing to onValidate()
**/
- public Boolean OldOnUpdateValidateBehaviour {get; private set;}
+ public Boolean OldOnUpdateValidateBehaviour { get; private set; }
/**
* True if the base class is checking the users CRUD requirements before invoking trigger methods
- **/
- public Boolean EnforcingTriggerCRUDSecurity {get; private set;}
-
+ **/
+ public Boolean EnforcingTriggerCRUDSecurity { get; private set; }
+
/**
* Enables reuse of the same Domain instance between before and after trigger phases (subject to recursive scenarios)
**/
- public Boolean TriggerStateEnabled {get; private set;}
-
+ public Boolean TriggerStateEnabled { get; private set; }
+
/**
- * Default configuration
+ * Default configuration
**/
- public Configuration()
- {
+ public Configuration() {
EnforcingTriggerCRUDSecurity = true; // Default is true for backwards compatability
TriggerStateEnabled = false;
OldOnUpdateValidateBehaviour = false; // Breaking change, but felt to better practice
}
-
+
/**
* See associated property
**/
- public Configuration enableTriggerState()
- {
+ public Configuration enableTriggerState() {
TriggerStateEnabled = true;
- return this;
+ return this;
}
-
+
/**
* See associated property
**/
- public Configuration disableTriggerState()
- {
+ public Configuration disableTriggerState() {
TriggerStateEnabled = false;
- return this;
+ return this;
}
/**
* See associated property
**/
- public Configuration enforceTriggerCRUDSecurity()
- {
+ public Configuration enforceTriggerCRUDSecurity() {
EnforcingTriggerCRUDSecurity = true;
return this;
}
@@ -624,8 +649,7 @@ public virtual with sharing class fflib_SObjectDomain
/**
* See associated property
**/
- public Configuration disableTriggerCRUDSecurity()
- {
+ public Configuration disableTriggerCRUDSecurity() {
EnforcingTriggerCRUDSecurity = false;
return this;
}
@@ -633,8 +657,7 @@ public virtual with sharing class fflib_SObjectDomain
/**
* See associated property
**/
- public Configuration enableOldOnUpdateValidateBehaviour()
- {
+ public Configuration enableOldOnUpdateValidateBehaviour() {
OldOnUpdateValidateBehaviour = true;
return this;
}
@@ -642,55 +665,46 @@ public virtual with sharing class fflib_SObjectDomain
/**
* See associated property
**/
- public Configuration disableOldOnUpdateValidateBehaviour()
- {
+ public Configuration disableOldOnUpdateValidateBehaviour() {
OldOnUpdateValidateBehaviour = false;
return this;
}
}
-
+
/**
* General exception class for the domain layer
**/
- public class DomainException extends Exception
- {
+ public class DomainException extends Exception {
}
/**
* Ensures logging of errors in the Domain context for later assertions in tests
**/
- public override String error(String message, SObject record)
- {
+ public override String error(String message, SObject record) {
return fflib_SObjectDomain.Errors.error(this, message, record);
}
-
+
/**
* Ensures logging of errors in the Domain context for later assertions in tests
**/
- public override String error(String message, SObject record, SObjectField field)
- {
+ public override String error(String message, SObject record, SObjectField field) {
return fflib_SObjectDomain.Errors.error(this, message, record, field);
}
/**
* DEPRECATED, This class has been moved to fflib_SObjects
**/
- public class ErrorFactory
- {
+ public class ErrorFactory {
private List errorList = new List();
- private ErrorFactory()
- {
-
+ private ErrorFactory() {
}
- public String error(String message, SObject record)
- {
+ public String error(String message, SObject record) {
return error(null, message, record);
}
- private String error(fflib_SObjectDomain domain, String message, SObject record)
- {
+ private String error(fflib_SObjectDomain domain, String message, SObject record) {
ObjectError objectError = new ObjectError();
objectError.domain = domain;
objectError.message = message;
@@ -699,13 +713,11 @@ public virtual with sharing class fflib_SObjectDomain
return message;
}
- public String error(String message, SObject record, SObjectField field)
- {
+ public String error(String message, SObject record, SObjectField field) {
return error(null, message, record, field);
}
- private String error(fflib_SObjectDomain domain, String message, SObject record, SObjectField field)
- {
+ private String error(fflib_SObjectDomain domain, String message, SObject record, SObjectField field) {
FieldError fieldError = new FieldError();
fieldError.domain = domain;
fieldError.message = message;
@@ -715,102 +727,84 @@ public virtual with sharing class fflib_SObjectDomain
return message;
}
- public List