Foundations Apex API Developer Reference

fferpcore.MessageDescription

global inherited sharing class MessageDescription

This class defines the content and layout of a message produced by a publication. It is created returned from the Field.getDescription methods. { "correlationId" : "Correlation Id - required for all messages" "body" : "Body - Map of the data that would be sent in the message body" }

Enums

NodeType

Value Description
SCALAR_NODE A single scalar value representing a single keyed value in the message.
MAP_NODE A container node that contains many keyed nodes. The child nodes preserve order.
LIST_NODE A container node that contains many keyed nodes. Used to build arrays for multiple rows.

Methods

MessageDescription

global MessageDescription(fferpcore.Context.Source correlation, fferpcore.MessageDescription.Node body, fferpcore.Context rootContext)

This constructor is used to create a description of the message sent by the publication to the subscription. The actual structure of the message is defined by the body parameter.

Input Parameters

Name Type Description
correlation fferpcore.Context.Source Contains a field to be used as the correlation Id.
body fferpcore.MessageDescription.Node When deserialized this object represents the message that will be sent.
rootContext fferpcore.Context The SObject this MessageDescription is associated with.

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.

//The unique identifier field for this message
fferpcore.Context.Source correlation = new fferpcore.Context.SObjectSource(ExampleObject__c.EmployeeId__c);

//The body which will contain the name and email associated to ExampleObject__c which sends the message
fferpcore.MessageDescription.Node body = new fferpcore.MessageDescription.MapNode()
  .withScalarChild('Name', ExampleObject__c.Name)
  .withScalarChild('Email', ExampleObject__c.Email__c);

//The SObject that this message is associated to
fferpcore.Context rootContext = new fferpcore.Context.SObjectContext(ExampleObject__c.SObjectType);

fferpcore.MessageDescription description = new fferpcore.MessageDescription(correlation, body, rootContext);

getCorrelation

global fferpcore.Context.Source getCorrelation()

This method returns the source of the message description which represents the correlation Id of a message. It should be a unique field. All messages with the same correlation Id are interpreted as relating to the same object in the publishing product. For example, if it is the EmployeeId of a worker, then it can be used to find all messages relating to that worker.

Return Value

This service returns a Context.Source.

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.

//The unique identifier field for this message
fferpcore.Context.Source correlation = new fferpcore.Context.SObjectSource(ExampleObject__c.EmployeeId__c);

//The body which will contain the name and email associated to ExampleObject__c which sends the message
fferpcore.MessageDescription.Node body = new fferpcore.MessageDescription.MapNode()
    .withScalarChild('Name', ExampleObject__c.Name)
    .withScalarChild('Email', ExampleObject__c.Email__c);

//The SObject that this message is associated to
fferpcore.Context rootContext = new fferpcore.Context.SObjectContext(ExampleObject__c.SObjectType);

fferpcore.MessageDescription description = new fferpcore.MessageDescription(correlation, body, rootContext);

fferpcore.Context.Source returnValue = description.getCorrelation();

getBody

global fferpcore.MessageDescription.Node getBody()

This method returns the root node associated with this description. It represents the structure of the data to be sent in the message body.

Return Value

This service returns a MessageDescription.Node object.

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.

//The unique identifier field for this message
fferpcore.Context.Source correlation = new fferpcore.Context.SObjectSource(ExampleObject__c.EmployeeId__c);

//The body which will contain the name and email associated to ExampleObject__c which sends the message
fferpcore.MessageDescription.Node body = new fferpcore.MessageDescription.MapNode().
  withScalarChild('Name', ExampleObject__c.Name).
  withScalarChild('Email', ExampleObject__c.Email__c);

//The SObject that this message is associated to
fferpcore.MessageDescription.Context rootContext = new fferpcore.MessageDescription.SObjectContext(ExampleObject__c.SObjectType);

fferpcore.MessageDescription description = new fferpcore.MessageDescription(correlation, body, rootContext);

fferpcore.MessageDescription.Node returnValue = description.getBody();

fferpcore.MessageDescription.Node

global inherited sharing abstract class Node

This class represents a value in the message. It takes a source that tells the Node where its data comes from. Node cannot be instantiated, and should not be directly subclassed outside of Foundations. People who wish to write custom Nodes must extend one of our concrete Node types depending on the shape of data that their Node represents.

Methods

mergeNode

global abstract fferpcore.MessageDescription.DeclarativeMergeResult mergeNode(List<String> path, fferpcore.MessageDescription.DeclarativeMergeRequest request)

This abstract method should be overridden by any class that extends MessageDescription.Node. Calling mergeNode on a ScalarNode will return an error result. Calling mergeNode on a MapNode will attempt to add a Node to the message tree. The result indicates whether the node was successfully added and, if it was, contains the new node. This method is used by the publication description user interface and is not intended for use elsewhere.

Input Parameters

Name Type Description
path List<String> A JSON path indicating where the node is to be added.
request fferpcore.MessageDescription.DeclarativeMergeRequest A request containing the child node.

Return Value

This service returns a DeclarativeMergeResult object.

accept

global abstract Object accept(fferpcore.MessageDescriptionVisitor visitor, Object memento)

This abstract method must be overridden by all classes extending MessageDescription.Node. Implementing methods should follow the visitor pattern; they should call visit on the visitor parameter, passing in themselves and the memento object.

Input Parameters

Name Type Description
visitor
memento

Return Value

This service returns an Object object.

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.

/**
 * Only counts the leaf nodes.
 */
public class CounterVisitor extends fferpcore.MessageDescriptionVisitor
{
    public Integer count = 0;

    public override Object visit(fferpcore.MessageDescription.ScalarNode node, Object args)
    {
        count++;
    }

    public override Object visit(fferpcore.MessageDescription.MapNode mapNode, Object args)
    {
        for(fferpcore.MessageDescription.NamedNode namedNode : mapNode.getChildren())
        {
            namedNode.getNode().accept(this, null);
        }
    }
} 

fferpcore.MessageDescription.Node node = getNode(); //get a node from somewhere
CounterVisitor visitor = new CounterVisitor();
node.accept(visitor, null);
Integer numLeaves = visitor.count;

