ERP Core

fferpcore.SubscriptionDescription

global class SubscriptionDescription implements LinkingMessageToObjectMarshaller, LinkingMessageToObjectMarshaller2

Contains the information and methods necessary to enable a subscription to handle an incoming message and update records accordingly. The data is transformed (Marshalled) into a format suitable for the subscribing product using Mappings. You can extend mappings to carry out complex operations on records before the final version of the records are produced.

This class implements the following interfaces:

Methods

SubscriptionDescription

global SubscriptionDescription(SObjectType context)

Constructor that specifies the object to be updated by the messages.

Input Parameters

Name Type Description
context SObjectType The object to be updated by the messages.

SubscriptionDescription

global SubscriptionDescription(SObjectType context, List<fferpcore.SubscriptionDescription.Mapping> mappings)

Constructor that specifies the object to be updated by the messages and mappings to be applied to the message fields.

Input Parameters

Name Type Description
context SObjectType The object to be updated by the messages.
mappings List<fferpcore.SubscriptionDescription.Mapping> List of mappings to be applied when updating the target object.

addMappings

global void addMappings(List<fferpcore.SubscriptionDescription.Mapping> mappings)

Add mappings to the description. Mappings are executed in order, allowing later mappings to override work done by earlier mappings.

Input Parameters

Name Type Description
mappings List<fferpcore.SubscriptionDescription.Mapping> The mappings to be added.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class ConcreteDescriber extends fferpcore.SubscriptionDescriber
{
    private static final SObjectType SOBJECT_TYPE = ExampleSObject__c.SObjectType;

    public override fferpcore.SubscriptionDescription describe()
    {
        fferpcore.SubscriptionDescription description = new fferpcore.SubscriptionDescription(SOBJECT_TYPE);
        description.addMappings(getStaticMappings());
        return description;
    }
    
    private List<fferpcore.SubscriptionDescription.Mapping> getStaticMappings()
    {
        return new List<fferpcore.SubscriptionDescription.Mapping>
        {
            new fferpcore.SubscriptionDescription.FieldMapping(ExampleSObject__c.Name, 'Name'),
            new fferpcore.SubscriptionDescription.FieldMapping(ExampleSObject__c.Address1__c, new List<String>{'Address', 'Line 1'}),
            new fferpcore.SubscriptionDescription.FieldMapping(ExampleSObject__c.Address2__c, new List<String>{'Address', 'Line 2'}),
            new fferpcore.SubscriptionDescription.LinkingFieldMapping(SOBJECT_TYPE, 'Link Control Field')
        };
    }
}

createStaticRecordTypeMapping

global static fferpcore.SubscriptionDescription.Mapping createStaticRecordTypeMapping(String recordTypeName, SObjectType objectType)

Creates a StaticRecordTypeMapping that applies the record type with the given name and SObjectType.

Input Parameters

Name Type Description
recordTypeName String The name of the record type.
objectType SObjectType The SObjectType of the record type.

Return Value

A mapping that can be used in a SubscriptionDescriber.

createStaticMapping

global static fferpcore.SubscriptionDescription.Mapping createStaticMapping(Object data, SObjectField targetField)

Creates a StaticMapping that applies the given data to the specified field.

Input Parameters

Name Type Description
data Object The data to populate the field with.
targetField SObjectField The field that will be populated with the data.

Return Value

A mapping that can be used in a SubscriptionDescriber.

createLookupRecordTypeMapping

global static fferpcore.SubscriptionDescription.Mapping createLookupRecordTypeMapping(List<String> messageKey, SObjectType lookupObjectType, SObjectField lookupField, SObjectField resultField, SObjectType recordTypeObjectType)

Creates a LookupRecordTypeMapping that locates a record belonging to the given SObjectType where the value on the given lookup field matches the value at the given message key. The value on the result field of the record is in turn used to locate a matching record type for the given record type SObjectType, which is subsequently applied to the record.

Input Parameters

Name Type Description
messageKey List<String> The key within the message where the lookup value is located.
lookupObjectType SObjectType The SObjectType on which to locate a record.
lookupField SObjectField The SObjectField used to locate the record.
resultField SObjectField The SObjectField in which the record type name is located.
recordTypeObjectType SObjectType The SObjectType of the record type.

Return Value

A mapping that can be used in a SubscriptionDescriber.

createDataTransformationRecordTypeMapping

global static fferpcore.SubscriptionDescription.Mapping createDataTransformationRecordTypeMapping(List<List<String>> messageKeys, Id transformTableId, SObjectType objectType)

