DataSource Blotter.NET  6.2.6-662-0db3f8d
 All Classes Namespaces Functions Properties Pages
Blotter API Overview

The Blotter API provides convenient abstractions for maintaining a blotter in real-time. A blotter is a table of generally static data augmented over time. The rows correspond to BlotterItems and the table to a BlotterChannel. The BlotterProvider allows multiple BlotterChannels, each associated with a user, to be serviced in a single namespace. Each channel is represented to the Liberator as a container and each constituent item a record.

Key Concepts

Blotter

Nested Blotter Concepts

Blotter Configuration

More on Representations

The tree in this example would be constructed as follows:

using System.Collections.Generic;
namespace Caplin.DataSource.Blotter.Example
{
public class CreatingATree
{
void SendTree(IBlotterChannel blotterChannel){
BlotterItem trade1 = new BlotterItem("Trade 1");
BlotterItem itemA = new BlotterItem("Item A");
BlotterItem itemB = new BlotterItem("Item B");
itemA.SetParent(trade1);
itemB.SetParent(trade1);
BlotterItem trade2 = new BlotterItem("Trade 2");
BlotterItem itemC = new BlotterItem("Item C");
BlotterItem itemD = new BlotterItem("Item D");
itemC.SetParent(trade2);
itemD.SetParent(trade2);
List<BlotterItem> blotterItemsToSend = new List<BlotterItem>();
blotterItemsToSend.Add(trade1);
blotterItemsToSend.Add(trade2);
blotterItemsToSend.Add(itemA);
blotterItemsToSend.Add(itemB);
blotterItemsToSend.Add(itemC);
blotterItemsToSend.Add(itemD);
blotterChannel.SendBlotterItems(blotterItemsToSend);
}
}
}

On the left is the Subcontainer Representation. This is the representation that will be used by default. In this case, subscribing to the 'ChannelSubejct' will return two BlotterItems, 'Trade 1' and 'Trade 2'. Each of these BlotterItems is a parent, so they will both have the field 'SubcontainerSubject'. Subscribing to 'Trade 1's 'SubcontainerSubject' will return the children of 'Trade 1', 'Trade 1:Item A' and 'Trade 1:Item B' and likewise for 'Trade 2's 'SubcontainerSubject'.

On the right is the Materialised Path Representation. The Blotter API is configured to use this representation from the top of the tree by setting Caplin.DataSource.Blotter.BlotterConfiguration#SetSubcontainerMaxDepth to nought. In this case, subscribing to the 'ChannelSubject' would return a flat representation of the tree, all the BlotterItems associated with this channel. The position of the BlotterItems in the tree is represented only by the 'Address' field which will contain the uniqueIds of every parent of this BlotterItem in order and this BlotterItem's uniqueId.

nested_blotter_tree.jpg

Getting Started

Instantiating a BlotterProvider

Here is how you would instantiate a BlotterProvider given a BlotterApplicationListener called BlotterUpdateGenerator:

using System;
using Caplin.DataSource.Blotter;
using System.Collections.Generic;
using Caplin.Logging;
namespace Caplin.DataSource.Blotter.Example
{
public class BlotterUpdateGenerator : IBlotterApplicationListener
{
private Logging.ILogger logger;
private int currentMessageIndex = 0;
public BlotterUpdateGenerator(Logging.ILogger logger)
{
this.logger = logger;
}
public void BlotterChannelOpened(IBlotterChannel channel)
{
// References to channels are obtained here. A reference
// would usually be kept so that blotter items can be added and
// removed with sendBlotterItem(s) and removeBlotterItem(s)
// as and when.
logger.Log(LogLevels.Info, "channel", "BlotterChannelOpened: " + channel.Subject);
channel.SendBlotterItem(BlotterItemFor(channel.Username));
}
public void BlotterChannelClosed(IBlotterChannel channel)
{
//any channel cleanup should go here
logger.Log(LogLevels.Info, "channel", "BlotterChannelClosed: " + channel.Subject);
}
private BlotterItem BlotterItemFor(string username)
{
//fields used here must be in your fields.conf
BlotterItem message = new BlotterItem(Convert.ToString(++currentMessageIndex));
message.SetField("tradeDate", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss z"));
message.SetField("currencyPair", "EUR/USD");
message.SetField("submittedBy", username);
return message;
}
}
}

Sample ApplicationListener

Here is the example ApplicationListener, BlotterUpdateGenerator:

using System;
using Caplin.DataSource;
using Caplin.Logging;
using Caplin.DataSource.Blotter;
using System.Threading;
using System.Collections.Generic;
namespace Caplin.DataSource.Blotter.Example
{
public class BlotterAdapterExample
{
private static string CHANNEL_NAMESPACE = "/BLOTTER/%u/CHANNEL";
private static string ITEM_NAMESPACE = "/BLOTTER/%u/ITEM/%i";
static void Main(string[] args)
{
ConsoleLogger logger = new ConsoleLogger();
IDataSource datasource = new DataSource("blotterExample.conf", logger);
BlotterConfiguration configuration = new BlotterConfiguration("BlotterDemoDotNet", CHANNEL_NAMESPACE, ITEM_NAMESPACE);
// DataSource is passed into the BlotterExample with the blotter configuration
new BlotterAdapterExample(datasource, configuration);
// The DataSource should not be started before creating a BlotterProvider to ensure all blotter requests are received
datasource.Start();
while (true)
{
Thread.Sleep(1000);
}
}
private ILogger logger;
public BlotterAdapterExample(IDataSource datasource, BlotterConfiguration configuration)
{
this.logger = datasource.Logger;
BlotterUpdateGenerator updateGenerator = new BlotterUpdateGenerator(logger);
new BlotterProvider(datasource, configuration, updateGenerator);
datasource.AddConnectionListener(new ConnectionListener(logger));
}
}
public class ConnectionListener : IConnectionListener
{
private ILogger logger;
public ConnectionListener(ILogger logger)
{
this.logger = logger;
}
public void ServiceStatus (IServiceStatusEvent ev)
{
logger.Log(LogLevels.Info, "status", "ServiceStatus changed to " + ev.Status);
}
public void PeerStatus (IPeerStatusEvent ev)
{
logger.Log(LogLevels.Info, "status", "PeerStatus changed to " + ev.Status);
}
}
}

Generated on Thu Apr 6 2017 16:23:13 for DataSource Blotter.NET