Add Dynamic Application Factory
This enabled realtime dependency injection for the fflib application. By default the configuration comes from the Custom Metadata object fflib_AppBinding__mdt, but can be fully customised and extended. Initial stuff
This commit is contained in:
+1
-1
@@ -150,7 +150,7 @@ public virtual class fflib_ClassicDomainFactory
|
||||
* avoids the need to stub the mock to return its ObjectType
|
||||
* @param mockDomain The instance of the Domain mock
|
||||
*/
|
||||
public virtual void setMock(Type domainType, fflib_IDomain mockDomain)
|
||||
public virtual void setMock(Object domainType, fflib_IDomain mockDomain)
|
||||
{
|
||||
mockDomainByObject.put(domainType, mockDomain);
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* File Name: fflib_AppBinding
|
||||
* Description: Definition for an Application Binding
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public virtual class fflib_AppBinding
|
||||
implements fflib_IAppBinding, Comparable
|
||||
{
|
||||
protected Object bindingObject { get; set; }
|
||||
protected Decimal bindingSequence { get; set; }
|
||||
protected fflib_AppBindingType bindingType { get; set; }
|
||||
protected System.Type implementationType { get; set; }
|
||||
protected System.Type interfaceType { get; set; }
|
||||
protected String namespacePrefix { get; set; }
|
||||
protected fflib_SharingMode sharingMode { get; set; }
|
||||
|
||||
public Integer compareTo(Object compareTo)
|
||||
{
|
||||
fflib_IAppBinding compareToEmp = (fflib_IAppBinding) compareTo;
|
||||
if (getSequence() == compareToEmp.getSequence()) return 0;
|
||||
if (getSequence() > compareToEmp.getSequence()) return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Object getBindingObject()
|
||||
{
|
||||
return this.bindingObject;
|
||||
}
|
||||
|
||||
public virtual fflib_AppBindingType getBindingType()
|
||||
{
|
||||
return this.bindingType;
|
||||
}
|
||||
|
||||
public virtual System.Type getImplementationType()
|
||||
{
|
||||
return this.implementationType;
|
||||
}
|
||||
|
||||
public Type getInterfaceType()
|
||||
{
|
||||
return this.interfaceType;
|
||||
}
|
||||
|
||||
public String getNamespacePrefix()
|
||||
{
|
||||
return this.namespacePrefix;
|
||||
}
|
||||
|
||||
public Decimal getSequence()
|
||||
{
|
||||
return this.bindingSequence;
|
||||
}
|
||||
|
||||
public fflib_SharingMode getSharingMode()
|
||||
{
|
||||
return this.sharingMode;
|
||||
}
|
||||
|
||||
public virtual Object newImplInstance()
|
||||
{
|
||||
return implementationType.newInstance();
|
||||
}
|
||||
|
||||
public virtual fflib_IAppBinding setBindingObject(Object bindingObject)
|
||||
{
|
||||
this.bindingObject = bindingObject;
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual fflib_IAppBinding setBindingType(fflib_AppBindingType bindingType)
|
||||
{
|
||||
this.bindingType = bindingType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual fflib_IAppBinding setNamespacePrefix(String namespacePrefix)
|
||||
{
|
||||
this.namespacePrefix = namespacePrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual fflib_IAppBinding setImplementationType(System.Type implementationType)
|
||||
{
|
||||
this.implementationType = implementationType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual fflib_IAppBinding setInterfaceType(Type interfaceType)
|
||||
{
|
||||
this.interfaceType = interfaceType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual fflib_IAppBinding setSequence(Decimal sequence)
|
||||
{
|
||||
this.bindingSequence = sequence;
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual fflib_IAppBinding setSharingMode(fflib_SharingMode sharingMode)
|
||||
{
|
||||
this.sharingMode = sharingMode;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* File Name: fflib_AppBindingMetaDataModule
|
||||
* Description: An application module responsible for loading the application bindings
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public with sharing class fflib_AppBindingMetaDataModule
|
||||
extends fflib_AppBindingModule
|
||||
{
|
||||
public override void init()
|
||||
{
|
||||
this.bindings = new List<fflib_IAppBinding>();
|
||||
for (fflib_AppBinding__mdt binding : fflib_AppBindingsSelector.newInstance().selectAll())
|
||||
{
|
||||
addBinding(
|
||||
new fflib_AppBinding()
|
||||
.setBindingObject(getBindingObject(binding))
|
||||
.setBindingType(getBindingType(binding))
|
||||
.setImplementationType(getSystemType(binding, fflib_AppBinding__mdt.ImplementationType__c))
|
||||
.setInterfaceType(getSystemType(binding, fflib_AppBinding__mdt.InterfaceType__c))
|
||||
.setNamespacePrefix(binding.NamespacePrefix)
|
||||
.setSequence(binding.BindingSequence__c)
|
||||
.setSharingMode(getSharingModeFromString(binding.SharingMode__c))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private Object getBindingObject(fflib_AppBinding__mdt binding)
|
||||
{
|
||||
if (String.isBlank(binding.BindingObject__c) && String.isBlank(binding.BindingObjectAlternate__c)) return null;
|
||||
|
||||
String bindingObjectApiName = String.isNotBlank(binding.BindingObject__c)
|
||||
? binding.BindingObject__r.QualifiedApiName.toLowerCase().trim()
|
||||
: binding.BindingObjectAlternate__c.toLowerCase().trim();
|
||||
|
||||
// Assume its an SObjectType
|
||||
List<Schema.DescribeSObjectResult> schemaDescribes = Schema.describeSObjects(new List<String> {bindingObjectApiName});
|
||||
if (schemaDescribes.size() == 1)
|
||||
{
|
||||
return schemaDescribes.get(0).getSObjectType();
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if its an Object (class)
|
||||
Type objectType = System.Type.forName(bindingObjectApiName);
|
||||
if (objectType == null)
|
||||
throw new DeveloperException('Failed to find (S)Object ' + bindingObjectApiName + ' referenced by binding ' + binding.DeveloperName);
|
||||
|
||||
return objectType;
|
||||
}
|
||||
}
|
||||
|
||||
private fflib_AppBindingType getBindingType(fflib_AppBinding__mdt binding)
|
||||
{
|
||||
Map<String, fflib_AppBindingType> bindingTypeByStrings = new Map<String, fflib_AppBindingType>();
|
||||
for (fflib_AppBindingType enumValue : fflib_AppBindingType.values())
|
||||
{
|
||||
bindingTypeByStrings.put(String.valueOf(enumValue).toUpperCase(), enumValue);
|
||||
}
|
||||
|
||||
if (bindingTypeByStrings.containsKey(binding.Type__c.toUpperCase()) == false)
|
||||
throw new DeveloperException(
|
||||
String.format(
|
||||
'Unable to identify binding type {0} referenced by binding {1}',
|
||||
new List<String>{ binding.Type__c, binding.DeveloperName}
|
||||
)
|
||||
);
|
||||
|
||||
return bindingTypeByStrings.get(binding.Type__c.toUpperCase());
|
||||
}
|
||||
|
||||
private fflib_SharingMode getSharingModeFromString(String sharingMode)
|
||||
{
|
||||
switch on sharingMode.toUpperCase()
|
||||
{
|
||||
when 'WITH SHARING'
|
||||
{
|
||||
return fflib_SharingMode.WithSharing;
|
||||
}
|
||||
when 'WITHOUT SHARING'
|
||||
{
|
||||
return fflib_SharingMode.WithoutSharing;
|
||||
}
|
||||
when 'INHERITED SHARING'
|
||||
{
|
||||
return fflib_SharingMode.WithoutSharing;
|
||||
}
|
||||
when 'NONE'
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Type getSystemType(fflib_AppBinding__mdt binding, Schema.SObjectField sObjectField)
|
||||
{
|
||||
String systemTypeName = String.valueOf(binding.get(sObjectField));
|
||||
if (null == systemTypeName) return null;
|
||||
|
||||
Type systemType = System.Type.forName(systemTypeName);
|
||||
if (null == systemType)
|
||||
throw new DeveloperException(
|
||||
String.format(
|
||||
'Unable to find {0} referenced by binding {1} for {2}',
|
||||
new List<String>{ systemTypeName, binding.DeveloperName, sObjectField.getDescribe().getName()}
|
||||
)
|
||||
);
|
||||
return systemType;
|
||||
}
|
||||
|
||||
public class DeveloperException extends Exception
|
||||
{
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* File Name: fflib_AppBindingModule
|
||||
* Description: An application module is responsible for loading the application bindings
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public virtual class fflib_AppBindingModule
|
||||
implements fflib_IAppBindingModule
|
||||
{
|
||||
protected List<fflib_IAppBinding> bindings;
|
||||
|
||||
public fflib_AppBindingModule(){ }
|
||||
|
||||
public fflib_AppBindingModule(List<fflib_IAppBinding> bindings)
|
||||
{
|
||||
this.bindings = bindings;
|
||||
}
|
||||
|
||||
public virtual void addBinding(fflib_IAppBinding binding)
|
||||
{
|
||||
if (null == this.bindings) this.bindings = new List<fflib_IAppBinding>();
|
||||
|
||||
this.bindings.add(binding);
|
||||
}
|
||||
|
||||
public virtual void addBindings(List<fflib_IAppBinding> bindings)
|
||||
{
|
||||
if (null == this.bindings)
|
||||
{
|
||||
this.bindings = bindings;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.bindings.addAll(bindings);
|
||||
}
|
||||
}
|
||||
|
||||
public List<fflib_IAppBinding> getBindings()
|
||||
{
|
||||
return this.bindings;
|
||||
}
|
||||
|
||||
public virtual void init()
|
||||
{
|
||||
if (null == this.bindings) this.bindings = new List<fflib_IAppBinding>();
|
||||
}
|
||||
}
|
||||
+318
@@ -0,0 +1,318 @@
|
||||
/**
|
||||
* File Name: fflib_AppBindingResolver
|
||||
* Description: Resolver for returning the requested binding(s)
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public virtual class fflib_AppBindingResolver
|
||||
implements fflib_IAppBindingResolver
|
||||
{
|
||||
// allow for dependency injection inside the resolver
|
||||
protected InternalBindings internalBindings
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == internalBindings)
|
||||
{
|
||||
internalBindings = new InternalBindings();
|
||||
}
|
||||
return internalBindings;
|
||||
}
|
||||
private set;
|
||||
}
|
||||
|
||||
protected fflib_IAppBinding bindingToResolve
|
||||
{
|
||||
get
|
||||
{
|
||||
if (bindingToResolve == null)
|
||||
{
|
||||
bindingToResolve = internalBindings.newAppBinding();
|
||||
}
|
||||
return bindingToResolve;
|
||||
}
|
||||
private set;
|
||||
}
|
||||
|
||||
protected fflib_IAppBindings bindings;
|
||||
private List<fflib_IAppBindingModule> modules;
|
||||
|
||||
public static fflib_IAppBindingResolver newInstance()
|
||||
{
|
||||
return new fflib_AppBindingResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructors
|
||||
*/
|
||||
public fflib_AppBindingResolver()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Providing routes to the AppBindingResolver constructor provides dependency injection inside the resolver
|
||||
*
|
||||
* @param routes The routes
|
||||
*/
|
||||
public fflib_AppBindingResolver(fflib_IAppBindingRouter routes)
|
||||
{
|
||||
this(routes.getRoutes());
|
||||
}
|
||||
|
||||
public fflib_AppBindingResolver(Map<System.Type, System.Type> internalBindings)
|
||||
{
|
||||
this.internalBindings = new InternalBindings(internalBindings);
|
||||
}
|
||||
|
||||
public fflib_IAppBindingResolver addModule(fflib_IAppBindingModule bindingModule)
|
||||
{
|
||||
if (null == this.modules) this.modules = new List<fflib_IAppBindingModule>();
|
||||
|
||||
this.modules.add(bindingModule);
|
||||
return this;
|
||||
}
|
||||
|
||||
public fflib_IAppBindingResolver byObject(Object bindingObject)
|
||||
{
|
||||
this.bindingToResolve.setBindingObject(bindingObject);
|
||||
return this;
|
||||
}
|
||||
|
||||
public fflib_IAppBindingResolver bySequence(Integer sequence)
|
||||
{
|
||||
this.bindingToResolve.setSequence(sequence);
|
||||
return this;
|
||||
}
|
||||
|
||||
public fflib_IAppBindingResolver byType(fflib_AppBindingType bindingType)
|
||||
{
|
||||
this.bindingToResolve.setBindingType(bindingType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public fflib_IAppBindingResolver byInterfaceType(Type interfaceType)
|
||||
{
|
||||
this.bindingToResolve.setInterfaceType(interfaceType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public fflib_IAppBindingResolver bySharingMode(fflib_SharingMode sharingMode)
|
||||
{
|
||||
this.bindingToResolve.setSharingMode(sharingMode);
|
||||
return this;
|
||||
}
|
||||
|
||||
public fflib_IAppBindingResolver byNamespacePrefix(String namespacePrefix)
|
||||
{
|
||||
this.bindingToResolve.setNamespacePrefix(namespacePrefix);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles lazy loading of modules, if no custom module is configured (via addModule) the default module is returned
|
||||
*
|
||||
* @return Returns the configured modules
|
||||
*/
|
||||
public List<fflib_IAppBindingModule> getModules()
|
||||
{
|
||||
if (null == this.modules)
|
||||
{
|
||||
// Lazy load the default Binding module is none other is set.
|
||||
modules = new List<fflib_IAppBindingModule>
|
||||
{
|
||||
internalBindings.newAppBindingModule()
|
||||
};
|
||||
}
|
||||
return modules;
|
||||
}
|
||||
|
||||
public List<fflib_IAppBinding> resolve()
|
||||
{
|
||||
if (!hasBindingsLoaded()) loadBindings();
|
||||
|
||||
fflib_IAppBindings resolvedBindings =
|
||||
this.bindings
|
||||
.selectByNamespacePrefix(bindingToResolve.getNamespacePrefix())
|
||||
.selectByType(bindingToResolve.getBindingType())
|
||||
.selectByInterfaceType(bindingToResolve.getInterfaceType())
|
||||
.selectByObject(bindingToResolve.getBindingObject())
|
||||
.selectBySharingMode(bindingToResolve.getSharingMode())
|
||||
.selectBySequence(bindingToResolve.getSequence());
|
||||
|
||||
this.bindingToResolve = internalBindings.newAppBinding();
|
||||
return resolvedBindings.getBindings();
|
||||
}
|
||||
|
||||
|
||||
protected Boolean hasBindingsLoaded()
|
||||
{
|
||||
return (this.bindings != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a domain to store the bindings,
|
||||
* retrieves the bindings from the modules
|
||||
* and stores the bindings in this.bindings
|
||||
*/
|
||||
protected virtual void loadBindings()
|
||||
{
|
||||
this.bindings = internalBindings.newAppBindings();
|
||||
List<fflib_IAppBindingModule> modules = getModules();
|
||||
List<fflib_IAppBinding> appBindings = loadModules(modules);
|
||||
this.bindings.addBindings(
|
||||
appBindings
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises all the modules and retrieves their binding.
|
||||
* Any child modules in all nested will also be initialised and processed
|
||||
*
|
||||
* @param modules The modules to load their binding
|
||||
*
|
||||
* @return Returns the bindings configured in the given modules
|
||||
*/
|
||||
protected virtual List<fflib_IAppBinding> loadModules(List<fflib_IAppBindingModule> modules)
|
||||
{
|
||||
List<fflib_IAppBinding> result = new List<fflib_IAppBinding>();
|
||||
for (fflib_IAppBindingModule module : getModules())
|
||||
{
|
||||
module.init();
|
||||
List<fflib_IAppBinding> bindings = module.getBindings();
|
||||
List<fflib_IAppBindingModule> subModules = getModulesFromBindings(bindings);
|
||||
|
||||
if (subModules.isEmpty() == false)
|
||||
{
|
||||
result.addAll(
|
||||
loadModules(subModules)
|
||||
);
|
||||
}
|
||||
result.addAll(bindings);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the bindings of the type module from the given list and returns their instance
|
||||
*
|
||||
* @param bindings The bindings to filter
|
||||
*
|
||||
* @return Returns the instances of Module bindings
|
||||
*/
|
||||
private List<fflib_IAppBindingModule> getModulesFromBindings(List<fflib_IAppBinding> bindings)
|
||||
{
|
||||
List<fflib_IAppBindingModule> result = new List<fflib_IAppBindingModule>();
|
||||
for (fflib_IAppBinding binding : bindings)
|
||||
{
|
||||
if (binding.getBindingType() != fflib_AppBindingType.Module) continue;
|
||||
|
||||
Object instance = binding.newImplInstance();
|
||||
if (!(instance instanceof fflib_IAppBindingModule))
|
||||
throw new DeveloperException(
|
||||
'Binding module should be an instance of fflib_IAppBindingModule, instead found: '
|
||||
+ binding.getImplementationType().getName()
|
||||
);
|
||||
|
||||
result.add(
|
||||
(fflib_IAppBindingModule) instance
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public class InternalBindings
|
||||
{
|
||||
private Map<System.Type, System.Type> bindings;
|
||||
|
||||
public InternalBindings()
|
||||
{
|
||||
}
|
||||
|
||||
public InternalBindings(Map<System.Type, System.Type> internalBindings)
|
||||
{
|
||||
this.bindings = internalBindings;
|
||||
}
|
||||
|
||||
public fflib_IAppBinding newAppBinding()
|
||||
{
|
||||
System.Type interfaceType = fflib_IAppBinding.class;
|
||||
if (hasInternalBinding(interfaceType))
|
||||
{
|
||||
Object instance = getInternalBinding(interfaceType);
|
||||
if (!(instance instanceof fflib_IAppBinding))
|
||||
throw new DeveloperException('Invalid internal binding for fflib_IAppBinding');
|
||||
|
||||
return (fflib_IAppBinding) instance;
|
||||
}
|
||||
|
||||
return new fflib_AppBinding();
|
||||
}
|
||||
|
||||
public fflib_IAppBindings newAppBindings()
|
||||
{
|
||||
System.Type interfaceType = fflib_IAppBindings.class;
|
||||
if (hasInternalBinding(interfaceType))
|
||||
{
|
||||
Object instance = getInternalBinding(interfaceType);
|
||||
if (!(instance instanceof fflib_IAppBinding))
|
||||
throw new DeveloperException('Invalid internal binding for fflib_IAppBindings');
|
||||
|
||||
return (fflib_IAppBindings) instance;
|
||||
}
|
||||
|
||||
return new fflib_AppBindings();
|
||||
}
|
||||
|
||||
private Boolean hasInternalBinding(System.Type interfaceType)
|
||||
{
|
||||
return this.bindings != null && this.bindings.containsKey(interfaceType);
|
||||
}
|
||||
|
||||
private Object getInternalBinding(System.Type interfaceType)
|
||||
{
|
||||
return this.bindings.get(interfaceType).newInstance();
|
||||
}
|
||||
|
||||
private fflib_IAppBindingModule newAppBindingModule()
|
||||
{
|
||||
System.Type interfaceType = fflib_IAppBindingModule.class;
|
||||
if (hasInternalBinding(interfaceType))
|
||||
{
|
||||
Object instance = getInternalBinding(interfaceType);
|
||||
if (!(instance instanceof fflib_IAppBindingModule))
|
||||
throw new DeveloperException('Invalid internal binding for fflib_IAppBindingModule');
|
||||
|
||||
return (fflib_IAppBindingModule) instance;
|
||||
}
|
||||
|
||||
return new fflib_AppBindingMetaDataModule();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeveloperException extends Exception {}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* File Name: fflib_AppBindingType
|
||||
* Description: Enum for Binding Types
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public enum fflib_AppBindingType
|
||||
{
|
||||
Domain, Service, Selector, Controller, Module, Misc
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* File Name: fflib_AppBindings
|
||||
* Description: Domain class for fflib_AppBinding objects
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public virtual class fflib_AppBindings
|
||||
implements fflib_IAppBindings
|
||||
{
|
||||
protected List<fflib_IAppBinding> bindings;
|
||||
|
||||
public fflib_AppBindings() { }
|
||||
|
||||
public fflib_AppBindings(List<fflib_IAppBinding> bindings)
|
||||
{
|
||||
this.bindings = bindings;
|
||||
}
|
||||
|
||||
public void addBinding(fflib_IAppBinding binding)
|
||||
{
|
||||
if (null == this.bindings)
|
||||
{
|
||||
this.bindings = new List<fflib_IAppBinding>{ binding };
|
||||
}
|
||||
{
|
||||
this.bindings.add(binding);
|
||||
}
|
||||
}
|
||||
|
||||
public void addBindings(List<fflib_IAppBinding> bindings)
|
||||
{
|
||||
if (null == this.bindings)
|
||||
{
|
||||
this.bindings = bindings;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.bindings.addAll(bindings);
|
||||
}
|
||||
}
|
||||
|
||||
public fflib_IAppBindings selectByObject(Object bindingObject)
|
||||
{
|
||||
if (null == bindingObject) return this;
|
||||
|
||||
List<fflib_IAppBinding> result = new List<fflib_IAppBinding>();
|
||||
for (fflib_IAppBinding binding : bindings)
|
||||
{
|
||||
if (binding.getBindingObject() != bindingObject) continue;
|
||||
|
||||
result.add(binding);
|
||||
}
|
||||
return new fflib_AppBindings(result);
|
||||
}
|
||||
|
||||
public fflib_IAppBindings selectBySequence(Decimal sequence)
|
||||
{
|
||||
bindings.sort();
|
||||
|
||||
if (null == sequence) return this;
|
||||
|
||||
List<fflib_IAppBinding> result = new List<fflib_IAppBinding>();
|
||||
for (fflib_IAppBinding binding : bindings)
|
||||
{
|
||||
if (binding.getSequence() != sequence) continue;
|
||||
|
||||
result.add(binding);
|
||||
}
|
||||
return new fflib_AppBindings(result);
|
||||
}
|
||||
|
||||
public fflib_IAppBindings selectByType(fflib_AppBindingType bindingType)
|
||||
{
|
||||
if (null == bindingType) return this;
|
||||
|
||||
List<fflib_IAppBinding> result = new List<fflib_IAppBinding>();
|
||||
for (fflib_IAppBinding binding : bindings)
|
||||
{
|
||||
if (binding.getBindingType() != bindingType) continue;
|
||||
|
||||
result.add(binding);
|
||||
}
|
||||
return new fflib_AppBindings(result);
|
||||
}
|
||||
|
||||
public fflib_IAppBindings selectByInterfaceType(Type interfaceType)
|
||||
{
|
||||
if (null == interfaceType) return this;
|
||||
|
||||
List<fflib_IAppBinding> result = new List<fflib_IAppBinding>();
|
||||
for (fflib_IAppBinding binding : bindings)
|
||||
{
|
||||
if (binding.getInterfaceType() != interfaceType) continue;
|
||||
|
||||
result.add(binding);
|
||||
}
|
||||
return new fflib_AppBindings(result);
|
||||
}
|
||||
|
||||
public fflib_IAppBindings selectBySharingMode(fflib_SharingMode sharingMode)
|
||||
{
|
||||
if (null == sharingMode) return this;
|
||||
|
||||
List<fflib_IAppBinding> result = new List<fflib_IAppBinding>();
|
||||
for (fflib_IAppBinding binding : bindings)
|
||||
{
|
||||
if (binding.getSharingMode() != sharingMode) continue;
|
||||
|
||||
result.add(binding);
|
||||
}
|
||||
return new fflib_AppBindings(result);
|
||||
}
|
||||
|
||||
public fflib_IAppBindings selectByNamespacePrefix(String namespacePrefix)
|
||||
{
|
||||
if (null == namespacePrefix) return this;
|
||||
|
||||
List<fflib_IAppBinding> result = new List<fflib_IAppBinding>();
|
||||
for (fflib_IAppBinding binding : bindings)
|
||||
{
|
||||
if (binding.getNamespacePrefix() != namespacePrefix) continue;
|
||||
|
||||
result.add(binding);
|
||||
}
|
||||
return new fflib_AppBindings(result);
|
||||
}
|
||||
|
||||
public List<fflib_IAppBinding> getBindings()
|
||||
{
|
||||
return this.bindings;
|
||||
}
|
||||
|
||||
public List<System.Type> getImplementations()
|
||||
{
|
||||
List<System.Type> result = new List<System.Type>();
|
||||
for (fflib_IAppBinding binding : bindings)
|
||||
{
|
||||
result.add(
|
||||
binding.getImplementationType()
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Object> getObjects()
|
||||
{
|
||||
return getBindings();
|
||||
}
|
||||
|
||||
public Object getType()
|
||||
{
|
||||
return fflib_IAppBinding.class;
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* File Name: fflib_AppBindingsSelector
|
||||
* Description: Selector for fflib_AppBinding__mdt records
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public virtual without sharing class fflib_AppBindingsSelector extends fflib_SObjectSelector
|
||||
{
|
||||
// Used for mocking
|
||||
@TestVisible
|
||||
private static System.Type SELECTOR_IMPL_TYPE = fflib_AppBindingsSelector.class;
|
||||
|
||||
public List<Schema.SObjectField> getSObjectFieldList()
|
||||
{
|
||||
return new List<Schema.SObjectField>
|
||||
{
|
||||
fflib_AppBinding__mdt.Id,
|
||||
fflib_AppBinding__mdt.BindingObject__c,
|
||||
fflib_AppBinding__mdt.BindingObjectAlternate__c,
|
||||
fflib_AppBinding__mdt.BindingSequence__c,
|
||||
fflib_AppBinding__mdt.DeveloperName,
|
||||
fflib_AppBinding__mdt.NamespacePrefix,
|
||||
fflib_AppBinding__mdt.ImplementationType__c,
|
||||
fflib_AppBinding__mdt.InterfaceType__c,
|
||||
fflib_AppBinding__mdt.SharingMode__c,
|
||||
fflib_AppBinding__mdt.Type__c
|
||||
};
|
||||
}
|
||||
|
||||
public static fflib_AppBindingsSelector newInstance()
|
||||
{
|
||||
return (fflib_AppBindingsSelector) SELECTOR_IMPL_TYPE.newInstance();
|
||||
}
|
||||
|
||||
public Schema.SObjectType getSObjectType()
|
||||
{
|
||||
return fflib_AppBinding__mdt.SObjectType;
|
||||
}
|
||||
|
||||
public virtual List<fflib_AppBinding__mdt> selectAll()
|
||||
{
|
||||
/**
|
||||
Todo - Waiting to uncomment the following section
|
||||
until fflib-apex-common fixes the getFieldPath issue
|
||||
Currently failing on the BindingObject__r field,
|
||||
thinking its not a relationship field
|
||||
|
||||
Error on line 119, column 1: fflib_QueryFactory.NonReferenceFieldException:
|
||||
fflib_AppBinding__mdt.BindingObject__r is not a lookup or master-detail
|
||||
field but is used in a cross-object query field.
|
||||
|
||||
return (List<fflib_AppBinding__mdt>) Database.query(
|
||||
newQueryFactory()
|
||||
.selectField('BindingObject__r.QualifiedApiName')
|
||||
.toSOQL());
|
||||
*/
|
||||
|
||||
return (List<fflib_AppBinding__mdt>) Database.query(
|
||||
String.format(
|
||||
'SELECT {0} FROM {1}',
|
||||
new List<String>
|
||||
{
|
||||
getFieldListString() + ', BindingObject__r.QualifiedApiName',
|
||||
getSObjectType().getDescribe().getName()
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* File Name: fflib_DynamicAppFactory
|
||||
* Description: Abstract class with common functionality for Dynamic Bindings
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public abstract class fflib_DynamicAppFactory
|
||||
{
|
||||
protected fflib_SharingMode sharingMode;
|
||||
protected fflib_IAppBindingResolver resolver;
|
||||
protected Map<System.Type, System.Type> routes;
|
||||
|
||||
protected Map<Object, Object> mockImplByObjectType = new Map<Object, Object>();
|
||||
|
||||
protected void setMock(Object objectType, Object mock)
|
||||
{
|
||||
this.mockImplByObjectType.put(
|
||||
objectType,
|
||||
mock
|
||||
);
|
||||
}
|
||||
|
||||
protected Object getMock(Object objectType)
|
||||
{
|
||||
return this.mockImplByObjectType.get(objectType);
|
||||
}
|
||||
|
||||
protected Boolean hasMock(Object objectType)
|
||||
{
|
||||
return this.mockImplByObjectType.containsKey(objectType);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* File Name: fflib_DynamicDomainFactory
|
||||
* Description:
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public virtual class fflib_DynamicDomainFactory
|
||||
extends fflib_DynamicAppFactory
|
||||
implements fflib_IDomainFactory
|
||||
{
|
||||
public static final fflib_AppBindingType DOMAIN = fflib_AppBindingType.Domain;
|
||||
|
||||
protected Map<Object, fflib_IDomain> mockDomainByObjectType = new Map<Object, fflib_IDomain>();
|
||||
protected fflib_ISelectorFactory selectorFactory;
|
||||
|
||||
|
||||
public fflib_DynamicDomainFactory(fflib_IAppBindingResolver resolver, fflib_ISelectorFactory selectorFactory)
|
||||
{
|
||||
this.resolver = resolver;
|
||||
this.selectorFactory = selectorFactory;
|
||||
}
|
||||
|
||||
public fflib_IDomain newInstance(Set<Id> recordIds)
|
||||
{
|
||||
return newInstance(this.selectorFactory.selectById(recordIds));
|
||||
}
|
||||
|
||||
public fflib_IDomain newInstance(Set<Id> recordIds, SObjectType sObjectType)
|
||||
{
|
||||
return newInstance(this.selectorFactory.selectById(recordIds, sObjectType));
|
||||
}
|
||||
|
||||
public fflib_IDomain newInstance(List<SObject> records)
|
||||
{
|
||||
SObjectType sObjectType = records.getSObjectType();
|
||||
|
||||
if (sObjectType == null)
|
||||
throw new DeveloperException('Could not determine the SObjectType of the provided records');
|
||||
|
||||
return newInstance(
|
||||
(List<Object>) records,
|
||||
(Object) sObjectType
|
||||
);
|
||||
}
|
||||
|
||||
public fflib_IDomain newInstance(List<Object> objects, Object objectType)
|
||||
{
|
||||
if (hasMock(objectType)) return (fflib_IDomain) getMock(objectType);
|
||||
|
||||
List<fflib_IAppBinding> bindings = resolver.byObject(objectType)
|
||||
.byType(DOMAIN)
|
||||
.resolve();
|
||||
|
||||
if (bindings.isEmpty())
|
||||
throw new DeveloperException('Unable to find domain binding ' + objectType);
|
||||
|
||||
System.Type domainImplementationType = bindings.get(0).getImplementationType();
|
||||
|
||||
Object instance = domainImplementationType.newInstance();
|
||||
|
||||
if (!(instance instanceof fflib_IDomainConstructor))
|
||||
throw new DeveloperException(
|
||||
String.format(
|
||||
'Domain implementation {0} should be an instance of fflib_IDomainConstructor',
|
||||
new List<String> { domainImplementationType.getName() }
|
||||
)
|
||||
);
|
||||
|
||||
return ((fflib_IDomainConstructor) domainImplementationType.newInstance())
|
||||
.construct(objects);
|
||||
}
|
||||
|
||||
public fflib_IDomain newInstance(List<SObject> records, SObjectType domainSObjectType)
|
||||
{
|
||||
return newInstance((List<Object>) records, (Object) domainSObjectType);
|
||||
}
|
||||
|
||||
public void setMock(fflib_ISObjectDomain mockDomain)
|
||||
{
|
||||
super.setMock(mockDomain.getType(), mockDomain);
|
||||
}
|
||||
|
||||
public void setMock(Schema.SObjectType sObjectType, fflib_ISObjectDomain mockDomain)
|
||||
{
|
||||
super.setMock(sObjectType, mockDomain);
|
||||
}
|
||||
|
||||
public void setMock(fflib_IDomain mockDomain)
|
||||
{
|
||||
super.setMock(mockDomain.getType(), mockDomain);
|
||||
}
|
||||
|
||||
public void setMock(Object domainType, fflib_IDomain mockDomain)
|
||||
{
|
||||
super.setMock(domainType, mockDomain);
|
||||
}
|
||||
|
||||
public class DeveloperException extends Exception {}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* File Name: fflib_DynamicSelectorFactory
|
||||
* Description:
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public virtual class fflib_DynamicSelectorFactory
|
||||
extends fflib_DynamicAppFactory
|
||||
implements fflib_ISelectorFactory
|
||||
{
|
||||
public static final fflib_AppBindingType SELECTOR_BINDING_TYPE = fflib_AppBindingType.Selector;
|
||||
|
||||
protected Map<Object, Object> mockSelectorImplByObjectType = new Map<Object, Object>();
|
||||
|
||||
public fflib_DynamicSelectorFactory(fflib_IAppBindingResolver resolver)
|
||||
{
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
public fflib_ISObjectSelector newInstance(SObjectType sObjectType)
|
||||
{
|
||||
if (hasMock(sObjectType)) return (fflib_ISObjectSelector) getMock(sObjectType);
|
||||
|
||||
List<fflib_IAppBinding> bindings = resolver
|
||||
.byType(SELECTOR_BINDING_TYPE)
|
||||
.byObject(sObjectType)
|
||||
.bySharingMode(sharingMode)
|
||||
.resolve();
|
||||
|
||||
if (bindings.isEmpty())
|
||||
throw new DeveloperException(
|
||||
String.format(
|
||||
'Unable to find selector binding {0} with sharing more {0}',
|
||||
new List<String>
|
||||
{
|
||||
sObjectType.getDescribe().getName(),
|
||||
sharingMode.name()
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
return (fflib_ISObjectSelector) bindings.get(0).newImplInstance();
|
||||
}
|
||||
|
||||
public List<SObject> selectById(Set<Id> recordIds)
|
||||
{
|
||||
if (null == recordIds || recordIds.size() == 0)
|
||||
throw new fflib_Application.DeveloperException('Invalid record Id\'s set');
|
||||
|
||||
return selectById(recordIds, new List<Id>(recordIds)[0].getSObjectType());
|
||||
}
|
||||
|
||||
public List<SObject> selectById(Set<Id> recordIds, SObjectType sObjectType)
|
||||
{
|
||||
if (null == recordIds || recordIds.size() == 0)
|
||||
throw new fflib_Application.DeveloperException('Invalid record Id\'s set');
|
||||
|
||||
return newInstance(sObjectType)
|
||||
.selectSObjectsById(recordIds);
|
||||
}
|
||||
|
||||
public List<SObject> selectByRelationship(List<SObject> relatedRecords, SObjectField relationshipField)
|
||||
{
|
||||
Set<Id> relatedIds =
|
||||
new RelatedRecordsDomain(relatedRecords)
|
||||
.getRelatedIds(relationshipField);
|
||||
|
||||
if (relatedIds.isEmpty()) return new List<SObject>();
|
||||
|
||||
return selectById(relatedIds);
|
||||
}
|
||||
|
||||
public void replaceWith(SObjectType sObjectType, Type replacementImplType)
|
||||
{
|
||||
resolver.byType(fflib_AppBindingType.Selector)
|
||||
.byObject(sObjectType)
|
||||
.bySharingMode(this.sharingMode)
|
||||
.resolve()
|
||||
.get(0)
|
||||
.setImplementationType(replacementImplType);
|
||||
}
|
||||
|
||||
public void setMock(fflib_ISObjectSelector selectorInstance)
|
||||
{
|
||||
setMock(selectorInstance.sObjectType(), selectorInstance);
|
||||
}
|
||||
|
||||
public void setMock(SObjectType sObjectType, fflib_ISObjectSelector selectorInstance)
|
||||
{
|
||||
super.setMock(sObjectType, selectorInstance);
|
||||
}
|
||||
|
||||
public fflib_DynamicSelectorFactory setSharingMode(fflib_SharingMode sharingMode)
|
||||
{
|
||||
this.sharingMode = sharingMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
private class RelatedRecordsDomain extends SObjects
|
||||
{
|
||||
public RelatedRecordsDomain(List<SObject> records)
|
||||
{
|
||||
super(records);
|
||||
}
|
||||
|
||||
public Set<Id> getRelatedIds(Schema.SObjectField relationshipField)
|
||||
{
|
||||
return getIdFieldValues(relationshipField).getIds();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeveloperException extends Exception {}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* File Name: fflib_DynamicServiceFactory
|
||||
* Description: Service Factory to return service class instances in a dynamic way
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public virtual class fflib_DynamicServiceFactory
|
||||
extends fflib_DynamicAppFactory
|
||||
implements fflib_IServiceFactory
|
||||
{
|
||||
public static final fflib_AppBindingType SERVICE_BINDING_TYPE = fflib_AppBindingType.Service;
|
||||
|
||||
protected Map<System.Type, Object> mockServiceImplByObjectType = new Map<System.Type, Object>();
|
||||
|
||||
public fflib_DynamicServiceFactory(fflib_IAppBindingResolver resolver)
|
||||
{
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
public Object newInstance(Type serviceInterfaceType)
|
||||
{
|
||||
if (hasMock(serviceInterfaceType)) return getMock(serviceInterfaceType);
|
||||
|
||||
List<fflib_IAppBinding> bindings = resolver
|
||||
.byType(SERVICE_BINDING_TYPE)
|
||||
.byInterfaceType(serviceInterfaceType)
|
||||
.bySharingMode(sharingMode)
|
||||
.resolve();
|
||||
|
||||
if (bindings.isEmpty())
|
||||
throw new DeveloperException(
|
||||
String.format(
|
||||
'Unable to find service binding {0} with sharing more {0}',
|
||||
new List<String>
|
||||
{
|
||||
serviceInterfaceType.getName(),
|
||||
sharingMode.name()
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
return bindings.get(0).newImplInstance();
|
||||
}
|
||||
|
||||
public void replaceWith(Type serviceInterfaceType, Type replacementImplType)
|
||||
{
|
||||
resolver.byType(SERVICE_BINDING_TYPE)
|
||||
.byInterfaceType(serviceInterfaceType)
|
||||
.bySharingMode(sharingMode)
|
||||
.resolve()
|
||||
.get(0) // TODO - validate that there are any resolved bindings
|
||||
.setImplementationType(replacementImplType);
|
||||
}
|
||||
|
||||
public void setMock(Type serviceInterfaceType, Object serviceImpl)
|
||||
{
|
||||
super.setMock(serviceInterfaceType, serviceImpl);
|
||||
}
|
||||
|
||||
public fflib_DynamicServiceFactory setSharingMode(fflib_SharingMode sharingMode)
|
||||
{
|
||||
this.sharingMode = sharingMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public class DeveloperException extends Exception {}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* File Name: fflib_SharingMode
|
||||
* Description: Enum with the Application Binding Sharing Modes
|
||||
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public enum fflib_SharingMode
|
||||
{
|
||||
WithSharing, WithoutSharing, InheritedSharing, None
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* File Name: fflib_IAppBinding
|
||||
* Description: Interface for Application Binding Data Object
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public interface fflib_IAppBinding
|
||||
{
|
||||
Object getBindingObject();
|
||||
fflib_AppBindingType getBindingType();
|
||||
System.Type getImplementationType();
|
||||
System.Type getInterfaceType();
|
||||
String getNamespacePrefix();
|
||||
Decimal getSequence();
|
||||
fflib_SharingMode getSharingMode();
|
||||
|
||||
Object newImplInstance();
|
||||
|
||||
fflib_IAppBinding setBindingObject(Object bindingObject);
|
||||
fflib_IAppBinding setBindingType(fflib_AppBindingType bindingType);
|
||||
fflib_IAppBinding setNamespacePrefix(String namespacePrefix);
|
||||
fflib_IAppBinding setImplementationType(System.Type implementationType);
|
||||
fflib_IAppBinding setInterfaceType(System.Type interfaceType);
|
||||
fflib_IAppBinding setSequence(Decimal sequence);
|
||||
fflib_IAppBinding setSharingMode(fflib_SharingMode sharingMode);
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* File Name: fflib_IAppBindingModule
|
||||
* Description: Interface for the Application Module
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public interface fflib_IAppBindingModule
|
||||
{
|
||||
void init();
|
||||
void addBinding(fflib_IAppBinding binding);
|
||||
void addBindings(List<fflib_IAppBinding> bindings);
|
||||
List<fflib_IAppBinding> getBindings();
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* File Name: fflib_IAppBindingResolver
|
||||
* Description:
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public interface fflib_IAppBindingResolver
|
||||
{
|
||||
fflib_IAppBindingResolver addModule(fflib_IAppBindingModule bindingModule);
|
||||
fflib_IAppBindingResolver byObject(Object bindingObject);
|
||||
fflib_IAppBindingResolver bySequence(Integer sequence);
|
||||
fflib_IAppBindingResolver byType(fflib_AppBindingType bindingType);
|
||||
fflib_IAppBindingResolver byInterfaceType(System.Type interfaceType);
|
||||
fflib_IAppBindingResolver bySharingMode(fflib_SharingMode sharingMode);
|
||||
fflib_IAppBindingResolver byNamespacePrefix(String namespacePrefix);
|
||||
List<fflib_IAppBinding> resolve();
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* File Name: fflib_IAppBindingRouter
|
||||
* Description:
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public interface fflib_IAppBindingRouter
|
||||
{
|
||||
Map<System.Type, System.Type> getRoutes();
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* File Name: fflib_IAppBindings
|
||||
* Description: Domain class interface signatures for fflib_AppBindings
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public interface fflib_IAppBindings
|
||||
extends fflib_IDomain
|
||||
{
|
||||
void addBinding(fflib_IAppBinding binding);
|
||||
void addBindings(List<fflib_IAppBinding> bindings);
|
||||
|
||||
fflib_IAppBindings selectByObject(Object bindingObject);
|
||||
fflib_IAppBindings selectBySequence(Decimal sequence);
|
||||
fflib_IAppBindings selectByType(fflib_AppBindingType bindingType);
|
||||
fflib_IAppBindings selectByInterfaceType(System.Type interfaceType);
|
||||
fflib_IAppBindings selectBySharingMode(fflib_SharingMode sharingMode);
|
||||
fflib_IAppBindings selectByNamespacePrefix(String namespacePrefix);
|
||||
|
||||
List<fflib_IAppBinding> getBindings();
|
||||
List<System.Type> getImplementations();
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Layout xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<layoutSections>
|
||||
<customLabel>false</customLabel>
|
||||
<detailHeading>false</detailHeading>
|
||||
<editHeading>true</editHeading>
|
||||
<label>Information</label>
|
||||
<layoutColumns>
|
||||
<layoutItems>
|
||||
<behavior>Required</behavior>
|
||||
<field>MasterLabel</field>
|
||||
</layoutItems>
|
||||
<layoutItems>
|
||||
<behavior>Required</behavior>
|
||||
<field>DeveloperName</field>
|
||||
</layoutItems>
|
||||
<layoutItems>
|
||||
<behavior>Required</behavior>
|
||||
<field>Type__c</field>
|
||||
</layoutItems>
|
||||
</layoutColumns>
|
||||
<layoutColumns>
|
||||
<layoutItems>
|
||||
<behavior>Edit</behavior>
|
||||
<field>IsProtected</field>
|
||||
</layoutItems>
|
||||
<layoutItems>
|
||||
<behavior>Required</behavior>
|
||||
<field>NamespacePrefix</field>
|
||||
</layoutItems>
|
||||
</layoutColumns>
|
||||
<style>TwoColumnsTopToBottom</style>
|
||||
</layoutSections>
|
||||
<layoutSections>
|
||||
<customLabel>true</customLabel>
|
||||
<detailHeading>true</detailHeading>
|
||||
<editHeading>true</editHeading>
|
||||
<label>Binding</label>
|
||||
<layoutColumns>
|
||||
<layoutItems>
|
||||
<behavior>Edit</behavior>
|
||||
<field>BindingObject__c</field>
|
||||
</layoutItems>
|
||||
<layoutItems>
|
||||
<behavior>Edit</behavior>
|
||||
<field>BindingObjectAlternate__c</field>
|
||||
</layoutItems>
|
||||
<layoutItems>
|
||||
<behavior>Edit</behavior>
|
||||
<field>BindingSequence__c</field>
|
||||
</layoutItems>
|
||||
</layoutColumns>
|
||||
<layoutColumns>
|
||||
<layoutItems>
|
||||
<behavior>Edit</behavior>
|
||||
<field>InterfaceType__c</field>
|
||||
</layoutItems>
|
||||
<layoutItems>
|
||||
<behavior>Required</behavior>
|
||||
<field>ImplementationType__c</field>
|
||||
</layoutItems>
|
||||
<layoutItems>
|
||||
<behavior>Required</behavior>
|
||||
<field>SharingMode__c</field>
|
||||
</layoutItems>
|
||||
</layoutColumns>
|
||||
<style>TwoColumnsLeftToRight</style>
|
||||
</layoutSections>
|
||||
<layoutSections>
|
||||
<customLabel>false</customLabel>
|
||||
<detailHeading>false</detailHeading>
|
||||
<editHeading>true</editHeading>
|
||||
<label>System Information</label>
|
||||
<layoutColumns>
|
||||
<layoutItems>
|
||||
<behavior>Readonly</behavior>
|
||||
<field>CreatedById</field>
|
||||
</layoutItems>
|
||||
</layoutColumns>
|
||||
<layoutColumns>
|
||||
<layoutItems>
|
||||
<behavior>Readonly</behavior>
|
||||
<field>LastModifiedById</field>
|
||||
</layoutItems>
|
||||
</layoutColumns>
|
||||
<style>TwoColumnsTopToBottom</style>
|
||||
</layoutSections>
|
||||
<layoutSections>
|
||||
<customLabel>true</customLabel>
|
||||
<detailHeading>true</detailHeading>
|
||||
<editHeading>false</editHeading>
|
||||
<label>Custom Links</label>
|
||||
<layoutColumns/>
|
||||
<layoutColumns/>
|
||||
<layoutColumns/>
|
||||
<style>CustomLinks</style>
|
||||
</layoutSections>
|
||||
<showEmailCheckbox>false</showEmailCheckbox>
|
||||
<showHighlightsPanel>false</showHighlightsPanel>
|
||||
<showInteractionLogPanel>false</showInteractionLogPanel>
|
||||
<showRunAssignmentRulesCheckbox>false</showRunAssignmentRulesCheckbox>
|
||||
<showSubmitAndAttachButton>false</showSubmitAndAttachButton>
|
||||
<summaryLayout>
|
||||
<masterLabel>00h55000002F8hB</masterLabel>
|
||||
<sizeX>4</sizeX>
|
||||
<sizeY>0</sizeY>
|
||||
<summaryLayoutStyle>Default</summaryLayoutStyle>
|
||||
</summaryLayout>
|
||||
</Layout>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<label>Application Binding</label>
|
||||
<pluralLabel>Application Bindings</pluralLabel>
|
||||
<visibility>Public</visibility>
|
||||
</CustomObject>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>BindingObjectAlternate__c</fullName>
|
||||
<description>Use this field to specify the SObject API name to bind to when the "Binding Object" field does not list that particular SObject. Only specify the "Binding Object" field or this one; not both.</description>
|
||||
<externalId>false</externalId>
|
||||
<fieldManageability>SubscriberControlled</fieldManageability>
|
||||
<inlineHelpText>Use this field to specify the SObject API name to bind to when the "Binding Object" field does not list that particular SObject. Only specify the "Binding Object" field or this one; not both.</inlineHelpText>
|
||||
<label>Binding Object Alternate</label>
|
||||
<length>255</length>
|
||||
<required>false</required>
|
||||
<type>Text</type>
|
||||
<unique>false</unique>
|
||||
</CustomField>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>BindingObject__c</fullName>
|
||||
<externalId>false</externalId>
|
||||
<fieldManageability>SubscriberControlled</fieldManageability>
|
||||
<label>Binding Object</label>
|
||||
<referenceTo>EntityDefinition</referenceTo>
|
||||
<relationshipLabel>Bindings</relationshipLabel>
|
||||
<relationshipName>Bindings</relationshipName>
|
||||
<required>false</required>
|
||||
<type>MetadataRelationship</type>
|
||||
<unique>false</unique>
|
||||
</CustomField>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>BindingSequence__c</fullName>
|
||||
<externalId>false</externalId>
|
||||
<fieldManageability>SubscriberControlled</fieldManageability>
|
||||
<label>Binding Sequence</label>
|
||||
<precision>18</precision>
|
||||
<required>false</required>
|
||||
<scale>0</scale>
|
||||
<type>Number</type>
|
||||
<unique>false</unique>
|
||||
</CustomField>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>ImplementationType__c</fullName>
|
||||
<externalId>false</externalId>
|
||||
<fieldManageability>SubscriberControlled</fieldManageability>
|
||||
<label>Implementation Type</label>
|
||||
<length>255</length>
|
||||
<required>true</required>
|
||||
<type>Text</type>
|
||||
<unique>false</unique>
|
||||
</CustomField>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>InterfaceType__c</fullName>
|
||||
<externalId>false</externalId>
|
||||
<fieldManageability>SubscriberControlled</fieldManageability>
|
||||
<label>Interface Type</label>
|
||||
<length>255</length>
|
||||
<required>false</required>
|
||||
<type>Text</type>
|
||||
<unique>false</unique>
|
||||
</CustomField>
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>SharingMode__c</fullName>
|
||||
<defaultValue>"With Sharing"</defaultValue>
|
||||
<externalId>false</externalId>
|
||||
<fieldManageability>DeveloperControlled</fieldManageability>
|
||||
<label>Sharing mode</label>
|
||||
<required>true</required>
|
||||
<type>Picklist</type>
|
||||
<valueSet>
|
||||
<restricted>true</restricted>
|
||||
<valueSetDefinition>
|
||||
<sorted>false</sorted>
|
||||
<value>
|
||||
<fullName>With Sharing</fullName>
|
||||
<default>true</default>
|
||||
<label>With Sharing</label>
|
||||
</value>
|
||||
<value>
|
||||
<fullName>Without Sharing</fullName>
|
||||
<default>false</default>
|
||||
<label>Without Sharing</label>
|
||||
</value>
|
||||
<value>
|
||||
<fullName>Inherited Sharing</fullName>
|
||||
<default>false</default>
|
||||
<label>Inherited Sharing</label>
|
||||
</value>
|
||||
<value>
|
||||
<fullName>None</fullName>
|
||||
<default>false</default>
|
||||
<label>None</label>
|
||||
</value>
|
||||
</valueSetDefinition>
|
||||
</valueSet>
|
||||
</CustomField>
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>Type__c</fullName>
|
||||
<externalId>false</externalId>
|
||||
<fieldManageability>DeveloperControlled</fieldManageability>
|
||||
<inlineHelpText>Type of binding or Logical layers of functionality</inlineHelpText>
|
||||
<label>Binding Type</label>
|
||||
<required>true</required>
|
||||
<type>Picklist</type>
|
||||
<valueSet>
|
||||
<restricted>true</restricted>
|
||||
<valueSetDefinition>
|
||||
<sorted>false</sorted>
|
||||
<value>
|
||||
<fullName>Domain</fullName>
|
||||
<default>true</default>
|
||||
<label>Domain</label>
|
||||
</value>
|
||||
<value>
|
||||
<fullName>Service</fullName>
|
||||
<default>false</default>
|
||||
<label>Service</label>
|
||||
</value>
|
||||
<value>
|
||||
<fullName>Selector</fullName>
|
||||
<default>false</default>
|
||||
<label>Selector</label>
|
||||
</value>
|
||||
<value>
|
||||
<fullName>Controller</fullName>
|
||||
<default>false</default>
|
||||
<label>Controller</label>
|
||||
</value>
|
||||
<value>
|
||||
<fullName>Module</fullName>
|
||||
<default>false</default>
|
||||
<label>Module</label>
|
||||
</value>
|
||||
<value>
|
||||
<fullName>EventListener</fullName>
|
||||
<default>false</default>
|
||||
<label>Event Listener</label>
|
||||
</value>
|
||||
<value>
|
||||
<fullName>Miscellaneous</fullName>
|
||||
<default>false</default>
|
||||
<label>Miscellaneous</label>
|
||||
</value>
|
||||
</valueSetDefinition>
|
||||
</valueSet>
|
||||
</CustomField>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ListView xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>All</fullName>
|
||||
<columns>MasterLabel</columns>
|
||||
<columns>BindingObject__c</columns>
|
||||
<columns>BindingObjectAlternate__c</columns>
|
||||
<columns>BindingSequence__c</columns>
|
||||
<columns>InterfaceType__c</columns>
|
||||
<columns>ImplementationType__c</columns>
|
||||
<filterScope>Everything</filterScope>
|
||||
<label>All</label>
|
||||
</ListView>
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ValidationRule xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>BindObj_Or_BindObjAlt</fullName>
|
||||
<active>true</active>
|
||||
<description>This validation rule ensures that only the "Binding Object" or the "Binding Object Alternate" field is specified and not both.</description>
|
||||
<errorConditionFormula>NOT( ISBLANK( BindingObject__c ) ) && NOT( ISBLANK( BindingObjectAlternate__c ) )</errorConditionFormula>
|
||||
<errorMessage>Only specify the "Binding Object" field or the "Binding Object Alternate" field; not both.</errorMessage>
|
||||
</ValidationRule>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ValidationRule xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<fullName>Require_Interface_Type_For_Services</fullName>
|
||||
<active>true</active>
|
||||
<description>An Interface Type is required for Service class Bindings</description>
|
||||
<errorConditionFormula>AND(ISPICKVAL(Type__c,"Service"), ISBLANK( InterfaceType__c ) )</errorConditionFormula>
|
||||
<errorDisplayField>ImplementationType__c</errorDisplayField>
|
||||
<errorMessage>An Interface Type is required for Service class Bindings</errorMessage>
|
||||
</ValidationRule>
|
||||
+2
-2
@@ -42,7 +42,7 @@ public interface fflib_IDomainFactory
|
||||
**/
|
||||
fflib_IDomain newInstance(Set<Id> recordIds);
|
||||
|
||||
fflib_IDomain newInstance(Set<Id> recordIds, Schema.SObjectType objectType);
|
||||
fflib_IDomain newInstance(Set<Id> recordIds, Schema.SObjectType sObjectType);
|
||||
|
||||
/**
|
||||
* Dynamically constructs an instance of the Domain class for the given records
|
||||
@@ -95,5 +95,5 @@ public interface fflib_IDomainFactory
|
||||
* avoids the need to stub the mock to return its ObjectType
|
||||
* @param mockDomain The instance of the Domain mock
|
||||
*/
|
||||
void setMock(Type domainType, fflib_IDomain mockDomain);
|
||||
void setMock(Object domainType, fflib_IDomain mockDomain);
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* File Name: fflib_DynamicDomainFactoryTest
|
||||
* Description:
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
@IsTest(IsParallel=true)
|
||||
public class fflib_DynamicDomainFactoryTest
|
||||
{
|
||||
private static final fflib_IAppBindingResolver bindingResolver =
|
||||
new fflib_AppBindingResolver();
|
||||
|
||||
|
||||
private static final fflib_IDomainFactory Domain =
|
||||
new fflib_DynamicDomainFactory(
|
||||
bindingResolver,
|
||||
fflib_DynamicSelectorFactoryTest.Selector);
|
||||
private static final SObjectType ACCOUNT_OBJECT_TYPE = Schema.Account.SObjectType;
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnDomain()
|
||||
{
|
||||
// Mock the App Bindings selector
|
||||
fflib_AppBindingsSelector.SELECTOR_IMPL_TYPE = AppBindingsSelectorMock.class;
|
||||
final List<Account> records = generateAccountRecords();
|
||||
|
||||
System.Test.startTest();
|
||||
Object instance = Domain.newInstance(records);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(instance instanceof fflib_SObjects);
|
||||
}
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnDomainById()
|
||||
{
|
||||
// Mock the App Bindings selector
|
||||
fflib_AppBindingsSelector.SELECTOR_IMPL_TYPE = AppBindingsSelectorMock.class;
|
||||
|
||||
final List<Account> records = generateAccountRecords();
|
||||
final Set<Id> ids = new fflib_SObjects(records).getRecordIds();
|
||||
|
||||
fflib_ApexMocks mocks = new fflib_ApexMocks();
|
||||
fflib_ISObjectSelector selectorMock = (fflib_ISObjectSelector) mocks.mock(fflib_ISObjectSelector.class);
|
||||
mocks.startStubbing();
|
||||
mocks.when(selectorMock.selectSObjectsById(ids)).thenReturn(records);
|
||||
mocks.stopStubbing();
|
||||
|
||||
fflib_DynamicSelectorFactoryTest.Selector.setMock(ACCOUNT_OBJECT_TYPE, selectorMock);
|
||||
|
||||
System.Test.startTest();
|
||||
Object instance = Domain.newInstance(ids);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(instance instanceof fflib_SObjects);
|
||||
System.assertEquals(records, ((fflib_SObjects) instance).getRecords());
|
||||
}
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheMockDomain()
|
||||
{
|
||||
// Mock the App Bindings selector
|
||||
fflib_AppBindingsSelector.SELECTOR_IMPL_TYPE = AppBindingsSelectorMock.class;
|
||||
|
||||
final List<Account> records = generateAccountRecords();
|
||||
final Set<Id> ids = new fflib_SObjects(records).getRecordIds();
|
||||
|
||||
fflib_ApexMocks mocks = new fflib_ApexMocks();
|
||||
fflib_SObjects domainMock = (fflib_SObjects) mocks.mock(fflib_SObjects.class);
|
||||
|
||||
mocks.startStubbing();
|
||||
mocks.when(domainMock.getType()).thenReturn(ACCOUNT_OBJECT_TYPE);
|
||||
mocks.when(domainMock.getRecords()).thenReturn(new List<Account>());
|
||||
mocks.stopStubbing();
|
||||
|
||||
System.Test.startTest();
|
||||
fflib_SObjects instanceA = (fflib_SObjects) Domain.newInstance(records);
|
||||
Domain.setMock(domainMock);
|
||||
fflib_SObjects instanceB = (fflib_SObjects) Domain.newInstance(records, ACCOUNT_OBJECT_TYPE);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assertEquals(records, instanceA.getRecords());
|
||||
System.assert(instanceB.getRecords().isEmpty());
|
||||
}
|
||||
|
||||
|
||||
private static List<Account> generateAccountRecords()
|
||||
{
|
||||
List<Account> records = new List<Account>
|
||||
{
|
||||
new Account(Id = fflib_IDGenerator.generate(ACCOUNT_OBJECT_TYPE)),
|
||||
new Account(Id = fflib_IDGenerator.generate(ACCOUNT_OBJECT_TYPE)),
|
||||
new Account(Id = fflib_IDGenerator.generate(ACCOUNT_OBJECT_TYPE))
|
||||
};
|
||||
return records;
|
||||
}
|
||||
|
||||
|
||||
public class MyDomainConstructor implements fflib_IDomainConstructor
|
||||
{
|
||||
public fflib_IDomain construct(List<Object> objects)
|
||||
{
|
||||
return new fflib_SObjects((List<SObject>) objects);
|
||||
}
|
||||
}
|
||||
|
||||
private class AppBindingsSelectorMock extends fflib_AppBindingsSelector
|
||||
{
|
||||
public override List<fflib_AppBinding__mdt> selectAll()
|
||||
{
|
||||
return new List<fflib_AppBinding__mdt>
|
||||
{
|
||||
new fflib_AppBinding__mdt(
|
||||
Type__c = 'Domain',
|
||||
BindingObject__c = '',
|
||||
BindingObjectAlternate__c = ACCOUNT_OBJECT_TYPE.getDescribe().getName(),
|
||||
ImplementationType__c = MyDomainConstructor.class.getName(),
|
||||
SharingMode__c = 'None'
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* File Name: fflib_DynamicSelectorFactoryTest
|
||||
* Description:
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
@IsTest(IsParallel=true)
|
||||
public class fflib_DynamicSelectorFactoryTest
|
||||
{
|
||||
|
||||
private static fflib_IAppBindingResolver bindingResolver =
|
||||
new fflib_AppBindingResolver();
|
||||
|
||||
@TestVisible
|
||||
private static final fflib_ISelectorFactory Selector =
|
||||
new fflib_DynamicSelectorFactory(bindingResolver)
|
||||
.setSharingMode(fflib_SharingMode.WithSharing);
|
||||
|
||||
private static final Type MY_SELECTOR_TYPE = fflib_DynamicSelectorFactoryTest.MySelector.class;
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheSelectorByBindingObject()
|
||||
{
|
||||
// Mock the App Bindings selector
|
||||
fflib_AppBindingsSelector.SELECTOR_IMPL_TYPE = AppBindingsSelectorMock.class;
|
||||
|
||||
System.Test.startTest();
|
||||
Object instance = Selector.newInstance(Schema.Account.SObjectType);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(instance instanceof fflib_DynamicSelectorFactoryTest.MySelector);
|
||||
}
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheAlternativeSelector()
|
||||
{
|
||||
// Mock the App Bindings selector
|
||||
fflib_AppBindingsSelector.SELECTOR_IMPL_TYPE = AppBindingsSelectorMock.class;
|
||||
|
||||
System.Test.startTest();
|
||||
Object instanceA = Selector.newInstance(Schema.Account.SObjectType);
|
||||
Selector.replaceWith(Schema.Account.SObjectType, MyMockSelector.class);
|
||||
Object instanceB = Selector.newInstance(Schema.Account.SObjectType);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(instanceA instanceof fflib_DynamicSelectorFactoryTest.MySelector);
|
||||
System.assert(instanceB instanceof fflib_DynamicSelectorFactoryTest.MyMockSelector);
|
||||
}
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheRecordsById()
|
||||
{
|
||||
Id id = fflib_IDGenerator.generate(Schema.Account.SObjectType);
|
||||
Set<Id> ids = new Set<Id>{ id };
|
||||
final List<Account> records = new List<Account>{ new Account(Name='Test') };
|
||||
|
||||
fflib_ApexMocks mocks = new fflib_ApexMocks();
|
||||
fflib_ISObjectSelector selectorMock = (fflib_ISObjectSelector) mocks.mock(fflib_ISObjectSelector.class);
|
||||
mocks.startStubbing();
|
||||
mocks.when(selectorMock.selectSObjectsById(ids)).thenReturn(records);
|
||||
mocks.stopStubbing();
|
||||
|
||||
Selector.setMock(Schema.Account.SObjectType, selectorMock);
|
||||
|
||||
System.Test.startTest();
|
||||
List<SObject> result = Selector.selectById(ids);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(result == records);
|
||||
((fflib_ISObjectSelector) mocks.verify(selectorMock)).selectSObjectsById(ids);
|
||||
}
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheRecordsByRelatedId()
|
||||
{
|
||||
Id id = fflib_IDGenerator.generate(Schema.Account.SObjectType);
|
||||
Set<Id> ids = new Set<Id>{ id };
|
||||
final List<Account> accounts = new List<Account>{ new Account(Id = id, Name='Test') };
|
||||
final List<Contact> contacts = new List<Contact> { new Contact(AccountId = id)};
|
||||
|
||||
fflib_ApexMocks mocks = new fflib_ApexMocks();
|
||||
fflib_ISObjectSelector selectorMock = (fflib_ISObjectSelector) mocks.mock(fflib_ISObjectSelector.class);
|
||||
mocks.startStubbing();
|
||||
mocks.when(selectorMock.sObjectType()).thenReturn(Schema.Account.SObjectType);
|
||||
mocks.when(selectorMock.selectSObjectsById(ids)).thenReturn(accounts);
|
||||
mocks.stopStubbing();
|
||||
|
||||
Selector.setMock(selectorMock);
|
||||
|
||||
System.Test.startTest();
|
||||
List<SObject> result = Selector.selectByRelationship(contacts, Schema.Contact.AccountId);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(result == accounts);
|
||||
((fflib_ISObjectSelector) mocks.verify(selectorMock)).selectSObjectsById(ids);
|
||||
}
|
||||
|
||||
public interface IMySelector extends fflib_ISObjectSelector {}
|
||||
|
||||
private abstract class MySelectorAbstract extends fflib_SObjectSelector implements IMySelector
|
||||
{
|
||||
public List<Schema.SObjectField> getSObjectFieldList()
|
||||
{
|
||||
return new List<Schema.SObjectField>{ Account.Id, Account.Name };
|
||||
}
|
||||
|
||||
public SObjectType getSObjectType()
|
||||
{
|
||||
return Schema.Account.SObjectType;
|
||||
}
|
||||
}
|
||||
|
||||
public class MySelector extends MySelectorAbstract {}
|
||||
public class MyMockSelector extends MySelectorAbstract {}
|
||||
|
||||
private class AppBindingsSelectorMock extends fflib_AppBindingsSelector
|
||||
{
|
||||
public override List<fflib_AppBinding__mdt> selectAll()
|
||||
{
|
||||
return new List<fflib_AppBinding__mdt>
|
||||
{
|
||||
new fflib_AppBinding__mdt(
|
||||
Type__c = 'Selector',
|
||||
BindingObject__c = '',
|
||||
BindingObjectAlternate__c = Schema.Account.SObjectType.getDescribe().getName(),
|
||||
ImplementationType__c = MY_SELECTOR_TYPE.getName(),
|
||||
SharingMode__c = 'With Sharing'
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* File Name: fflib_DynamicServiceFactoryTest
|
||||
* Description:
|
||||
*
|
||||
* @author : architect ir. Wilhelmus G.J. Velzeboer
|
||||
*
|
||||
* Copyright (c), W.G.J. Velzeboer,
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above author notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
@IsTest(IsParallel=true)
|
||||
public class fflib_DynamicServiceFactoryTest
|
||||
{
|
||||
private static final Type MY_SERVICE_INTERFACE_TYPE = fflib_DynamicServiceFactoryTest.IMyService.class;
|
||||
private static final Type MY_SERVICE_TYPE = fflib_DynamicServiceFactoryTest.MyService.class;
|
||||
private static final Type MY_ALT_SERVICE_TYPE = fflib_DynamicServiceFactoryTest.MyALtService.class;
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheCorrectInstance()
|
||||
{
|
||||
fflib_AppBindingModule module = new fflib_AppBindingModule();
|
||||
module.addBinding(createBindingForMyService());
|
||||
bindingResolver.addModule(module);
|
||||
|
||||
System.Test.startTest();
|
||||
Object instance = Service.newInstance(MY_SERVICE_TYPE);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(instance instanceof fflib_DynamicServiceFactoryTest.MyService);
|
||||
}
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheAlternativeInstance()
|
||||
{
|
||||
fflib_AppBindingModule module = new fflib_AppBindingModule();
|
||||
module.addBinding(createBindingForMyService());
|
||||
bindingResolver.addModule(module);
|
||||
Service.replaceWith(MyService.class, MyAltService.class);
|
||||
|
||||
System.Test.startTest();
|
||||
Object instance = Service.newInstance(MY_SERVICE_TYPE);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(instance instanceof fflib_DynamicServiceFactoryTest.MyAltService);
|
||||
}
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheMockInstance()
|
||||
{
|
||||
fflib_AppBindingModule module = new fflib_AppBindingModule();
|
||||
module.addBinding(createBindingForMyService());
|
||||
bindingResolver.addModule(module);
|
||||
IMyService mock = new MyAltService();
|
||||
Service.setMock(MyService.class, mock);
|
||||
|
||||
System.Test.startTest();
|
||||
Object instance = Service.newInstance(MY_SERVICE_TYPE);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(instance instanceof fflib_DynamicServiceFactoryTest.MyAltService);
|
||||
}
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheFirstBindingInstance()
|
||||
{
|
||||
fflib_AppBindingsSelector.SELECTOR_IMPL_TYPE = AppBindingsSelectorMock.class;
|
||||
|
||||
System.Test.startTest();
|
||||
Object instance = Service.newInstance(MY_SERVICE_INTERFACE_TYPE);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(instance instanceof fflib_DynamicServiceFactoryTest.MyService);
|
||||
}
|
||||
|
||||
@IsTest
|
||||
static void itShouldReturnTheSecondBindingInstance()
|
||||
{
|
||||
fflib_AppBindingsSelector.SELECTOR_IMPL_TYPE = reverseAppBindingsSelectorMock.class;
|
||||
|
||||
System.Test.startTest();
|
||||
Object instance = Service.newInstance(MY_SERVICE_INTERFACE_TYPE);
|
||||
System.Test.stopTest();
|
||||
|
||||
System.assert(instance instanceof fflib_DynamicServiceFactoryTest.MyAltService);
|
||||
}
|
||||
|
||||
|
||||
private static fflib_AppBinding createBindingForMyService()
|
||||
{
|
||||
fflib_AppBinding result = new fflib_AppBinding();
|
||||
|
||||
result.setBindingType(fflib_AppBindingType.Service);
|
||||
result.setInterfaceType(MY_SERVICE_TYPE);
|
||||
result.setImplementationType(MY_SERVICE_TYPE);
|
||||
result.setSharingMode(fflib_SharingMode.WithSharing);
|
||||
result.setSequence(2);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static fflib_AppBinding createBindingForMyAltService()
|
||||
{
|
||||
fflib_AppBinding result = createBindingForMyService();
|
||||
result.setImplementationType(MyAltService.class);
|
||||
result.setSequence(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static fflib_IAppBindingResolver bindingResolver =
|
||||
new fflib_AppBindingResolver();
|
||||
|
||||
private static final fflib_IServiceFactory Service =
|
||||
new fflib_DynamicServiceFactory(bindingResolver)
|
||||
.setSharingMode(fflib_SharingMode.WithSharing);
|
||||
|
||||
public interface IMyService {}
|
||||
|
||||
public class MyService implements IMyService { }
|
||||
|
||||
public class MyAltService implements IMyService { }
|
||||
|
||||
private class AppBindingsSelectorMock extends fflib_AppBindingsSelector
|
||||
{
|
||||
public override List<fflib_AppBinding__mdt> selectAll()
|
||||
{
|
||||
return new List<fflib_AppBinding__mdt>
|
||||
{
|
||||
new fflib_AppBinding__mdt(
|
||||
Type__c = 'Service',
|
||||
InterfaceType__c = MY_SERVICE_INTERFACE_TYPE.getName(),
|
||||
ImplementationType__c = MY_SERVICE_TYPE.getName(),
|
||||
SharingMode__c = 'With Sharing',
|
||||
BindingSequence__c = 1
|
||||
),
|
||||
new fflib_AppBinding__mdt(
|
||||
Type__c = 'Service',
|
||||
InterfaceType__c = MY_SERVICE_INTERFACE_TYPE.getName(),
|
||||
ImplementationType__c = MY_ALT_SERVICE_TYPE.getName(),
|
||||
SharingMode__c = 'With Sharing',
|
||||
BindingSequence__c = 2
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class reverseAppBindingsSelectorMock extends fflib_AppBindingsSelector
|
||||
{
|
||||
public override List<fflib_AppBinding__mdt> selectAll()
|
||||
{
|
||||
return new List<fflib_AppBinding__mdt>
|
||||
{
|
||||
new fflib_AppBinding__mdt(
|
||||
Type__c = 'Service',
|
||||
InterfaceType__c = MY_SERVICE_INTERFACE_TYPE.getName(),
|
||||
ImplementationType__c = MY_SERVICE_TYPE.getName(),
|
||||
SharingMode__c = 'With Sharing',
|
||||
BindingSequence__c = 2
|
||||
),
|
||||
new fflib_AppBinding__mdt(
|
||||
Type__c = 'Service',
|
||||
InterfaceType__c = MY_SERVICE_INTERFACE_TYPE.getName(),
|
||||
ImplementationType__c = MY_ALT_SERVICE_TYPE.getName(),
|
||||
SharingMode__c = 'With Sharing',
|
||||
BindingSequence__c = 1
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>51.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
Reference in New Issue
Block a user