Creates a DataTransformationRecordTypeMapping that extracts the data at the specified keys within the message, transforms it using the specified transformation table, and finally applies the record type with the matching name for the given SObjectType.

Input Parameters

Name Type Description
messageKeys List<List<String>> The keys within the message where the data is located.
transformTableId Id The ID of the transformation table.
objectType SObjectType The SObjectType of the record type.

Return Value

A mapping that can be used in a SubscriptionDescriber.

createRecordTypeMapping

global static fferpcore.SubscriptionDescription.Mapping createRecordTypeMapping(List<String> messageKey, SObjectType objectType)

Creates a RecordTypeMapping that applies a record type for the given SObjectType with the name matching the data at the specified key within the message.

Input Parameters

Name Type Description
messageKey List<String> The key within the message where the record type name is located.
objectType SObjectType The SObjectType of the record type.

Return Value

A mapping that can be used in a SubscriptionDescriber.

createDataTransformationLookupMapping

global static fferpcore.SubscriptionDescription.Mapping createDataTransformationLookupMapping(SObjectField targetField, List<List<String>> messageKeys, Id transformTableId, SObjectType relatedObjectType)

Create a DataTransformationLookupMapping that can take 1 or 2 message keys to transform using the DataTransformationTable designated by the transformTableId. The result from the transformation is then used to lookup a record using the designated name field on a related object. The Id is then applied to the targetField.

Input Parameters

Name Type Description
targetField SObjectField The field that should be populated with the result of the lookup.
messageKeys List<List<String>> A list of string lists that correspond to the keys in the message.
transformTableId Id The Id for the DataTransformationTable that should be used to perform the transformation.
relatedObjectType SObjectType The type of the related SObject on which to lookup the Id.

Return Value

A mapping that can be used in a SubscriptionDescriber.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class PSAResourceUpdateSubscriptionDescriber extends fferpcore.SubscriptionDescriber
{
    private static final SObjectType SOBJECT_TYPE = PSAFakeResource__c.SObjectType;

    public static final String NAME_KEY = 'Name';
    public static final String JOB_TITLE_KEY = 'JobTitle';

    public static final String[] JOB_TITLE_PATH = new String[]{JOB_TITLE_KEY};
    public static final Id JOB_TITLE_TRANSFORMATION_TABLE_ID = getJobTitleTransformationTableId();

    public override fferpcore.SubscriptionDescription describe()
    {
        return new fferpcore.SubscriptionDescription(SOBJECT_TYPE, getStaticMappings());
    }

    private List<fferpcore.SubscriptionDescription.Mapping> getStaticMappings()
    {
        
        return new List<fferpcore.SubscriptionDescription.Mapping>
        {
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Name, NAME_KEY),

            //Take the JobTitle from the message, do a transformation to convert it to a role, the look up the role and put the role ID on the resource.
            fferpcore.SubscriptionDescription.createDataTransformationLookupMapping(
                PSAFakeResource__c.Role__c,
                new List<List<String>>{JOB_TITLE_PATH},
                JOB_TITLE_TRANSFORMATION_TABLE_ID,
                PSAFakeRole__c),        
        };
    }
}

createDataTransformationLookupMapping

global static fferpcore.SubscriptionDescription.Mapping createDataTransformationLookupMapping(SObjectField targetField, List<List<String>> messageKeys, Id transformTableId, SObjectType relatedObjectType, SObjectField relatedLookupField, SObjectField relatedResultField)

Create a DataTransformationLookupMapping that can take 1 or 2 message keys to transform using the DataTransformationTable designated by the transformTableId. The result from the transformation is then used to lookup a record using the designated relatedLookupField field on a related object. The contents of relatedResultField is then applied to the targetField.

Input Parameters

Name Type Description
targetField SObjectField The field that should be populated with the result of the lookup.
messageKeys List<List<String>> A list of string lists that correspond to the keys in the message.
transformTableId Id The Id for the DataTransformationTable that should be used to perform the transformation.
relatedObjectType SObjectType The type of the related SObject on which to lookup the Id.
relatedLookupField SObjectField The field on the related object to lookup with data from the message key.
relatedResultField SObjectField The field that contains the data that should be applied to the target field.

Return Value

