Skip to content

Commit d769994

Browse files
zubriclaude
andcommitted
fix(PW-3126): fix DN to BIC extraction to include branch from ou component
Added parseBranch() to DistinguishedName to extract the branch code from the ou field of a SWIFT DN string, selecting the rightmost ou when multiple are present (closest to o=<bic8>). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2534960 commit d769994

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Prowide Core - CHANGELOG
22

3+
#### 10.3.9 - SNAPSHOT
4+
* (PW-3126) Fixed DN to BIC extraction in `DistinguishedName` to include the branch code from the `ou` component
5+
36
#### 10.3.8 - January 2026
47
* (PW-2967) Fixed Field95D component label from "Legal Entity Identifier" to "Digital Ledger Identifier" to match XSD schema
58
* Feat: `MtSwiftMessage` now automatically extracts and persists UETR from block 3 field 121 during message parsing

src/main/java/com/prowidesoftware/swift/model/DistinguishedName.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.prowidesoftware.swift.model;
22

33
import org.apache.commons.lang3.StringUtils;
4+
import org.apache.commons.lang3.Strings;
45

56
/**
67
* Represents a Distinguished Name (DN) in the context of a directory service.
@@ -62,13 +63,38 @@ public static String parseBIC(final String dn) {
6263
return null;
6364
}
6465
for (String s : StringUtils.split(dn, ",")) {
65-
if (StringUtils.startsWith(s, "o=") && !StringUtils.equals(s, "o=swift")) {
66+
if (Strings.CS.startsWith(s, "o=") && !Strings.CS.equals(s, "o=swift")) {
6667
return StringUtils.upperCase(StringUtils.substringAfter(s, "o="));
6768
}
6869
}
6970
return null;
7071
}
7172

73+
/**
74+
* Parses the branch code from a SWIFT Distinguished Name string.
75+
*
76+
* <p>The branch is represented by the {@code ou} component. When multiple {@code ou} components
77+
* are present, the one closest to {@code o=&lt;bic8&gt;} (i.e. the rightmost) is the branch code,
78+
* as DNs are read right-to-left from least to most specific:
79+
* <pre>cn=a,ou=dept,ou=bbb,o=biccode,o=swift → branch is "BBB"</pre>
80+
*
81+
* @param dn the Distinguished Name string, may be null or blank
82+
* @return the branch code in uppercase, or null if not present or if the input is blank
83+
*/
84+
protected static String parseBranch(final String dn) {
85+
if (StringUtils.isBlank(dn)) {
86+
return null;
87+
}
88+
String branch = null;
89+
for (String s : StringUtils.split(dn, ",")) {
90+
if (Strings.CS.startsWith(s, "ou=")) {
91+
// keep iterating — last match is the rightmost (closest to o=<bic8>)
92+
branch = StringUtils.substringAfter(s, "ou=");
93+
}
94+
}
95+
return StringUtils.isBlank(branch) ? null : StringUtils.upperCase(branch);
96+
}
97+
7298
/**
7399
* Builder class for constructing DistinguishedName instances.
74100
*/

src/test/java/com/prowidesoftware/swift/model/DistinguishedNameTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,46 @@ void testParseBIC() {
5757

5858
assertNull(DistinguishedName.parseBIC("XXX"));
5959
}
60+
61+
@Test
62+
void testParseBranchSingleOU() {
63+
assertEquals("XXX", DistinguishedName.parseBranch("ou=xxx,o=biccode,o=swift"));
64+
}
65+
66+
@Test
67+
void testParseBranchUppercasesResult() {
68+
assertEquals("XXX", DistinguishedName.parseBranch("ou=XXX,o=biccode,o=swift"));
69+
}
70+
71+
@Test
72+
void testParseBranchWithCN() {
73+
assertEquals("XXX", DistinguishedName.parseBranch("cn=a,ou=xxx,o=biccode,o=swift"));
74+
}
75+
76+
@Test
77+
void testParseBranchMultipleOU() {
78+
// rightmost ou (closest to o=<bic8>) is the branch; leftmost is a subdivision
79+
assertEquals("BBB", DistinguishedName.parseBranch("cn=a,ou=dept,ou=bbb,o=biccode,o=swift"));
80+
}
81+
82+
@Test
83+
void testParseBranchNoOU() {
84+
assertNull(DistinguishedName.parseBranch("o=biccode,o=swift"));
85+
}
86+
87+
@Test
88+
void testParseBranchNull() {
89+
assertNull(DistinguishedName.parseBranch(null));
90+
}
91+
92+
@Test
93+
void testParseBranchBlank() {
94+
assertNull(DistinguishedName.parseBranch(""));
95+
assertNull(DistinguishedName.parseBranch(" "));
96+
}
97+
98+
@Test
99+
void testParseBranchNoMatch() {
100+
assertNull(DistinguishedName.parseBranch("o=biccode,o=swift"));
101+
}
60102
}

0 commit comments

Comments
 (0)