Skip to content

Commit

Permalink
Merge branch 'SRU2024' into SRU2024_v10
Browse files Browse the repository at this point in the history
  • Loading branch information
zubri authored Nov 15, 2024
2 parents 835d51f + 101d358 commit f433602
Show file tree
Hide file tree
Showing 13 changed files with 1,016 additions and 268 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Prowide Core - CHANGELOG

#### 10.2.3 - November 2024
* (PW-2040) Updated the BBAN validation data file to the IBAN REGISTRY Jul 2024 release
* (PW-2006) Fixed `getMUR` and `setMUR` in `SwiftMessage` to prioritize field 108 in block 4 over block 3 for system messages (category 0)
* Added new `MtSequenceEnum` with all the available inner sequences of specific MT schemas
* Added `isSystemMessage()` to SwiftMessage to check if the message is a category 0 message (010. 011, etc...)
* Added new `MtSequenceEnum` with all the available inner sequences of specific MT schemas

#### 10.2.2 - October 2024
* Added new `FieldEnum` with all the available field names
* Code security improvements as per CodeQL recommendations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@

package com.prowidesoftware.swift.model.field;

import com.prowidesoftware.Generated;

/**
* Enumeration of fields for SRU 2024
*
* @since 9.5.2
*/
@Generated
public enum FieldEnum {

F11A,
Expand Down Expand Up @@ -61,6 +64,9 @@ public enum FieldEnum {
F14N,
F14O,
F14J,
F14P,
F14Q,
F14R,
F14S,
F15A,
F15B,
Expand All @@ -80,8 +86,10 @@ public enum FieldEnum {
F15P,
F16A,
F16C,
F16D,
F16R,
F16S,
F16W,
F17A,
F17B,
F17C,
Expand Down Expand Up @@ -142,7 +150,6 @@ public enum FieldEnum {
F22F,
F22G,
F22H,
F22J,
F22K,
F22L,
F22M,
Expand Down Expand Up @@ -204,7 +211,6 @@ public enum FieldEnum {
F29H,
F29I,
F29J,
F29K,
F29L,
F29M,
F29N,
Expand All @@ -213,11 +219,14 @@ public enum FieldEnum {
F29S,
F29T,
F29U,
F29Q,
F29W,
F30F,
F30G,
F30H,
F30I,
F30J,
F30K,
F30M,
F30N,
F30P,
Expand Down Expand Up @@ -320,9 +329,7 @@ public enum FieldEnum {
F37L,
F37M,
F37N,
F37P,
F37R,
F37U,
F37V,
F38A,
F38D,
Expand All @@ -333,7 +340,6 @@ public enum FieldEnum {
F39A,
F39B,
F39C,
F39D,
F39E,
F39F,
F39M,
Expand All @@ -360,7 +366,6 @@ public enum FieldEnum {
F44D,
F44E,
F44F,
F44H,
F44J,
F45A,
F45B,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright 2006-2024 Prowide
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.prowidesoftware.swift.model.mt;

import com.prowidesoftware.Generated;

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

/**
* Enumeration representing all possible sequence paths for each MT (Message Type) schema.
* Each constant in this enumeration corresponds to a specific MT schema, identified by its
* sequence paths as a comma-separated string (CSV) for SRU 2024.
*
* <p>For example, the MT508 message type may have sequence paths such as "A", "A/A1", "B", "B/B1", and "C",
* which would be represented as the CSV string "A,A/A1,B,B/B1,C".
* Note that internal loops not clearly identified and named in the standard as a sequence, are excluded.
*
* <p>For example, the MT801 message contains the "Loop1" and "Loop2" sequences, and this are not included in the sequence paths.
*
* @since 9.5.3
*/
@Generated
public enum MtSequenceEnum {

MT101("A,B"),
MT102("A,B,C"),
MT102_STP("A,B,C"),
MT104("A,B,C"),
MT107("A,B,C"),
MT202COV("A,B"),
MT204("A,B"),
MT205COV("A,B"),
MT300("A,B,B/B1,B/B2,C,D,D/D1,E,E/E1,E/E1/E1a,E/E1/E1a/E1a1,F"),
MT304("A,B,B/B1,B/B2,C,C/C1,C/C1/C1a,D,E"),
MT305("A,B,B/B1,B/B1/B1a,B/B1/B1a/B1a1"),
MT306("A,B,B/B1,B/B2,C,D,E,F,F/F1,G,H,I,J,J/J1,J/J2,K,L,M,M/M1,M/M1/M1a,M/M1/M1a/M1a1"),
MT320("A,B,C,D,E,F,G,H,I"),
MT321("A,A/A1,B,B/B1,B/B2,B/B3,C,C/C1"),
MT330("A,B,C,D,E,F,G,H"),
MT340("A,B,B/B1,B/B2,C,D,E,F,G,G/G1,G/G1/G1a,G/G1/G1a/G1a1"),
MT341("A,B,B/B1,C,D,D/D1,D/D1/D1a,D/D1/D1a/D1a1"),
MT350("A,B,C,D,D/D1,D/D2"),
MT360("A,B,B/B1,C,C/C1,C/C2,C/C3,D,E,E/E1,F,F/F1,F/F2,F/F3,G,H,L,M,N,O,O/O1,O/O1/O1a,O/O1/O1a/O1a1"),
MT361("A,B,B/B1,C,C/C1,C/C2,C/C3,D,E,E/E1,F,F/F1,F/F2,F/F3,G,H,I,J,K,L,M,N,O,P,P/P1,P/P1/P1a,P/P1/P1a/P1a1"),
MT362("A,B,C,D,E"),
MT364("A,B,E,L,M"),
MT365("A,B,E,J,K,L,M"),
MT370("A,A/A1,A/A2,B,B/B1"),
MT380("A,A/A1,B,B/B1,B/B2,C"),
MT381("A,A/A1,B,B/B1,B/B2,C"),
MT416("A,B"),
MT430("A,B"),
MT500("A,A/A1,B,B/B1,B/B2,C,C/C1,C/C2,D,E"),
MT501("A,A/A1,B,B/B1,B/B2,C,C/C1,C/C2,D,E"),
MT502("A,A/A1,B,B/B1,B/B2,B/B3,C,C/C1,C/C2,C/C3,D,E"),
MT503("A,A/A1,A/A2,B,B/B1,C,C/C1,C/C2,C/C3,D"),
MT504("A,A/A1,A/A2,B,B/B1,C,C/C1,C/C1/C1a,C/C1/C1a/C1a1,C/C2,C/C2/C2a,C/C2/C2a/C2a1,C/C3,D,D/D1,E,E/E1,F"),
MT505("A,A/A1,A/A2,B,B/B1,B/B1/B1a,B/B1/B1a/B1a1,B/B2,B/B2/B2a,B/B2/B2a/B2a1,B/B3,C,C/C1,D,D/D1,E"),
MT506("A,A/A1,A/A2,B,B/B1,C,C/C1,C/C2,C/C3,D,D/D1,D/D2,D/D3,E"),
MT507("A,A/A1,A/A2,B,B/B1,B/B1/B1a,B/B1/B1a/B1a1,B/B1/B1b,B/B1/B1b/B1b1,C"),
MT508("A,A/A1,B,B/B1,C"),
MT509("A,A/A1,A/A2,A/A2/A2a,B,B/B1,C"),
MT510("A,A/A1,A/A2,A/A2/A2a,B,C"),
MT513("A,A/A1,B,B/B1,C,C/C1,C/C2,C/C3,D,D/D1,D/D2,D/D3,E,F"),
MT514("A,A/A1,B,B/B1,B/B2,C,C/C1,C/C2,C/C3,D,E"),
MT515("A,A/A1,B,C,C/C1,C/C2,D,D/D1,D/D2,D/D3,E,F"),
MT516("A,B,C"),
MT517("A,A/A1"),
MT518("A,A/A1,B,B/B1,B/B2,C,C/C1,C/C2,C/C3,D,E"),
MT519("A,A/A1,B,B/B1,B/B2,C,C/C1,C/C2,D"),
MT524("A,A/A1,B,B/B1,C"),
MT526("A,B"),
MT527("A,A/A1,A/A2,B,B/B1,C,D,E"),
MT530("A,B,B/B1,C,C/C1,C/C1/C1a"),
MT535("A,A/A1,B,B/B1,B/B1/B1a,B/B1/B1b,B/B1/B1b/B1b1,B/B1/B1c,C"),
MT536("A,A/A1,B,B/B1,B/B1/B1a,B/B1/B1a/B1a1,B/B1/B1a/B1a2,B/B1/B1a/B1a2/B1a2A,C"),
MT537("A,A/A1,B,B/B1,B/B2,B/B2/B2a,B/B2/B2b,B/B2/B2b/B2b1,C,C/C1,C/C2,C/C2/C2a,C/C3,C/C3/C3a,D,D/D1,D/D1/D1a,D/D1/D1a/D1a1,D/D1/D1a/D1a1/D1a1A,D/D1/D1a/D1a1/D1a1A/D1a1A1,D/D1/D1a/D1a1/D1a1B,D/D1/D1a/D1a1/D1a1B/D1a1B1,D/D1/D1a/D1a1/D1a1B/D1a1B1/D1a1B1a,D/D1/D1a/D1a1/D1a1B/D1a1B1/D1a1B1a/D1a1B1a1,E"),
MT538("A,A/A1,B,B/B1,B/B2,B/B2/B2a,B/B2/B2a/B2a1,C"),
MT540("A,A/A1,B,B/B1,C,C/C1,D,E,E/E1,E/E2,E/E3,F"),
MT541("A,A/A1,B,B/B1,C,C/C1,D,E,E/E1,E/E2,E/E3,F"),
MT542("A,A/A1,B,B/B1,C,C/C1,D,E,E/E1,E/E2,E/E3,F"),
MT543("A,A/A1,B,B/B1,C,C/C1,D,E,E/E1,E/E2,E/E3,F"),
MT544("A,A/A1,B,B/B1,C,C/C1,D,E,E/E1,E/E2,E/E3,F"),
MT545("A,A/A1,B,B/B1,C,C/C1,D,E,E/E1,E/E2,E/E3,F"),
MT546("A,A/A1,B,B/B1,C,C/C1,D,E,E/E1,E/E2,E/E3,F"),
MT547("A,A/A1,B,B/B1,C,C/C1,D,E,E/E1,E/E2,E/E3,F"),
MT548("A,A/A1,A/A2,A/A2/A2a,B,B/B1,C,C/C1,C/C1/C1a,C/C1/C1a/C1a1,C/C1/C1a/C1a1/C1a1A,C/C1/C1a/C1a1/C1a1A/C1a1A1,C/C1/C1a/C1a1/C1a1B,C/C1/C1a/C1a1/C1a1B/C1a1B1,C/C1/C1a/C1a1/C1a1B/C1a1B1/C1a1B1a,C/C1/C1a/C1a1/C1a1B/C1a1B1/C1a1B1a/C1a1B1a1,D"),
MT549("A,A/A1,B,C,D"),
MT558("A,A/A1,A/A2,A/A2/A2a,A/A3,B,B/B1,C,D,E"),
MT564("A,A/A1,A/A2,B,B/B1,B/B2,C,D,E,E/E1,E/E1/E1a,E/E2,F"),
MT565("A,A/A1,B,B/B1,B/B2,C,D,E"),
MT566("A,A/A1,A/A2,B,B/B1,C,D,D/D1,D/D1/D1a,D/D1/D1b,D/D2,D/D2/D2a,D/D2/D2b,E"),
MT567("A,A/A1,A/A2,A/A2/A2a,B,C"),
MT568("A,A/A1,B,B/B1,C"),
MT569("A,A/A1,A/A2,B,C,C/C1,C/C1/C1a,C/C1/C1a/C1a1,C/C1/C1a/C1a1/C1a1A,D"),
MT575("A,A/A1,B,B/B1,B/B1/B1a,B/B1/B1a/B1a1,B/B1/B1a/B1a2,B/B1/B1a/B1a3,B/B1/B1a/B1a4,C,C/C1,C/C2,C/C2/C2a,D"),
MT576("A,A/A1,B,B/B1,B/B2,B/B2/B2a,B/B2/B2b,B/B2/B2c,C"),
MT578("A,A/A1,B,B/B1,C,C/C1,D,E,E/E1,E/E2,E/E3,F"),
MT586("A,A/A1,B,B/B1,B/B2,B/B3,B/B4,B/B4/B4a,B/B5,B/B6,B/B6/B6a,B/B6/B6b,C"),
MT600("A,B,C,D,D/D1,D/D1/D1a,D/D1/D1a/D1a1"),
MT601("A,B,B/B1,B/B1/B1a,B/B1/B1a/B1a1"),
MT620("A,B,C,D,E,F,G,G/G1,G/G2,H"),
MT670("A,A/A1,A/A2,B,B/B1,B/B2,C"),
MT671("A,A/A1,B,B/B1,B/B2,C"),
MT760("A,B,C"),
MT767("A,B,C");

private final String sequences;

MtSequenceEnum(String sequences) {
this.sequences = sequences;
}

/**
* Returns the sequence paths for this MT schema.
* Each sequence path represents a hierarchical structure within the MT schema.
*
* @return A Set of sequence paths.
*
*/
public Set<String> sequences() {
return Arrays.stream(sequences.split(","))
.collect(Collectors.toSet());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public enum IbanValidationResult {
INVALID_CHARACTERS("Invalid character '${found}' found"),
MISSING_CHECK_DIGITS("Missing check digits"),
INVALID_CHECK_DIGITS_FORMAT("Expected 2 check digits and found ${found}"),
IVALID_CHECK_DIGITS("The expected computed check digit is ${expectedCheckDigit} and ${found} was found"),
INVALID_CHECK_DIGITS("The expected computed check digit is ${expectedCheckDigit} and ${found} was found"),

MISSING_BBAN("Missing custom account number (BBAN)"),
BBAN_MAX_LENGTH(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ static IbanValidationResult validateCheckDigit(final String iban) {
if (calculateMod(iban) != 1) {
final String checkDigit = IBAN.getCheckDigits(iban);
final String expectedCheckDigit = calculateCheckDigit(iban);
IbanValidationResult result = IbanValidationResult.IVALID_CHECK_DIGITS;
IbanValidationResult result = IbanValidationResult.INVALID_CHECK_DIGITS;
result.setExpectedCheckDigit(expectedCheckDigit);
result.setFound(checkDigit);
return result;
Expand Down
73 changes: 55 additions & 18 deletions src/main/java/com/prowidesoftware/swift/model/SwiftMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -1298,43 +1298,66 @@ public String getMOR() {
}

/**
* Gets MUR (Message User Reference) from field 108 in the user header block (block 3) or in the text block
* (block 4). Notice for user to user messages this field is located at the user header, however for system messages
* (category 0) the field is located at the text block.
*
* <p>The MUR is the Message User Reference used by applications for reconciliation with ACK. It is a free-format
* Gets MUR (Message User Reference) from field 108.
* <p>
* For user to user messages (category 1 to 9) the MUR is located in the user header block (block 3). Where for
* system messages (category 0) the MUR is located in the text block (block 4). Moreover, system messages such as
* the MT011 could have the mandatory reconciliation MUR in the block 4, but also another MUR in the optional user
* header block (block 3), in such cases the returned MUR is the one in the block 4.
* <p>
* Order of precedence for MUR extraction is block 4, then block 3.
* <p>
* The MUR is the Message User Reference used by applications for reconciliation with ACK. It is a free-format
* field in which users may specify their own reference of up to 16 characters of the permitted character set.
*
* @return the value of field 108 if found, or null when not found neither in block 3 or block 4
* @return the value of field 108 if found, or null when not found neither in block 4 o block 3
* @since 7.0
*/
public String getMUR() {
if (this.block3 != null && this.block3.containsTag(Field108.NAME)) {
return this.block3.getTagValue(Field108.NAME);
}
// we check first the block 4, because system message could contain both MURs.
if (this.block4 != null && this.block4.containsTag(Field108.NAME)) {
return this.block4.getTagValue(Field108.NAME);
}
if (this.block3 != null && this.block3.containsTag(Field108.NAME)) {
return this.block3.getTagValue(Field108.NAME);
}
return null;
}

/**
* Sets the MUR (Message User Reference) in the user header block.
* <p>If a MUR field is present, its value will be overwritten.
* <p>The MUR is the Message User Reference used by applications for reconciliation with ACK.
* Sets the MUR (Message User Reference) field 108.
* <p>
* For system messages (category 0) the MUR is located in the text block (block 4). Thus, a field 108 is added to
* the block 4, or of the field exist its value is updated. For user to user messages (category 1 to 9) the MUR is
* added to the user header block (block 3), or if the field exist its value is updated.
* <p>
* The MUR is the Message User Reference used by applications for reconciliation with ACK.
* It is a free-format field in which users may specify their own reference of up to 16 characters
* of the permitted character set, and it is contained in a 108 field at the message user header (block 3).
*
* @param mur a non blank MUR value to set, if value is blank this method does nothing
* @param mur a non-blank MUR value to set, if value is blank this method does nothing
* @return this
* @since 7.10.4
*/
public SwiftMessage setMUR(String mur) {
if (StringUtils.isNotBlank(mur)) {
if (this.block3 == null) {
this.block3 = new SwiftBlock3();
if (isSystemMessage()) {
// for system messages we set or update the MUR in the block 4
if (this.block4 == null) {
this.block4 = new SwiftBlock4();
this.block4.append(new Field108(mur));
} else if (this.block4.containsTag(Field108.NAME)) {
this.block4.getTagByName(Field108.NAME).setValue(mur);
} else {
this.block4.append(new Field108(mur));
}
} else {
// for user to user messages we set or update the MUR in the block 3
if (this.block3 == null) {
this.block3 = new SwiftBlock3();
}
this.block3.builder().setField108(new Field108(mur));
}
this.block3.builder().setField108(new Field108(mur));
}
return this;
}
Expand Down Expand Up @@ -1644,7 +1667,7 @@ public final MtCategory getCategory() {
/**
* Returns true if message service id is anything but 01 = GPA/FIN Message (system and user-to-user)
*
* @return true if message is a service message, false otherwise
* @return true if message is a service message, false if not or cannot be determined (header is null)
* @since 7.8.8
*/
public final boolean isServiceMessage() {
Expand All @@ -1657,7 +1680,7 @@ public final boolean isServiceMessage() {
/**
* Returns true if message service id is 21 = GPA/FIN Message (ACK/NAK/UAK/UNK)
*
* @return true if it is a service message for acknowledgment, false if not or header is null and service id cannot be determined
* @return true if it is a service message for acknowledgment, false if not or cannot be determined (header is null)
* @since 7.8.9
*/
public boolean isServiceMessage21() {
Expand All @@ -1667,6 +1690,20 @@ public boolean isServiceMessage21() {
return this.block1.getServiceIdType() == ServiceIdType._21;
}

/**
* Returns true if this message is a system message.
* <p>
* System messages are categorized as Category 0 (MT0xx) messages. These messages are primarily used for
* administrative communication and system-related interactions between SWIFT users and the SWIFT network itself,
* rather than for financial transactions or operational communication.
* @return true if system message, false if not or cannot be determined (header is null)
* @since 9.5.3
*/
public boolean isSystemMessage() {
String type = getType();
return type != null && type.startsWith("0");
}

/**
* Returns true if this message is an ACK.
* This is determined by testing first if it is a system message, and second
Expand Down
Loading

0 comments on commit f433602

Please sign in to comment.