A mapping that can be used in a SubscriptionDescriber.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class PSAResourceUpdateSubscriptionDescriber extends fferpcore.SubscriptionDescriber
{
    private static final SObjectType SOBJECT_TYPE = PSAFakeResource__c.SObjectType;

    public static final String NAME_KEY = 'Name';
    public static final String JOB_TITLE_KEY = 'JobTitle';

    public static final String[] JOB_TITLE_PATH = new String[]{JOB_TITLE_KEY};
    public static final Id JOB_TITLE_TRANSFORMATION_TABLE_ID = getJobTitleTransformationTableId();

    public override fferpcore.SubscriptionDescription describe()
    {
        return new fferpcore.SubscriptionDescription(SOBJECT_TYPE, getStaticMappings());
    }

    private List<fferpcore.SubscriptionDescription.Mapping> getStaticMappings()
    {
        
        return new List<fferpcore.SubscriptionDescription.Mapping>
        {
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Name, NAME_KEY),

            //Take the JobTitle from the message, do a transformation to convert it to a role, then look up the role using the role name, and put the primary area on the resource
            fferpcore.SubscriptionDescription.createDataTransformationLookupMapping(
                PSAFakeResource__c.Role__c,
                new List<List<String>>{JOB_TITLE_PATH},
                JOB_TITLE_TRANSFORMATION_TABLE_ID,
                PSAFakeRole__c,
                PSAFakeRole__c.Name,
                PSAFakeRole__c.PrimaryArea__c)        
        };
    }
}

createDataTransformationMapping

global static fferpcore.SubscriptionDescription.Mapping createDataTransformationMapping(SObjectField targetField, List<List<String>> messageKeys, Id transformTableId)

Create a TransformationMapping that can take 1 or 2 message keys to transform using the DataTransformationTable designated by the transformTableId. The result from the transformation is then applied to the target field on the target object.

Input Parameters

Name Type Description
targetField SObjectField The field that should be populated with the result of the data transformation.
messageKeys List<List<String>> A list of string lists that correspond to the keys in the message.
transformTableId Id The Id for the DataTransformationTable that should be used to perform the transformation.

Return Value

A mapping that can be used in a SubscriptionDescriber.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class PSAResourceUpdateSubscriptionDescriber extends fferpcore.SubscriptionDescriber
{
    private static final SObjectType SOBJECT_TYPE = PSAFakeResource__c.SObjectType;

    public static final String NAME_KEY = 'Name';
    public static final String JOB_TITLE_KEY = 'JobTitle';
    public static final String[] JOB_TITLE_PATH = new String[]{JOB_TITLE_KEY};
    public static final Id JOB_TITLE_TRANSFORMATION_TABLE_ID = getJobTitleTransformationTableId();

    public override fferpcore.SubscriptionDescription describe()
    {
        return new fferpcore.SubscriptionDescription(SOBJECT_TYPE, getStaticMappings());
    }

    private List<fferpcore.SubscriptionDescription.Mapping> getStaticMappings()
    {
        
        return new List<fferpcore.SubscriptionDescription.Mapping>
        {
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Name, NAME_KEY),

            //Take the JobTitle from the message and apply a mapping to a role.
            fferpcore.SubscriptionDescription.createDataTransformationMapping(
                PSAFakeResource__c.RoleName__c,
                new List<List<String>>{JOB_TITLE_PATH},
                JOB_TITLE_TRANSFORMATION_TABLE_ID
            )        
        };
    }
}

createLookupMapping

global static fferpcore.SubscriptionDescription.Mapping createLookupMapping(SObjectField targetField, List<String> messageKey, SObjectType relatedObjectType)

Create a LookupMapping that takes a message key which is used to lookup a record using the designated name field on a related object. The id of the related record is then applied to the targetField.

Input Parameters

Name Type Description
targetField SObjectField The field that should be populated with the result of the lookup.
messageKey List<String> A list of strings that correspond to the key in the message.
relatedObjectType SObjectType The type of the related SObject on which to lookup the Id.

Return Value

A mapping that can be used in a SubscriptionDescriber.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class PSAResourceUpdateSubscriptionDescriber extends fferpcore.SubscriptionDescriber
{
    private static final SObjectType SOBJECT_TYPE = PSAFakeResource__c.SObjectType;

    public static final String NAME_KEY = 'Name';
    public static final String DEPARTMENT_KEY = 'Department';
    public static final String DEPARTMENT_NAME_KEY = 'Name';
    public static final String[] DEPARTMENT_NAME_PATH = new String[]{DEPARTMENT_KEY, DEPARTMENT_NAME_KEY};

    public override fferpcore.SubscriptionDescription describe()
    {
        return new fferpcore.SubscriptionDescription(SOBJECT_TYPE, getStaticMappings());
    }

    private List<fferpcore.SubscriptionDescription.Mapping> getStaticMappings()
    {
        
        return new List<fferpcore.SubscriptionDescription.Mapping>
        {
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Name, NAME_KEY),

            //Put the department ID in the Department field
            fferpcore.SubscriptionDescription.createLookupMapping(PSAFakeResource__c.Department__c, DEPARTMENT_NAME_PATH, PSAFakeDepartment__c.SObjectType)        
        };
    }
}