prepare

global abstract void prepare(fferpcore.DataSource dataSource)

This abstract method must be implemented on every class that extends MessageDescription.Node. Each node contains a Context.Source. This method calls prepare on that source, passing in the DataSource. Calling this method is required before the message can be built. Nodes are responsible for calling prepare on any children they might have.

Input Parameters

Name Type Description
dataSource fferpcore.DataSource A container for the SObject used to populate 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.

public class ExampleDataSource extends fferpcore.DataSource
{
    public Iterator<ExampleDataSourceRow> runQuery()
    {
        //return an iterator over some ExampleDataSourceRows
    }

    ...
}

public class ExampleDataSourceRow extends fferpcore.DataSource.Row
{
    ...
}

fferpcore.MessageDescripition messageDescription = getMessageDescription(); get a MessageDescription from somewhere
fferpcore.DataSource source = new ExampleDataSource();

//This example makes some messagerequests
List<MessagingSystemService.MessageRequest> messageRequests = new List<MessagingSystemService.MessageRequest>();

Context.Source correlationSource = messageDescription.getCorrelation();
fferpcore.MessageDescription.Node bodyNode = messageDescription.getBody();

//The correlation source must be prepared as the correlation field may not be present in the message.
correlationSource.prepare(source);

bodyNode.prepare(source);

Iterator<fferpcore.DataSource.Row> dataSourceRowIterator = source.runQuery();

while (dataSourceRowIterator.hasNext())
{
    DataSource.Row dataSourceRow = dataSourceRowIterator.next();

    String correlationId = String.valueOf(correlationSource.getData(dataSourceRow));

    JSONGenerator message = JSON.createGenerator(false);

    //Call build, passing in a DataSource.Row
    bodyNode.build(message, dataSourceRow);
    String body = generator.getAsString();

    MessagingSystemService.MessageRequest messageRequest =
    new MessagingSystemService.MessageRequest(messageType, correlationId, body);

    messageRequests.add(messageRequest);
}

//we now have some messaging requests, ready to go.

build

global abstract void build(JSONGenerator generator, fferpcore.DataSource.Row row)

This abstract method should be overridden by any class that extends MessageDescription.Node. However there are default implementations in fferpcore.MessageDescription.ScalarNode and MessageDescription.MapNode. This method uses the message structure to write the data in the row parameter to the supplied JSONGenerator.

Input Parameters

Name Type Description
generator JSONGenerator This will contain the message when finished.
row fferpcore.DataSource.Row The row contains the data to be built into 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.

public class ExampleDataSource extends fferpcore.DataSource
{
    public Iterator<ExampleDataSourceRow> runQuery()
    {
        //return an iterator over some ExampleDataSourceRows
    }

    ...
}

public class ExampleDataSourceRow extends fferpcore.DataSource.Row
{
    ...
}

fferpcore.MessageDescripition messageDescription = getMessageDescription(); get a MessageDescription from somewhere
fferpcore.DataSource source = new ExampleDataSource();

//This example makes some messagerequests
List<fferpcore.MessagingSystemService.MessageRequest> messageRequests = new List<fferpcore.MessagingSystemService.MessageRequest>();

Context.Source correlationSource = messageDescription.getCorrelation();
fferpcore.MessageDescription.Node bodyNode = messageDescription.getBody();

//The correlation source must be prepared as the correlation field may not be present in the message.
correlationSource.prepare(source);

bodyNode.prepare(source);

Iterator<fferpcore.DataSource.Row> dataSourceRowIterator = source.runQuery();

while (dataSourceRowIterator.hasNext())
{
    fferpcore.DataSource.Row dataSourceRow = dataSourceRowIterator.next();

    String correlationId = String.valueOf(correlationSource.getData(dataSourceRow));

    JSONGenerator message = JSON.createGenerator(false);

    //Call build, passing in a DataSource.Row
    bodyNode.build(message, dataSourceRow);
    String body = generator.getAsString();

    fferpcore.MessagingSystemService.MessageRequest messageRequest =
        new fferpcore.MessagingSystemService.MessageRequest(messageType, correlationId, body);

    messageRequests.add(messageRequest);
}

//we now have some messaging requests, ready to go.

getType

global abstract fferpcore.MessageDescription.NodeType getType()

Returns a MessageDescription.NodeType object to indicate this whether this is a ScalarNode or a MapNode.

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.MessageDescription description = getMessageDescription(); // get a message description from somewhere
fferpcore.MessageDescription.Node testNode = description.getBody();

if (testNode.getType() == fferpcore.MessageDescription.NodeType.SCALAR_NODE)
{
    //Do something with the ScalarNode
}
else if (testNode.getType() == fferpcore.MessageDescription.NodeType.MAP_NODE)
{
    //Do something with the MapNode
}
else
{
    //Error, unexpected node type!
}

getSource

global fferpcore.Context.Source getSource()

Returns the source that provides data for this node.

Return Value

This service returns a Source object.

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 void checkSource()
{
    fferpcore.MessageDescription.Node node = makeBody();

    //The root is a MapNode, constructed with no parameters. It has a PassthroughSource
    fferpcore.Context.Source source = node.getSource();
    System.assertEquals(fferpcore.Context.SourceType.PASSTHROUGH, source.getType());

    //Let's find out what the sources are of the child nodes
    for (fferpcore.MessageDescription.Node child : node.getChildren())
    {
        System.debug('NodeType: ' + child.getSource().getType());
    }
}

public fferpcore.MessageDescription.Node makeBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, new fferpcore.Context.SObjectSource(PSAFakeResource__c.Address1__c))
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(PSAFakeResource__c.Department__c)
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

isDeclarative

global Boolean isDeclarative()

Returns true if this is a custom node. Only nodes that have been added via the build method are declarative.

Return Value

This service returns a Boolean object.

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 void checkSource()
{
    fferpcore.MessageDescription.Node node = makeBody();

    //This node was constructed programmatically, so isDeclarative is false. 
    System.assertnode.isDeclarative(false, node.isDeclarative());
}

