Since fields in an MT message are ordered, this can be tricky some times depending if the needed change involves just changing existing fields content or adding new fields.
Modifying content of an existing message is done with the generic backbone model; implemented in the SwiftMessage class and in particular for the text block implementation in the SwiftBlock4 class.
If the message to modify has been created or parsed into an MTnnn class, the underlying model can be accessed like this:
MT103 mt = MT103.parse(file); SwiftBlock4 b4 = mt.getSwiftMessage().getBlock4();
Notice the MTnnn classes and its getFieldnn methods are a convenient abstraction to read message content or to create new messages from scratch, but they are not suitable for content modification.
The SwiftBlock4 class implements the structure of any MT message text block and provides several helpful API to retrieve fields and alter content. Also it provides API to insert new fields between others.
Updating a field value
Updating an existing field value or component within a field can be achieved in several ways.
The simplest scenario, when a complete field value must be changed can be handled by just retrieving the generic Tag object and setting its new value as a string.
The SwiftBlock4 provides several API to retrieve tags; by name and letter option, by number, by name and qualifier, etc..
Let's say now we need to set a new value for field 57A. Since this field has several internal components (subfields) it can be useful to build the new value from a Field57A object. We can do that as follows:
Field57A field57A = new Field57A(); field57A.setAccount("12345"); field57A.setBIC("NEWAESMMXXX"); b4.getTagByName("57A").setValue(field57A.getValue());
Notice how we created a new field, but then we had to load the actual Tag instance in order to overwrite its value.
The getValue() call returns the serialization of all present field components into a proper string format. For instance in the example the resulting string would be:
/12345 [CRLF] NEWAESMMXXX
Notice the starting slash and the line feed are automatically added.
A similar approach can be use if we need to change just a specific component from an existing field. As in the previous example we use a Field object because it provides helpful API to manipulate internal components. But instead of creating the Field object from scratch, we start by loading it from the actual message. In this example we will change just the value date from the existing field 32A:
Field32A field32A = mt.getField32A().setComponent1(Calendar.getInstance()); b4.getTagByName("32A").setValue(field32A.getValue());
Notice how we first loaded the helper Field32A instance, which is filled with content from the internal Tag object. The we use this field object to alter the value date. At that moment the actual message content has not been modified because the Field instance is a detached object, changing it does not modify the actual message. So finally, we used the detached modified field to update the current Tag value in the underlying message.
Inserting new fields in MT message
The text block of a SWIFT message is syntactically an ordered list of fields and as such in the underlying model it is actually implemented as a List<Tag>. So depending on the specific need, inserting new fields in specific positions into an existing block can be tricky. Unfortunately in current version there is no easy/out-of-the-box API for this but the following workaround can be handly.
- First alternative involves inserting new fields by means of plain List manipulation using Java API. This can be done in combination of the indexOf methods provided by SwiftBlock4 to select the specific positions where new fields must be added. The text block can be thinked of as a String, and the provided API as StringUtils.
- Then, depending on how many fields are being added and how many remain the same, it may be also convenient to create a new block, appending in order the fields from the original message plus the new ones to add.
- Finally, if you are comfortable manipulating XML a total different approach is to convert the SWIFT message into XML, manipulating the XML, and then converting the XML back to SWIFT. The proprietary XML parser and writer are provided within the API.
The alternative to choose depends mainly on the use case. If the implementation is for a specific MT and use case the first two options can be convenient. But if the requirements is generic, for several situations and MTs, the XML approach would be better.
An extension for the SwiftBlock4 API is in the roadmap and will provide methods to insert new fields in specific index based positions.
Using the tag index
For the block 4 a couple of methods were also introduced to handle fields order, the addTag(index, Tag) and setTag(index, Tag).
The addTag at index adds a tag at the specified position in this tag list, and shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices).
SwiftBlock4 b4 = new SwiftBlock4(); b4.append(new Tag("20:PAY01")); b4.append(new Tag("23B:CRED")); b4.append(new Tag("71A:SHA")); b4.addTag(2 , (new Tag("21:RELREF")));
At this point the tag list will contain fields: 20, 21, 23B and 71A
Then the setTag at index replaces the tag at the specified position in the tag list with the new tag.
b4.setTag(2, (new Tag("32A", "180419USD1234,")));
At this point the tag list will contain fields: 20, 32A, 23B and 71A