createLookupMapping

global static fferpcore.SubscriptionDescription.Mapping createLookupMapping(SObjectField targetField, List<String> messageKey, SObjectType relatedObjectType, SObjectField relatedLookupField, SObjectField relatedResultField)

Create a LookupMapping that takes a message key which is used to lookup a record using the designated relatedLookupField field on a related object. The contents of relatedResultField is then applied to the targetField.

Input Parameters

Name Type Description
targetField SObjectField The field that should be populated with the result of the lookup.
messageKey List<String> A list of strings that correspond to the key in the message.
relatedObjectType SObjectType The type of the related SObject on which to lookup the Id.
relatedLookupField SObjectField The field on the related object to lookup with data from the message key.
relatedResultField SObjectField The field that contains the data that should be applied to the target field.

Return Value

A mapping that can be used in a SubscriptionDescriber.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class PSAResourceUpdateSubscriptionDescriber extends fferpcore.SubscriptionDescriber
{
    private static final SObjectType SOBJECT_TYPE = PSAFakeResource__c.SObjectType;

    public static final String NAME_KEY = 'Name';
    public static final String DEPARTMENT_KEY = 'Department';
    public static final String DEPARTMENT_NAME_KEY = 'Name';
    public static final String[] DEPARTMENT_NAME_PATH = new String[]{DEPARTMENT_KEY, DEPARTMENT_NAME_KEY};

    public override fferpcore.SubscriptionDescription describe()
    {
        return new fferpcore.SubscriptionDescription(SOBJECT_TYPE, getStaticMappings());
    }

    private List<fferpcore.SubscriptionDescription.Mapping> getStaticMappings()
    {
        
        return new List<fferpcore.SubscriptionDescription.Mapping>
        {
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Name, NAME_KEY),

            //Look up the department name, and set the department building on our resource.
            fferpcore.SubscriptionDescription.createLookupMapping(
                PSAFakeResource__c.DepartmentBuilding__c, 
                DEPARTMENT_NAME_PATH, 
                PSAFakeDepartment__c.SObjectType, 
                PSAFakeDepartment__c.Name, 
                PSAFakeDepartment__c.Building),    
        };
    }
}

createFieldMapping

global static fferpcore.SubscriptionDescription.Mapping createFieldMapping(SObjectField targetField, List<String> messageKey)

Create a FieldMapping that takes one message key to populate the target field with.

Input Parameters

Name Type Description
targetField SObjectField The field that should be populated.
messageKey List<String> A list of strings that correspond to the key in the message.

Return Value

A mapping that can be used in a SubscriptionDescriber.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class PSAResourceUpdateSubscriptionDescriber extends fferpcore.SubscriptionDescriber
{
    private static final SObjectType SOBJECT_TYPE = PSAFakeResource__c.SObjectType;

    public static final String NAME_KEY = 'Name';
    public static final String ADDRESS_KEY = 'Address';
    public static final String ADDRESS_LINE_1_KEY = 'Line 1';
    public static final String ADDRESS_LINE_2_KEY = 'Line 2';
    public static final String ADDRESS_LINE_3_KEY = 'Line 3';
    public static final String ADDRESS_LINE_4_KEY = 'Line 4';
    public static final String TELEPHONE_KEY = 'Telephone';

    public static final String[] ADDRESS_LINE_1_PATH = new String[]{ADDRESS_KEY, ADDRESS_LINE_1_KEY};
    public static final String[] ADDRESS_LINE_2_PATH = new String[]{ADDRESS_KEY, ADDRESS_LINE_2_KEY};
    public static final String[] ADDRESS_LINE_3_PATH = new String[]{ADDRESS_KEY, ADDRESS_LINE_3_KEY};
    public static final String[] ADDRESS_LINE_4_PATH = new String[]{ADDRESS_KEY, ADDRESS_LINE_4_KEY};

    public override fferpcore.SubscriptionDescription describe()
    {
        return new fferpcore.SubscriptionDescription(SOBJECT_TYPE, getStaticMappings());
    }

    private List<fferpcore.SubscriptionDescription.Mapping> getStaticMappings()
    {
        
        return new List<fferpcore.SubscriptionDescription.Mapping>
        {
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Name, NAME_KEY),
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Phone__c, TELEPHONE_KEY),
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Address1__c, ADDRESS_LINE_1_PATH),
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Address2__c, ADDRESS_LINE_2_PATH),
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Address3__c, ADDRESS_LINE_3_PATH),
            fferpcore.SubscriptionDescription.createFieldMapping(PSAFakeResource__c.Address4__c, ADDRESS_LINE_4_PATH),
        };
    }
}