/**
 * We assume UpdateResourceMessage is a class with appropriate constants defined in it.
 */
public fferpcore.MessageDescription.Node makeBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, new fferpcore.Context.SObjectSource(PSAFakeResource__c.Address1__c))
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(PSAFakeResource__c.Department__c)
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

supportsDeclarative

global Boolean supportsDeclarative()

Indicates whether or not a Node can have declaratively defined children added to it. ScalarNodes never support declarative. MapNodes support declarative by default, but could be modified to not support declarative.

Return Value

This service returns a Boolean object.

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 void checkDeclarative()
{
    fferpcore.MessageDescription.Node root = makeBody();
    
    System.assert(root.supportsDeclarative(), 'The root is a MapNode, so supports declarative');

    for (fferpcore.MessageDescription.NamedNode namedNode : root.getChildren())
    {
        fferpcore.MessageDescription.Node node = namedNode.getNode();
        if (node.getType() == fferpcore.MessageDeclarative.NodeType.SCALAR_NODE)
        {
            System.assert(!node.supportsDeclarative(), 'ScalarNodes never support declarative');
        }
        else if (node.getType() == fferpcore.MessageDeclarative.NodeType.MAP_NODE)
        {
            System.assert(node.supportsDeclarative(), 'MapNodes don\'t support declarative by default.');

        }
        else
        {
            System.assert(false, 'Unexpected Node type: ' + node.getType());
        }
    }
}

/**
 * We assume UpdateResourceMessage is a class with appropriate constants defined in it.
 */
public fferpcore.MessageDescription.Node makeBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, new fferpcore.Context.SObjectSource(PSAFakeResource__c.Address1__c))
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(PSAFakeResource__c.Department__c)
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

getOutputContext

global fferpcore.Context getOutputContext()

This method returns a fferpcore.Context describing the data for the Node. It is a convenience for calling getSource().getOuputContext().

Return Value

The Output Context from this Node's Source.

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 fferpcore.MessageDescription.Node getBody()
{
    return new fferpcore.MessageDescription.MapNode(new fferpcore.Context.SObjectSource('key', Account.Name));
}

fferpcore.MessageDescription description = new fferpcore.MessageDescription(
            new fferpcore.Context.SObjectSource(HCMFakeWorker__c.EmployeeId__c),
            getBody(),
            new fferpcore.Context.SObjectContext(Account.SObjectType)
        );

fferpcore.MessageDescription.Node root = description.getBody()
fferpcore.Context cx = root.getOutputContext();

setInputContext

global virtual void setInputContext(fferpcore.Context context)

Each node contains a source. Calling this method sets the context on that source. This method then calls setInputContext on any child nodes the map node has.

Input Parameters

Name Type Description
context fferpcore.Context The context to be set on the source.

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.

//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.MessageDescription.Node body = getBody(); //create the message structure
fferpcore.Context ctx = new fferpcore.Context.SObjectContext(Account.SObjectType);
body.setInputContext(ctx);

fferpcore.MessageDescription.ScalarNode

global inherited sharing virtual class ScalarNode extends Node

A simple value representing a single keyed value in the message. This can be:
- a single field from an SObject record when the source is a Context.SObjectSource;
- a constant literal value when the source is a Context.StaticSource. You can extend this class with your own sources.

This class extends fferpcore.MessageDescription.Node

Methods

ScalarNode

global ScalarNode(fferpcore.Context.Source source)

This constructor creates a ScalarNode with data coming from the specified Source.

Input Parameters

Name Type Description
source fferpcore.Context.Source The source of data for this node.

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.Context.Source exampleSource = new fferpcore.Context.StaticSource('1234', 'Fixed Field');
fferpcore.MessageDescription.ScalarNode node = new fferpcore.MessageDescription.ScalarNode(exampleSource);

accept

global virtual override Object accept(fferpcore.MessageDescriptionVisitor visitor, Object memento)

This method forms part of the visitor pattern. If this method is overridden, implementations should call visit on the visitor parameter, passing in themselves and the memento object.

Input Parameters

Name Type Description
visitor fferpcore.MessageDescriptionVisitor The visitor.
memento Object An object storing data used by the visitor.

Return Value

This service returns an Object object.

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.

/**
 * Only counts the leaf nodes.
 */
public class CounterVisitor extends fferpcore.MessageDescriptionVisitor
{
    public Integer count = 0;

    public override Object visit(fferpcore.MessageDescription.ScalarNode node, Object args)
    {
        count++;
    }

    public override Object visit(fferpcore.MessageDescription.MapNode mapNode, Object args)
    {
        for(fferpcore.MessageDescription.NamedNode namedNode : mapNode.getChildren())
        {
            namedNode.getNode().accept(this, null);
        }
    }
} 

fferpcore.MessageDescription.Node node = getNode(); //get a node from somewhere
CounterVisitor visitor = new CounterVisitor();
node.accept(visitor, null);
Integer numLeaves = visitor.count;

mergeNode

global virtual override fferpcore.MessageDescription.DeclarativeMergeResult mergeNode(List<String> path, fferpcore.MessageDescription.DeclarativeMergeRequest request)

Calling mergeNode on a ScalarNode will return an error result. This method is used by the publication description user interface and is not intended for use elsewhere.

Input Parameters

Name Type Description
path List<String> A JSON path indicating where the node is to be added.
request fferpcore.MessageDescription.DeclarativeMergeRequest A request containing the child node.

Return Value

This service returns a DeclarativeMergeResult object.

prepare

global virtual override void prepare(fferpcore.DataSource dataSource)

Each node contains an Context.Source. This method calls prepare on that source, passing in the DataSource. Calling this method is required before the message can be built.

Input Parameters

Name Type Description
dataSource fferpcore.DataSource A container for the SObject used to populate 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.

public class ExampleDataSource extends fferpcore.DataSource
{
    public Iterator<ExampleDataSourceRow> runQuery()
    {
        //return an iterator over some ExampleDataSourceRows
    }

    ...
}

public class ExampleDataSourceRow extends fferpcore.DataSource.Row
{
    ...
}

