SWIFT is a standard which describe acollection of messages formats. There are a lot of financial applications whichworks with financial transactions, and, often, these applications must communicatebetween them. Because each of them worked with certain formats, there washarder and harder to maintain a good transmission of information, and requireda lot of time and effort.
Because of that, SWIFT standard wasreleased to describe how the messages should be structured and how to exposethe information, in order to be properly interpreted, to be easier tomanipulate and, thanks God, make developer life easier. []
There are few hundreds of SWIFT messages,called generically MTXXX, where XXX is a 3-digit number. A SWIFT message is composed,as general structure, from 3 parts, header, body and trailer, and each of themare composed by fields, well delimited by field identifiers (labels). Forexample, a transaction of MT103 type:
{1:F01BANKINFOAXXX1234567890}{2:O1037549081128ABCDOP2LCYYY40369224800811281431N}{3:{108:08B2807310101800}{119:STP}}{4:
:20:123456786
:23B:ABCD
:32A:081128EUR11111,11
:33B:EUR11111,11
:50K:/000011111
TEST COMPANY
TEST STREET
TEST CITY
TEST COUNTRY
:52A:ABCDGB2LXXX
:53A:ABCDNL2AXXX
:59:/ZZ96ABCD0002001126690718
810252 TEST TEST TEST CITY
TEST COUNTRY
ZZ
:71A:AAA
:77B:3
172929
-}{5:{CHK:70788693BBA7}{MAC:00000000}}{S:{SAC:}{COP:P}}
(note: the dates within transaction arenot real, as we are not interested about data, but about structure).
Thus, all information is well representedand has a well-known position inside of message – sender address, senderaccount, amount, date, receiver address etc., giving possibility to createsoftware mechanisms to extract useful data from message.
But, although we know now the structureof messages, is still hard to work with them. We still have complicatedstructures of messages, and, if an application works with many types ofmessages, the development is still a nightmare for us.
In this respect, Microsoft has elaborateda package, which comes to help BizTalk developers on financial applications.This package comes with description of every SWIFT message, providing a schemafile and a policy file for each SWIFT message type, to be used in applications.This is great, because the schema is, most of the time, the hardest part todevelop when we create an import or export channel. All we have to do further,to create a channel, is to develop a map, a pipeline, a destination schema (forimport) or source schema (for export) and to configure some ports.
After create all of these elements, wecan still have a problem: when import file contains more than one message, wecannot import them all using a simple pipeline, having just schemaspecifications. We can even specify the number of message elements in schema tobe * (unbounded), no effect. Biztalk does not know to “break” the file intomessages, and only the first message will be imported.
For that, we can use a technique named“debatching”. Practically, we must manually break the message before to send itto the message schema in order to be validated and, after that, mapped todestination schema.
More exactly, we will develop a pipelinecomponent, which will be added to Disassemble step on the pipeline:

Here is the code of pipeline component:
using System;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.ComponentModel;
usingMicrosoft.BizTalk.Component;
usingMicrosoft.BizTalk.Component.Interop;
usingMicrosoft.BizTalk.PipelineOM;
usingMicrosoft.BizTalk.Message.Interop;
using System.IO;
usingMicrosoft.Solutions.FinancialServices;
usingMicrosoft.Solutions.FinancialServices.SWIFT;
usingMicrosoft.Solutions.FinancialServices.SWIFT.Pipelines;
namespace SWIFT.Pipeline.Components
{
[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
[ComponentCategory(CategoryTypes.CATID_DisassemblingParser)]
[System.Runtime.InteropServices.Guid("116A2C53-4E95-4506-8110-AD2F924DEDDD")]
public class SwiftFlatFileDisassembler: SWIFTDasm, IBaseComponent, IDisassemblerComponent, IPersistPropertyBag
{
/// <summary>
/// Class constructor.
/// </summary>
publicSwiftFlatFileDisassembler(){}
#region IDisassemblerComponentMembers
/// <summary>
/// Method is called by BizTalk when a new message is receivedon receive port.
/// </summary>
voidIDisassemblerComponent.Disassemble(IPipelineContext pContext,Microsoft.BizTalk.Message.Interop.IBaseMessage pInMsg)
{
try
{
//here we can process the original streambefore disassembling
IBaseMessage_originalIBaseMessage = pInMsg;
// callDisassemble method of base class to break the stream in individual messages
base.Disassemble(pContext,pInMsg);
}
catch(Exception ex)
{
//threatpossible error
throw;
}
}
/// <summary>
/// Total number of transactions.
/// </summary>
privateint _totalTransactions = 0;
/// <summary>
/// Method parse received file and identifies the transactions
/// </summary>
Microsoft.BizTalk.Message.Interop.IBaseMessageIDisassemblerComponent.GetNext(IPipelineContext pContext)
{
IBaseMessage iBaseMessage = null;
try
{
//getiBaseMessage message from base class
iBaseMessage = base.GetNext(pContext);
// ifGetNext from base class don't return null we promote BatchId on messagecontext.
if(iBaseMessage != null)
{
//check if message was successfully parsed, according toschema
boolmessageIsNotParsed = bool.Parse(iBaseMessage.Context.Read("A4SWIFT_Failed", "http://schemas.microsoft.com/A4SWIFT/Property").ToString());
if(messageIsNotParsed)
{
//threat error
throw new Exception(errorMessage);
}
_totalTransactions ++;
}
else
{
//finishof the message queue - process the _totalTransactions
}
}
catch(Exception ex)
{
//threaterror
throw;
}
returniBaseMessage;
}
#endregion
#region IBaseComponent Members
[Browsable(false)]
stringIBaseComponent.Description
{
get{ return "SWIFTFlat File disassembler"; }
}
[Browsable(false)]
stringIBaseComponent.Name
{
get{ return "SWIFTFlat File Disassembler"; }
}
[Browsable(false)]
stringIBaseComponent.Version
{
get{ return "1.0.0.0";}
}
#endregion
#region IPersistPropertyBag Members
voidIPersistPropertyBag.GetClassID(out Guid classID)
{
classID = newGuid("116A2C53-4E95-4506-8110-AD2F924DEDDD");
}
voidIPersistPropertyBag.InitNew()
{
base.InitNew();
}
voidIPersistPropertyBag.Load(IPropertyBag propertyBag, interrorLog)
{
base.Load(propertyBag,errorLog);
}
voidIPersistPropertyBag.Save(IPropertyBag propertyBag, boolclearDirty, bool saveAllProperties)
{
base.Save(propertyBag,clearDirty, saveAllProperties);
}
#endregion
}
}
To create this component, add as referenceto the project the assemblies: Microsoft.Solutions.FinancialServices.SWIFT.PipelineComponents.SWIFTDasm,which comes with SWIFT 2007 Message Pack installation.
Thereare 2 methods, implemented by IDisassemblerComponent interface:
- Disassemble – which breaks the originalstream (given as parameter) into individual messages and creates a queue, withthem
- GetNext, which is calledfor each message in the queue, and get as parameter the message resulted afterapplying message schema to original message; thus, we receive XML messagecorresponding to individualmessage.
In this way, every MT message is processed as an individual message and processed further(mapper or whatever), allowing us to work with flat files with multiple messages.
SwiftFlatFileDisassembler.rar (13.15 kb)