fferpcore.SubscriptionDescription.ApplyMappingRequest

global abstract class ApplyMappingRequest

A request to apply a mapping to a record. A fferpcore.SubscriptionDescription.Mapping object accepts an ApplyMappingRequest in the performImmediateActions method. The request contains the record to be updated as well as the message.

Methods

getRecord

global abstract SObject getRecord()

Returns the record being worked on.

Return Value

The record being worked on.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

/**
 * Simple class that only ever updates one field on ExampleObject
 */
public abstract class ExampleMapping extends fferpcore.SubscriptionDescription.Mapping
{
     public static List<String> COST_KEY = new List<String>{"Cost"};

     public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
     {
         fferpcore.SubscriptionDescriptionValue value = request.getValue(COST_KEY);

         // If value is null then the path is not present in the message. If the message explicitly states a null value
         // then value.getValue() will be null.
         if(value != null)
         {
             //get the object to update
             ExampleObject record = request.getRecord();
  
             //Update the record with the value from the message
             record.Cost__c = value.getValue());
         }
     }
}

isFirstRequestForRecord

global abstract Boolean isFirstRequestForRecord()

When messages are sent in bulk, ApplyMappingRequests are grouped by record before being provided to the mapping. For example, a mapping might handle two messages for record A, then one message for record B, then five messages for record C. This method can be used to find if we have moved on to a different record. When messages are sent synchronously they are handled one at a time and this method will always return true.

Return Value

True if this is the first request for the given record.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class ExampleMapping extends fferpcore.SubscriptionDescription.Mapping
{
    ...
        
    public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
    {
        if (request.isFirstRequestForRecord())
        {
            //Can execute code you only want to run once per record, or when you change from one record to the next.
            ExampleObject recordBeingUpdated = request.getRecord();
            
            ...
        }
        
        //Code that you want to run for every message
        ...
    }
} 

isLastRequestForRecord

global virtual Boolean isLastRequestForRecord()

Return Value

True if this is the last request for the given record.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class ExampleMapping extends fferpcore.SubscriptionDescription.Mapping
{
    ...
        
    public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
    {
        //Code that you want to run for every message
        ...

        if (request.isLastRequestForRecord())
        {
            //Can modify the final record in someway which we only want to do on  the final request
            ExampleObject recordBeingUpdated = request.getRecord();
            
            ...
        }
    }
}

getMessage

global abstract Map<String, Object> getMessage()

Returns the deserialized messageBody. The getValue method has been provided for easy access to a specific part of the message.

Return Value

The deserialized message being worked on.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

fferpcore.SubscriptionDescription.ApplyMappingRequest request = getRequest(); //The request we are handling.
Map<String, Object> body = request.getMessage();
//Can now access all the data in the message.

//Note that request.getMessage() is equivalent to (Map<String, Object>) request.getValue(new List<String>{}).getValue();
//I.e. getting the value of the root node.

getValue

global abstract fferpcore.SubscriptionDescription.Value getValue(List<String> jsonPath)

Return a fferpcore.SubscriptionDescription.Value containing the value for the given path in the messages, or null if the path is not present in the message. If the path is present with an explicit null value then a fferpcore.SubscriptionDescription.Value containing null is returned.

Input Parameters

Name Type Description
jsonPath List<String> The key to a value in the message.

Return Value

The value if found, or null if missing.

Sample Data

List<String> jsonPath: ["Department", "AddressLine1"]

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

String serializedMessageBody = '{"Size": "Large", "Vehicles": {"Car": "Honda", "Bike": "BMX"}, "Flowers": null }';

fferpcore.SubscriptionDescription.ApplyMappingRequestImpl request = ...; //a request for a message with 'messageBody'