fferpcore.MessageDescripition messageDescription = getMessageDescription(); get a MessageDescription from somewhere
fferpcore.DataSource source = new ExampleDataSource();

//This example makes some messagerequests
List<fferpcore.MessagingSystemService.MessageRequest> messageRequests = new List<fferpcore.MessagingSystemService.MessageRequest>();

fferpcore.Context.Source correlationSource = messageDescription.getCorrelation();
fferpcore.MessageDescription.Node bodyNode = messageDescription.getBody();

//The correlation source must be prepared as the correlation field may not be present in the message.
correlationSource.prepare(source);

bodyNode.prepare(source);

Iterator<fferpcore.DataSource.Row> dataSourceRowIterator = source.runQuery();

while (dataSourceRowIterator.hasNext())
{
    fferpcore.DataSource.Row dataSourceRow = dataSourceRowIterator.next();

    String correlationId = String.valueOf(correlationSource.getData(dataSourceRow));

    JSONGenerator message = JSON.createGenerator(false);

    //Call build, passing in a DataSource.Row
    bodyNode.build(message, dataSourceRow);
    String body = generator.getAsString();

    fferpcore.MessagingSystemService.MessageRequest messageRequest =
        new fferpcore..MessageRequest(messageType, correlationId, body);

    messageRequests.add(messageRequest);
}

//we now have some messaging requests, ready to go.

build

global virtual override void build(JSONGenerator generator, fferpcore.DataSource.Row row)

This method uses the message structure to write the data in the row parameter to the supplied JSONGenerator.

Input Parameters

Name Type Description
generator JSONGenerator This will contain the message when generated.
row fferpcore.DataSource.Row The row contains the data to be built into 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.

public class ExampleDataSource extends fferpcore.DataSource
{
    public Iterator<ExampleDataSourceRow> runQuery()
    {
        //return an iterator over some ExampleDataSourceRows
    }

    ...
}

public class ExampleDataSourceRow extends fferpcore.DataSource.Row
{
    ...
}

fferpcore.MessageDescripition messageDescription = getMessageDescription(); get a MessageDescription from somewhere
fferpcore.DataSource source = new ExampleDataSource();

//This example makes some messagerequests
List<fferpcore.MessagingSystemService.MessageRequest> messageRequests = new List<fferpcore.MessagingSystemService.MessageRequest>();

fferpcore.Context.Source correlationSource = messageDescription.getCorrelation();
fferpcore.MessageDescription.Node bodyNode = messageDescription.getBody();

//The correlation source must be prepared as the correlation field may not be present in the message.
correlationSource.prepare(source);

bodyNode.prepare(source);

Iterator<fferpcore.DataSource.Row> dataSourceRowIterator = source.runQuery();

while (dataSourceRowIterator.hasNext())
{
    fferpcore.DataSource.Row dataSourceRow = dataSourceRowIterator.next();

    String correlationId = String.valueOf(correlationSource.getData(dataSourceRow));

    JSONGenerator message = JSON.createGenerator(false);

    //Call build, passing in a DataSource.Row
    bodyNode.build(message, dataSourceRow);
    String body = generator.getAsString();

    fferpcore.MessagingSystemService.MessageRequest messageRequest =
        new fferpcore..MessageRequest(messageType, correlationId, body);

    messageRequests.add(messageRequest);
}

//we now have some messaging requests, ready to go.

getType

global override fferpcore.MessageDescription.NodeType getType()

Returns a MessageDescription.NodeType object to indicate this is a ScalarNode type node.

Return Value

This service returns a MessageDescription.NodeType object.

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.MessageDescription description = getMessageDescription(); // get a message description from somewhere
fferpcore.MessageDescription.Node testNode = description.getBody();

if (testNode.getType() == fferpcore.MessageDescription.NodeType.SCALAR_NODE)
{
    //Do something with the ScalarNode
}
else if (testNode.getType() == fferpcore.MessageDescription.NodeType.MAP_NODE)
{
    //Do something with the MapNode
}
else
{
    //Error, unexpected node type!
}

fferpcore.MessageDescription.MapNode

global inherited sharing virtual class MapNode extends Node implements ContainerNode

A container node that contains a many keyed nodes. The child nodes preserve order.

Methods

MapNode

global MapNode(fferpcore.Context.Source source)

This constructor creates a MapNode with the specified source.

Input Parameters

Name Type Description
source fferpcore.Context.Source The source to be used on this node.

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.

/**
 * Create the description for our message
 * We assume UpdateResourceMessage is a class with appropriate constants defined in it. 
 */
public fferpcore.MessageDescription.Node getBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, PSAFakeResource__c.Address1__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(new fferpcore.Context.SObjectSource(PSAFakeResource__c.Department__c))
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

MapNode

global MapNode()

Creates a new MapNode with a PassthroughSource. It is equivalent to calling new MessageDescription.MapNode(new Context.PassthroughSource()).

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.

/**
 * Create the description for our message
 * We assume UpdateResourceMessage is a class with appropriate constants defined in it. 
 */
public fferpcore.MessageDescription.Node getBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, PSAFakeResource__c.Address1__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(new fferpcore.Context.SObjectSource(PSAFakeResource__c.Department__c))
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

MapNode

global MapNode(SObjectField field)

Constructs a MapNode specifying an SObjectField as the data source. It is equivalent to calling new MessageDescription.MapNode(new Context.SObjectSource(field)).

Input Parameters

Name Type Description
field SObjectField Where the data comes from for this node.

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.

/**
 * Create the description for our message
 * We assume UpdateResourceMessage is a class with appropriate constants defined in it. 
 */
public fferpcore.MessageDescription.Node getBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, PSAFakeResource__c.Address1__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(PSAFakeResource__c.Department__c)
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

getChildren

global virtual List<fferpcore.MessageDescription.NamedNode> getChildren()

Returns the children of this node. The child nodes are wrapped in NamedNode objects which contain the node key as well as the node itself.

Return Value

This service returns a list of MessageDescription.NamedNode objects.

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.

/**
 * Create the description for our message
 * We assume UpdateResourceMessage is a class with appropriate constants defined in it.
 */
public fferpcore.MessageDescription.Node getBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, PSAFakeResource__c.Address1__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(PSAFakeResource__c.Department__c)
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

public void performBodyTest()
{
    fferpcore.MessageDescription.Node body = getBody();
    List<fferpcore.MessageDescription.NamedNode> children = body.getChildren();
    System.assertEquals(5, children.size());
}

withChild

global fferpcore.MessageDescription.MapNode withChild(String name, fferpcore.MessageDescription.Node child)

Adds the specified child node. This method returns the object the method is called on, so can be used as part of the fluent pattern.

Input Parameters

Name Type Description
name String The name of the node.
child fferpcore.MessageDescription.Node The child node to be added.

Return Value

This service returns a MessageDescription.MapNode.

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.

/**
 * Create the description for our message
 * We assume UpdateResourceMessage is a class with appropriate constants defined in it. 
 */
public fferpcore.MessageDescription.Node getBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, PSAFakeResource__c.Address1__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(PSAFakeResource__c.Department__c)
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

withScalarChild

global fferpcore.MessageDescription.MapNode withScalarChild(String name, fferpcore.Context.Source source)

Adds a new scalar node with the specified source. This method returns the object the method is called on, so can be used as part of the fluent pattern. It is equivalent to calling withChild(name, new MessageDescription.ScalarNode(source)).

Input Parameters

Name Type Description
name String The name of the node.
source fferpcore.Context.Source The source of the new child node.

Return Value

This service returns a MessageDescription.MapNode.

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.

/**
 * Create the description for our message
 * We assume UpdateResourceMessage is a class with appropriate constants defined in it. 
 */
public fferpcore.MessageDescription.Node getBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, new fferpcore.Context.SObjectSource(PSAFakeResource__c.Address1__c))
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(PSAFakeResource__c.Department__c)
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

withScalarChild

global fferpcore.MessageDescription.MapNode withScalarChild(String name, SObjectField field)

Adds a new scalar node with the specified source. This method returns the object the method is called on, so can be used as part of the fluent pattern. It is equivalent to calling withChild(name, new Context.SObjectSource(field)).

Input Parameters

Name Type Description
name String The name of the node.
field SObjectField The field that acts as the source of data.

Return Value

This service returns a MessageDescription.MapNode.

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.

/**
 * Create the description for our message
 * We assume UpdateResourceMessage is a class with appropriate constants defined in it. 
 */
public fferpcore.MessageDescription.Node getBody()
{
    return new fferpcore.MessageDescription.MapNode()
        .withChild(UpdateResourceMessage.LINK_CONTROL_KEY, fferpcore.LinkControlBody.getOutgoingDescriptionNode(PSAFakeResource__c.SObjectType, 'PSA'))
        .withScalarChild(UpdateResourceMessage.NAME_KEY, PSAFakeResource__c.Name)
        .withChild(UpdateResourceMessage.ADDRESS_KEY, new fferpcore.MessageDescription.MapNode()
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_1_KEY, PSAFakeResource__c.Address1__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_2_KEY, PSAFakeResource__c.Address2__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_3_KEY, PSAFakeResource__c.Address3__c)
            .withScalarChild(UpdateResourceMessage.ADDRESS_LINE_4_KEY, PSAFakeResource__c.Address4__c))
        .withScalarChild(UpdateResourceMessage.TELEPHONE_KEY, PSAFakeResource__c.Phone__c)
        .withChild(UpdateResourceMessage.DEPARTMENT_KEY, new fferpcore.MessageDescription.MapNode(PSAFakeResource__c.Department__c)
            .withScalarChild(UpdateResourceMessage.DEPARTMENT_NAME_KEY, PSAFakeDepartment__c.Name));
}

accept

global override Object accept(fferpcore.MessageDescriptionVisitor visitor, Object memento)

This method forms part of the visitor pattern. If this method is overridden, implementations should call call visit on the visitor parameter, passing in themselves and the memento object.

Input Parameters

Name Type Description
visitor fferpcore.MessageDescriptionVisitor The visitor.
memento Object An object storing data used by the visitor.

Return Value

This service returns an Object object.

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.

/**
 * Only counts the leaf nodes.
 */
public class CounterVisitor extends fferpcore.MessageDescriptionVisitor
{
    public Integer count = 0;

    public override Object visit(fferpcore.MessageDescription.ScalarNode node, Object args)
    {
        count++;
    }

    public override Object visit(fferpcore.MessageDescription.MapNode mapNode, Object args)
    {
        for(fferpcore.MessageDescription.NamedNode namedNode : mapNode.getChildren())
        {
            namedNode.getNode().accept(this, null);
        }
    }
} 

fferpcore.MessageDescription.Node node = getNode(); //get a node from somewhere
CounterVisitor visitor = new CounterVisitor();
node.accept(visitor, null);
Integer numLeaves = visitor.count;

mergeNode

global override fferpcore.MessageDescription.DeclarativeMergeResult mergeNode(List<String> path, fferpcore.MessageDescription.DeclarativeMergeRequest request)

Calling mergeNode on a MapNode will attempt to add a node to the message tree. The result indicates whether the node was successfully added and if it was, contains the new node. This method is used by the publication description user interface and is not intended for use elsewhere.

Input Parameters

Name Type Description
path List<String> A JSON path indicating where the node is to be added.
request fferpcore.MessageDescription.DeclarativeMergeRequest A request containing the child node.

Return Value

This service returns a DeclarativeMergeResult object.

prepare

global override virtual void prepare(fferpcore.DataSource dataSource)

Each node contains an Context.Source. This method calls prepare on that source, passing in the DataSource. Calling this method is required before the message can be built. MapNode will call prepare on its children.

Input Parameters

Name Type Description
dataSource fferpcore.DataSource A container for the SObject used to populate 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.

public class ExampleDataSource extends fferpcore.DataSource
{
    public Iterator<ExampleDataSourceRow> runQuery()
    {
        //return an iterator over some ExampleDataSourceRows
    }

    ...
}