System.assertEquals('Large', request.getValue(new List<String>{'Size'}).getValue());
System.assertEquals('Honda', request.getValue(new List<String>{'Vehicles', 'Car'}).getValue());
System.assertEquals('BMX', request.getValue(new List<String>{'Vehicles', 'Bike'}).getValue());
System.assertEquals(null, request.getValue(new List<String>{'Vehicles', 'Tractor'});                                  
System.assertEquals(null, request.getValue(new List<String>{'Smells'});       
System.assertEquals(null, request.getValue(new List<String>{'Flowers'}).getValue());

respondError

global abstract void respondError(fferpcore.ErpErrorBody error)

Marks the message with an error. If the error logging is set to MessagingSettingsService.LOGGING_LEVEL_ERROR or MessagingSettingsService.LOGGING_LEVEL_ALL, the message is marked with an error that you can investigate. After this method is called, processing on the record will be stopped and changes will not be saved. All other messages for that record will be marked in error.

Input Parameters

Name Type Description
error fferpcore.ErpErrorBody Details of the error that has occurred

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class ExampleMapping extends fferpcore.SubscriptionDescription.Mapping
{
     public static List<String> COST_KEY = new List<String>{'Cost'};

     public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
     {
         try 
         {
             request.getRecord().put('TargetField__c', request.getValue('MessageKey').getValue());
         }
         catch (Exception e)
         {
             request.respondError(new fferpcore.ErpErrorBody(e.getMessage()));
         }
     }
}   

fferpcore.SubscriptionDescription.Value

global class Value

A holder for a value, so we can tell the difference between null and missing.

Methods

Value

global Value(Object value)

Constructs a Value object wrapping the provided parameter.

Input Parameters

Name Type Description
value Object The data to be held in the Value

getValue

global Object getValue()

Return Value

Returns the value wrapped by this object, or null to indicate the key was not present in the message.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

/**
 * Simple class that only ever updates one field on ExampleObject 
 */
public class ExampleMapping extends fferpcore.SubscriptionDescription.Mapping
{
     public static List<String> COST_KEY = new List<String>{'Cost'};

     public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
     {
         fferpcore.SubscriptionDescriptionValue value = request.getValue(COST_KEY);
     
         if(value != null)
         {
             //get the object to update
             ExampleObject record = request.getRecord();
  
             //Update the record with the value from the message
             record.Cost__c = value.getValue());
         }
     }
}

fferpcore.SubscriptionDescription.Mapping

global abstract class Mapping

A strategy to marshal data from the fferpcore.Message to the target record. Any concrete Mapping implementation must extend this class.

Methods

getAdditionalSelections

global virtual Set<String> getAdditionalSelections()

These selections are passed to the fferpcore.LinkingCorrelationStrategy to be used when querying the SObject Records. Names must be fully qualified. The selections can include relationship selections and subselects, but beware of LIMITs when doing this. The default implementation returns null.

Return Value

Set of any additional selections required by the mapping.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class PersonNameMapping extends fferpcore.SubscriptionDescription.Mapping
{
    //Message contains keys FirstName, MiddleNames, LastName
    public static List<String> firstNameKey = new List<String>{'FirstName'};
    public static List<String> middleNameKey = new List<String>{'MiddleNames'};
    public static List<String> lastNameKey = new List<String>{'LastName'};

    //Target object has two name fields
    private static String forenamesTargetField = 'Forenames__c';
    private static String surnameTargetField = 'Surname__c';

    public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
    {
        //Use string manipulation to populate two name fields from three.
        ...
    }

    public override Set<String> getAdditionalSelections()
    {
        //If our calculation requires data from other tables or other fields on this table that aren't updated, 
        //we need to identify them here.
        return new Set<String>{'Forenames__c', 'Surname__c', 'DateOfBirth__c'};
    }

    public override Set<String> getTargetFields()
    {
        return new Set<String>{'Forenames__c', 'Surname__c'};
    }

    public override List<List<String>> getMessageKeys()
    {
        return new List<List<String>>{firstNameKey, middleNameKey, lastNameKey};
    }
}

performImmediateActions

global abstract void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)

Applies information from the fferpcore.Message to the Record. This is called before performBulkActions. This method must be overridden by any class that extends SubscriptionDescription.Mapping.

Input Parameters

Name Type Description
request fferpcore.SubscriptionDescription.ApplyMappingRequest The mapping request to be applied by this mapping.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

/**
 * Simple class that only ever updates one field on ExampleObject 
 */
public class ExampleMapping extends fferpcore.SubscriptionDescription.Mapping
{
     public static List<String> COST_KEY = new List<String>{'Cost'};