public class ExampleDataSourceRow extends fferpcore.DataSource.Row
{
    ...
}

fferpcore.MessageDescripition messageDescription = getMessageDescription(); get a MessageDescription from somewhere
fferpcore.DataSource source = new ExampleDataSource();

//This example makes some messagerequests
List<fferpcore.MessagingSystemService.MessageRequest> messageRequests = new List<fferpcore.MessagingSystemService.MessageRequest>();

fferpcore.Context.Source correlationSource = messageDescription.getCorrelation();
fferpcore.MessageDescription.Node bodyNode = messageDescription.getBody();

//The correlation source must be prepared as the correlation field may not be present in the message.
correlationSource.prepare(source);

bodyNode.prepare(source);

Iterator<fferpcore.DataSource.Row> dataSourceRowIterator = source.runQuery();

while (dataSourceRowIterator.hasNext())
{
    fferpcore.DataSource.Row dataSourceRow = dataSourceRowIterator.next();

    String correlationId = String.valueOf(correlationSource.getData(dataSourceRow));

    JSONGenerator message = JSON.createGenerator(false);

    //Call build, passing in a DataSource.Row
    bodyNode.build(message, dataSourceRow);
    String body = generator.getAsString();

    fferpcore.MessagingSystemService.MessageRequest messageRequest =
        new fferpcore..MessageRequest(messageType, correlationId, body);

    messageRequests.add(messageRequest);
}

//we now have some messaging requests, ready to go.

setInputContext

global override void setInputContext(fferpcore.Context ctx)

Each node contains a source. Calling this method sets the context on that source. This method then calls setInputContext on any child nodes the map node has.

Input Parameters

Name Type Description
ctx fferpcore.Context The context to be set on the source.

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.MessageDescription.MapNode body = getBody(); //create the message structure. The root is a MapNode.
fferpcore.Context ctx = new fferpcore.Context.SObjectContext(Account.SObjectType);
body.setInputContext(ctx);

build

global override virtual void build(JSONGenerator generator, fferpcore.DataSource.Row parentRow)

This method uses the message structure to write the data in the row parameter to the supplied JSONGenerator.

Input Parameters

Name Type Description
generator JSONGenerator This will contain the message when finished.
parentRow fferpcore.DataSource.Row The row contains data to be built into 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.

public class ExampleDataSource extends fferpcore.DataSource
{
    public Iterator<ExampleDataSourceRow> runQuery()
    {
        //return an iterator over some ExampleDataSourceRows
    }

    ...
}

public class ExampleDataSourceRow extends fferpcore.DataSource.Row
{
    ...
}

fferpcore.MessageDescripition messageDescription = getMessageDescription(); get a MessageDescription from somewhere
fferpcore.DataSource source = new ExampleDataSource();

//This example makes some messagerequests
List<fferpcore.MessagingSystemService.MessageRequest> messageRequests = new List<fferpcore.MessagingSystemService.MessageRequest>();

fferpcore.Context.Source correlationSource = messageDescription.getCorrelation();
fferpcore.MessageDescription.Node bodyNode = messageDescription.getBody();

//The correlation source must be prepared as the correlation field may not be present in the message.
correlationSource.prepare(source);

bodyNode.prepare(source);

Iterator<fferpcore.DataSource.Row> dataSourceRowIterator = source.runQuery();

while (dataSourceRowIterator.hasNext())
{
    fferpcore.DataSource.Row dataSourceRow = dataSourceRowIterator.next();

    String correlationId = String.valueOf(correlationSource.getData(dataSourceRow));

    JSONGenerator message = JSON.createGenerator(false);

    //Call build, passing in a DataSource.Row
    bodyNode.build(message, dataSourceRow);
    String body = generator.getAsString();

    fferpcore.MessagingSystemService.MessageRequest messageRequest =
        new fferpcore..MessageRequest(messageType, correlationId, body);

    messageRequests.add(messageRequest);
}

//we now have some messaging requests, ready to go.

getType

global override fferpcore.MessageDescription.NodeType getType()

Returns a MessageDescription.NodeType object to indicate this is a MapNode type node.

Return Value

This service returns a MessageDescription.NodeType object.

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.MessageDescription description = getMessageDescription(); // get a message description from somewhere
fferpcore.MessageDescription.Node testNode = description.getBody();

if (testNode.getType() == fferpcore.MessageDescription.NodeType.SCALAR_NODE)
{
    //Do something with the ScalarNode
}
else if (testNode.getType() == fferpcore.MessageDescription.NodeType.MAP_NODE)
{
    //Do something with the MapNode
}
else
{
    //Error, unexpected node type!
}

fferpcore.MessageDescription.ListNode

global inherited sharing class ListNode extends Node implements ContainerNode

A container node that creates a list.

Methods

ListNode

global ListNode(fferpcore.Context.Source source)

This constructor creates a ListNode with the specified source.

Input Parameters

Name Type Description
source fferpcore.Context.Source The source to be used on this node.

ListNode

global ListNode(SObjectType childType, SObjectField childLookupField)

Constructs a ListNode specifying an SObjectType and SObjectField as the data source. This is equivalent to calling new MessageDescription.ListNode(new Context.SObjectSource(childType, childLookupField)).

Input Parameters

Name Type Description
childType SObjectType The type of the child SObject.
childLookupField SObjectField The field on the child SObject that references the parent.

getChildren

global List<fferpcore.MessageDescription.NamedNode> getChildren()

withChild

global fferpcore.MessageDescription.ListNode withChild(String name, fferpcore.MessageDescription.Node child)

Adds the specified child node. This method returns the object that the method is called on, so can be used as part of the fluent pattern.

Input Parameters

Name Type Description
name String The name of the node.
child fferpcore.MessageDescription.Node The child node to be added.

Return Value

This service returns a MessageDescription.ListNode.

withScalarChild

global fferpcore.MessageDescription.ListNode withScalarChild(String name, fferpcore.Context.Source source)

Adds a new scalar node with the specified source. This method returns the object the method is called on, so can be used as part of the fluent pattern. This is equivalent to calling withChild(name, new MessageDescription.ScalarNode(source)).

Input Parameters

Name Type Description
name String The name of the node.
source fferpcore.Context.Source The source of the new child node.

Return Value

This service returns a MessageDescription.ListNode.

withScalarChild

global fferpcore.MessageDescription.ListNode withScalarChild(String name, SObjectField field)

Adds a new scalar node with the specified source. This method returns the object that the method is called on, so can be used as part of the fluent pattern. This is equivalent to calling withChild(name, new Context.SObjectSource(field)).

Input Parameters

Name Type Description
name String The name of the node.
field SObjectField The field that acts as the source of data.

Return Value

This service returns a MessageDescription.ListNode.

accept

global override Object accept(fferpcore.MessageDescriptionVisitor visitor, Object memento)

This method forms part of the visitor pattern.

Input Parameters

Name Type Description
visitor fferpcore.MessageDescriptionVisitor The visitor.
memento Object An object storing data used by the visitor.

Return Value

This service returns an Object object.

mergeNode

global override fferpcore.MessageDescription.DeclarativeMergeResult mergeNode(List<String> path, fferpcore.MessageDescription.DeclarativeMergeRequest request)

This method attempts to add a node to the message tree. The result indicates whether the node was successfully added. If it was, it also contains the new node. This method is used by the publication description user interface and is not intended for use elsewhere.

Input Parameters

Name Type Description
path List<String> A JSON path indicating where the node is to be added.
request fferpcore.MessageDescription.DeclarativeMergeRequest A request containing the child node.

Return Value

This service returns a DeclarativeMergeResult object.

prepare

global override virtual void prepare(fferpcore.DataSource dataSource)

This method calls Prepare on each fferpcore.Context.Source and passes in the DataSource. This method must be called before the message is built. ListNode calls Prepare on its children.

Input Parameters

Name Type Description
dataSource fferpcore.DataSource A container for the SObject used to populate the message.

setInputContext

global override void setInputContext(fferpcore.Context ctx)

Each node contains a source. Calling this method sets the context on that source. This method then calls setInputContext on any child nodes the map node has.

Input Parameters

Name Type Description
ctx fferpcore.Context The context to be set on the source.

build

global override virtual void build(JSONGenerator generator, fferpcore.DataSource.Row parentRow)

This method uses the message structure to write the data in the row parameter to the supplied JSONGenerator.

Input Parameters

Name Type Description
generator JSONGenerator Contains the message once it is built.
parentRow fferpcore.DataSource.Row The row contains data to be built into the message.

getType

global override fferpcore.MessageDescription.NodeType getType()

Returns a MessageDescription.NodeType object to indicate this is a ListNode type node.

Return Value

This service returns a MessageDescription.NodeType object.

fferpcore.MessageDescription.NamedNode

global inherited sharing class NamedNode

A wrapper that holds a Node and a String that identifies it. This class is used as the children on a MapNode.

Methods

NamedNode

global NamedNode(String name, fferpcore.MessageDescription.Node node)

Constructs a fferpcore.MessageDescription.NamedNode with the specified name and node.

Input Parameters

Name Type Description
name String The name of the node.
node fferpcore.MessageDescription.Node The actual node this object is holding.

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.MessageDescription.ScalarNode scalarNode1 = 
    new fferpcore.MessageDescription.ScalarNode(new fferpcore.Context.StaticSource('TestData', 'Example data for our source'));
fferpcore.MessageDescription.ScalarNode scalarNode2 = 
    new fferpcore.MessageDescription.ScalarNode(new fferpcore.Context.StaticSource('DifferentDadta', 'More data for our source'));

fferpcore.MessageDescription.NamedNode namedNode = new fferpcore.MessageDescription.NamedNode('staticNode', scalarNode1);

System.assertEquals(namedNode, new fferpcore.MessageDescription.NamedNode('staticNode', scalarNode1));
System.assertNotEquals(namedNode, new fferpcore.MessageDescription.NamedNode('abc', scalarNode1), 'Are not equal and the names are different');
System.assertNotEquals(namedNode, new fferpcore.MessageDescription.NamedNode('staticNode', scalarNode2), 'Are not equals as the Nodes are different')

getName

global String getName()

Returns a string identifying the node.

Return Value

This service returns a string object.

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.

/**
 * Method to recursively traverse the message tree and log the names of all the nodes.
 */
public void logChildNames(fferpcore.MessageDescription.NamedNode namedNode)
{
    System.debug("Found node: " + namedNode.getName());
    fferpcore.MessageDescription.Node node = namedNode.getNode();
    if (node.getType() == fferpcore.MessageDescription.NodeType.MAP_NODE)  
    {
        (fferpcore.MessageDescription.MapNode) mapNode = (fferpcore.MessageDescription.MapNode) node;
        for (fferpcore.MessageDescription.Node child : mapNode.getChildren())
        {
            logChildNames(child);
        }
    }
}

getNode

global fferpcore.MessageDescription.Node getNode()

Returns the Node contained in this NamedNode.

Return Value

This service returns a Node object.

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.

/**
 * Method to recursively traverse the message tree and log the names of all the nodes.
 */
public void logChildNames(fferpcore.MessageDescription.NamedNode namedNode)
{
    System.debug("Found node: " + namedNode.getName());
    fferpcore.MessageDescription.Node node = namedNode.getNode();
    if (node.getType() == fferpcore.MessageDescription.NodeType.MAP_NODE)  
    {
        (fferpcore.MessageDescription.MapNode) mapNode = (fferpcore.MessageDescription.MapNode) node;
        for (fferpcore.MessageDescription.Node child : mapNode.getChildren())
        {
            logChildNames(child);
        }
    }
}

equals

global Boolean equals(Object obj)

Determines whether the node is equal to the supplied object. Two NamedNodes are considered to be equal if they have the same name and their nodes are equal.

Input Parameters

Name Type Description
obj Object The object we are checking equality against.

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.MessageDescription.ScalarNode scalarNode1 = 
    new fferpcore.MessageDescription.ScalarNode(new fferpcore.Context.StaticSource('TestData', 'Example data for our source'));