     public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
     {
         fferpcore.SubscriptionDescription.Value value = request.getValue(COST_KEY);
     
         if(value != null)
         {
             //get the object to update
             ExampleObject record = request.getRecord();
  
             //Update the record with the value from the message
             record.Cost__c = value.getValue();
         }
     }
}

performBulkActions

global virtual void performBulkActions()

Called after all messages have been processed, to allow the Mapping to perform any bulk actions.
An exception thrown here will result in all Messages and changes being rejected. If you can handle errors at the record level or message level using the respondError() method on a stored ApplyMappingRequest then do so as this will result in less damage to other records and messages.
The default implementation of this method does nothing.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class FatalisticMapping extends fferpcore.SubscriptionDescription.Mapping
{
     private boolean fatalErroroccurred = false;

     public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
     {
         //Handle requests, and potentially set fatalErroroccurred if something goes wrong. If something has gone wrong we can
         //still fail messages that we have already successfully processed.
         ...
     }

     public override void performBulkActions()
     {
        if (fatalErroroccurred)
        {
            throw new Exception('A fatal error occurred. Failing all messages.');
        }
     }
}  

getTargetFields

global abstract Set<String> getTargetFields()

Mappings must override this method to indicate which fields they can affect.

Return Value

The set of field names on the target record populated by this Mapping.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class PersonNameMapping extends fferpcore.SubscriptionDescription.Mapping
{
    //Message contains keys FirstName, MiddleNames, LastName
    public static List<String> firstNameKey = new List<String>{'FirstName'};
    public static List<String> middleNameKey = new List<String>{'MiddleNames'};
    public static List<String> lastNameKey = new List<String>{'LastName'};

    //Target object has two name fields
    private static String forenamesTargetField = 'Forenames__c';
    private static String surnameTargetField = 'Surname__c';

    public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
    {
        //Use string manipulation to populate two name fields from three.
        ...
    }

    public override Set<String> getAdditionalSelections()
    {
        //If our calculation requires data from other tables or other fields on this table that aren't updated, 
        //we need to identify them here.
        return new Set<String>{'Forenames__c', 'Surname__c', 'DateOfBirth__c'};
    }

    public override Set<String> getTargetFields()
    {
        return new Set<String>{'Forenames__c', 'Surname__c'};
    }

    public override List<List<String>> getMessageKeys()
    {
        return new List<List<String>>{firstNameKey, middleNameKey, lastNameKey};
    }
} 

getMessageKeys

global abstract List<List<String>> getMessageKeys()

Mappings must override this method to indicate which fields they use from the message.

Return Value

The message keys read by this Mapping.

Sample Code

//Note: This sample code is for demonstration purposes only. It is not intended for
//use in a production environment, is not guaranteed against defects or errors, and
//is in no way optimized or streamlined.

public class PersonNameMapping extends fferpcore.SubscriptionDescription.Mapping
{
    //Message contains keys FirstName, MiddleNames, LastName
    public static List<String> firstNameKey = new List<String>{'FirstName'};
    public static List<String> middleNameKey = new List<String>{'MiddleNames'};
    public static List<String> lastNameKey = new List<String>{'LastName'};

    //Target object has two name fields
    private static String forenamesTargetField = 'Forenames__c';
    private static String surnameTargetField = 'Surname__c';

    public override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)
    {
        //Use string manipulation to populate two name fields from three.
        ...
    }

    public override Set<String> getAdditionalSelections()
    {
        //If our calculation requires data from other tables or other fields on this table that aren't updated, 
        //we need to identify them here.
        return new Set<String>{'Forenames__c', 'Surname__c', 'DateOfBirth__c'};
    }

    public override Set<String> getTargetFields()
    {
        return new Set<String>{'Forenames__c', 'Surname__c'};
    }

    public override List<List<String>> getMessageKeys()
    {
        return new List<List<String>>{firstNameKey, middleNameKey, lastNameKey};
    }
} 

disableFields

global virtual void disableFields(Set<String> fieldNames)

Allows mappings to be superseded by providing the set of fields that later mappings write to. A Mapping must not write to a field if it was provided in this set.

Input Parameters

Name Type Description
fieldNames Set<String> The target fields that are written by later mappings.

isDisabled

global virtual Boolean isDisabled()

Return Value

True if the result of disableFields() is that this mapping is completely disabled.

fferpcore.SubscriptionDescription.FieldMapping

global class FieldMapping extends Mapping

If the value is present but null, then null is applied. If the value is absent then no action is taken.

This class extends fferpcore.SubscriptionDescription.Mapping

Methods