fferpcore.MessageDescription.ScalarNode scalarNode2 = 
    new fferpcore.MessageDescription.ScalarNode(new fferpcore.Context.StaticSource('DifferentDadta', 'More data for our source'));

fferpcore.MessageDescription.NamedNode namedNode = new fferpcore.MessageDescription.NamedNode('staticNode', scalarNode1);

//test1 is true as the names are the same and the nodes are equal
Boolean test1 = namedNode.equals(new fferpcore.MessageDescription.NamedNode('staticNode', scalarNode1));

//test2 is false because the names are different
Boolean test2 = namedNode.equals(new fferpcore.MessageDescription.NamedNode('abc', scalarNode1));

//test 3 is false because the Nodes are not equal
Boolean test3 = namedNode.equals(new fferpcore.MessageDescription.NamedNode('staticNode', scalarNode2));

hashCode

global Integer hashCode()

Returns an Integer computed from the Name and Node in this object.

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.MessageDescription.ScalarNode scalarNode1 = 
    new fferpcore.MessageDescription.ScalarNode(new Context.StaticSource('TestData', 'Example data for our source'));

fferpcore.MessageDescription.NamedNode namedNode1 = new MessageDescription.NamedNode('staticNode', scalarNode1);
fferpcore.MessageDescription.NamedNode namedNode2 = new MessageDescription.NamedNode('staticNode', scalarNode1);

System.assertEquals(namedNode1, namedNode2);
System.assertEquals(namedNode1.hashCode(), namedNode2.hashCode());

fferpcore.MessageDescription.DeclarativeMergeResult

global inherited sharing class DeclarativeMergeResult

This result contains the result of calling mergeNode on a MessageDescription.Node. If the merge was successful the result contains the child node. If the merge was not successful, the result contains a String detailing the problem.

Methods

DeclarativeMergeResult

global DeclarativeMergeResult(Boolean passed, fferpcore.MessageDescription.Node node)

This constructor is used to create a successful merge result. The resulting object acts as a wrapper for the child node that was added.

Input Parameters

Name Type Description
passed Boolean Indicates that the node was successfully added.
node fferpcore.MessageDescription.Node The new child node.

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.MessageDescription.Node oldNode = new fferpcore.MessageDescription.ScalarNode(new fferpcore.Context.SObjectSource(Account.Name));
fferpcore.MessageDescription.DeclarativeMergeResult result = new fferpcore.MessageDescription.DeclarativeMergeResult(true, node);
fferpcore.MessageDescription.Node newNode = result.getNode(); 
System.assertEquals(oldNode, newNode, 'Check the result acts as a wrapper for the node');

DeclarativeMergeResult

global DeclarativeMergeResult(Boolean passed, String message)

This constructor is used to create an unseccessful merge result. The resulting object acts as a wrapper for the error message.

Input Parameters

Name Type Description
passed Boolean Indicates that the merge was unsuccessful.
message String A description of why the merge failed.

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.MessageDescription.DeclarativeMergeResult result = new fferpcore.MessageDescription.DeclarativeMergeResult(false, 'Error');
System.assertEquals('Error', result.getMessage(), 'Check the result acts as a wrapper for the message');

hasPassed

global Boolean hasPassed()

Indicates whether a declarative merge request was successful.

Return Value

This service returns a Boolean object.

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.MessageDescription.DeclarativeMergeRequest request = getRequest(); //get a request from somewhere
fferpcore.MessageDescription.DeclarativeMergeResult result = request.build(new fferpcore.Context.SObjectContext(Account.SObjectType));
if (result.hasPassed())
{
    fferpcore.MessageDescription.Node node = result.getNode();
    //do something with the child node
}
else
{
    String error = result.getMessage();
    //do something with the error
}

getMessage

global String getMessage()

Returns the error message of an unseccessful declarative merge request. If called on a successful request then the empty string is returned.

Return Value

This service returns a String object.

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.MessageDescription.DeclarativeMergeRequest request = getRequest(); //get a request from somewhere
fferpcore.MessageDescription.DeclarativeMergeResult result = request.build(new fferpcore.Context.SObjectContext(Account.SObjectType));
if (result.hasPassed())
{
    fferpcore.MessageDescription.Node node = result.getNode();
    //do something with the child node
}
else
{
    String error = result.getMessage();
    //do something with the error
}

getNode

global fferpcore.MessageDescription.Node getNode()

Returns the node that was added in a successful declarative merge request. If called on an unsuccessful request then null returned.

Return Value

This service returns a Node object.

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.MessageDescription.DeclarativeMergeRequest request = getRequest(); //get a request from somewhere
fferpcore.MessageDescription.DeclarativeMergeResult result = request.build(new fferpcore.Context.SObjectContext(Account.SObjectType));
if (result.hasPassed())
{
    fferpcore.MessageDescription.Node node = result.getNode();
    //do something with the child node
}
else
{
    String error = result.getMessage();
    //do something with the error
}

fferpcore.MessageDescription.DeclarativeMergeRequest

global inherited sharing class DeclarativeMergeRequest

This class is used internally by EPR to build the message descriptions. It does not have any global constructors and cannot be used elsewhere. This object holds the fferpcore.MessageDescription.Node we are attemping to add to the message.

Methods

build

global fferpcore.MessageDescription.DeclarativeMergeResult build(fferpcore.Context context)

This method is called on a fferpcore.MessageDescription.DeclarativeMergeRequest to add a node to the message. The context parameter states the source of data required for the node specified in the request.

Return Value

This service returns a DeclarativeMergeResult object.

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.MessageDescription.DeclarativeMergeRequest request = getRequest(); //get a request from somewhere
fferpcore.MessageDescription.DeclarativeMergeResult result = request.build(new fferpcore.Context.SObjectContext(Account.SObjectType));
if (result.hasPassed())
{
    fferpcore.MessageDescription.Node node = result.getNode();
    //do something with the child node
}
else
{
    String error = result.getMessage();
    //do something with the error
}
© Copyright 2009–2022 FinancialForce.com, inc. Confidential – all rights reserved. Various trademarks held by their respective owners.