FieldMapping

global FieldMapping(SObjectField targetField, List<String> messageKey)

Constructs a FieldMapping that populates targetField with data from the part of the message accessed by messageKey.

Input Parameters

Name Type Description
targetField SObjectField The field to write to.
messageKey List<String> The path in the JSON structure to read from.

FieldMapping

global FieldMapping(SObjectField targetField, String messageKey)

Constructs a FieldMapping that populates targetField with data from the part of the message accessed by messageKey. This method is a convenience for calling: new SubscriptionDescription.FieldMapping(targetField, new List<String>{messageKey}).

Input Parameters

Name Type Description
targetField SObjectField The field to write to.
messageKey String The key to read in the JSON structure.

getAdditionalSelections

global override Set<String> getAdditionalSelections()

Implementation of SubscriptionDescription.Mapping.getAdditionalSelections(). This method is invoked by the fferpcore.SubscriptionDescription and should not be called directly.

Return Value

Any fields that will be updated and therefore need to be queried.

performImmediateActions

global override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)

Implementation of SubscriptionDescription.Mapping.performImmediateActions(SubscriptionDescription.ApplyMappingRequest request). This method is invoked by the fferpcore.SubscriptionDescription and should not be called directly. Perform any mapping functionality on the given request only.

Input Parameters

Name Type Description
request fferpcore.SubscriptionDescription.ApplyMappingRequest The mapping request containing the record and message data.

getTargetFields

global override Set<String> getTargetFields()

Implementation of SubscriptionDescription.Mapping.getTargetFields(). This method is invoked by the SubscriptionDescriptionController and should not be called directly.

Return Value

Any fields that will be updated.

getMessageKeys

global override List<List<String>> getMessageKeys()

Implementation of SubscriptionDescription.Mapping.getMessageKeys(). This method is invoked by the SubscriptionDescriptionController and should not be called directly.

Return Value

Any message keys that will be used.

fferpcore.SubscriptionDescription.LinkingFieldMapping

global class LinkingFieldMapping extends Mapping

Mapping that maintains Linking Fields based on information in the Message. See fferpcore.LinkingFieldManager for details on the fields maintained. Often these LinkControl Messages are received in response to an outgoing message and are used to indicate whether or not the message was successfully handled in the other product.

This class extends fferpcore.SubscriptionDescription.Mapping

Methods

LinkingFieldMapping

global LinkingFieldMapping(SObjectType recordType, List<String> linkControlPath)

Constructs a LinkingFieldMapping to update the specified record type.

Input Parameters

Name Type Description
recordType SObjectType The record type on which to maintain linking control fields.
linkControlPath List<String> Where to find the LinkControlBody in the JSON Message.

LinkingFieldMapping

global LinkingFieldMapping(SObjectType recordType, String linkControlKey)

This method is provided as a shorthand for calling: new SubscriptionDescription.LinkingFieldMapping(recordType, new List<String>{linkControlKey})

Input Parameters

Name Type Description
recordType SObjectType The record type on which to maintain linking control fields.
linkControlKey String Where to find the LinkControlBody in the JSON Message.

getAdditionalSelections

global override Set<String> getAdditionalSelections()

Implementation of SubscriptionDescription.Mapping.getAdditionalSelections(). This method is invoked by the fferpcore.SubscriptionDescription and should not be called directly.

Return Value

Any fields that will be updated and therefore need to be queried.

performImmediateActions

global override void performImmediateActions(fferpcore.SubscriptionDescription.ApplyMappingRequest request)

Implementation of SubscriptionDescription.Mapping.performImmediateActions(SubscriptionDescription.ApplyMappingRequest request). This method is invoked by the fferpcore.SubscriptionDescription and should not be called directly. Perform any mapping functionality on the given request only.

Input Parameters

Name Type Description
request fferpcore.SubscriptionDescription.ApplyMappingRequest The mapping request containing the record and message data.

getTargetFields

global override Set<String> getTargetFields()

Implementation of SubscriptionDescription.Mapping.getTargetFields(). This method is invoked by the SubscriptionDescriptionController and should not be called directly.

Return Value

Any fields that will be updated.

getMessageKeys

global override List<List<String>> getMessageKeys()

Implementation of SubscriptionDescription.Mapping.getMessageKeys(). This method is invoked by the SubscriptionDescriptionController and should not be called directly.

Return Value

Any message keys that will be used.

© Copyright 2009–2018 FinancialForce.com, inc. Confidential – all rights reserved. Various trademarks held by their respective owners.