com.prowidesoftware.swift.model.IbanValidationUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pw-swift-core Show documentation
Show all versions of pw-swift-core Show documentation
Prowide Library for SWIFT messages
/*
* Copyright 2006-2023 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;
import com.prowidesoftware.swift.utils.IsoUtils;
/**
* Helper API for IBAN validation
*
* @author psantamarina
* @since 7.9.7
*/
class IbanValidationUtils {
static final String IBAN_DEFAULT_CHECK_DIGIT = "00";
private static final int MOD = 97;
private static final long MAX = 999999999;
private static final int MAX_BBAN_LENGTH = 30;
// Suppress default constructor for noninstantiability
private IbanValidationUtils() {
throw new AssertionError();
}
/**
* Checks the IBAN country code
*
* @return problem found or null if country code is OK
*/
static IbanValidationResult validateCountryCode(final String iban) {
// check if iban contains 2 char country code
if (iban.length() < IBAN.COUNTRY_CODE_LENGTH) {
return IbanValidationResult.MISSING_COUNTRY_CODE;
}
final String countryCode = IBAN.getCountryCode(iban);
// check case sensitivity
if (!countryCode.equals(countryCode.toUpperCase())
|| !Character.isLetter(countryCode.charAt(0))
|| !Character.isLetter(countryCode.charAt(1))) {
IbanValidationResult result = IbanValidationResult.INVALID_COUNTRY_CODE_CHARSET;
result.setFound(countryCode);
return result;
}
if (!IsoUtils.getInstance().isValidISOCountry(countryCode)) {
IbanValidationResult result = IbanValidationResult.INVALID_COUNTRY_CODE;
result.setFound(countryCode);
return result;
}
return null;
}
/**
* Checks the check digits are present
*
* @return problem found or null if OK
*/
static IbanValidationResult validateCheckDigitPresence(final String iban) {
// check if iban contains 2 digit check digit
if (iban.length() < IBAN.COUNTRY_CODE_LENGTH + IBAN.CHECK_DIGIT_LENGTH) {
return IbanValidationResult.MISSING_CHECK_DIGITS;
}
final String checkDigit = IBAN.getCheckDigits(iban);
// check digits
if (!Character.isDigit(checkDigit.charAt(0)) || !Character.isDigit(checkDigit.charAt(1))) {
IbanValidationResult result = IbanValidationResult.INVALID_CHECK_DIGITS_FORMAT;
result.setFound(checkDigit);
return result;
}
return null;
}
/**
* Checks the BBAN is present
*
* @return problem found or null if OK
* @since 7.9.7
*/
static IbanValidationResult validateBbanPresence(final String iban) {
if (iban.length() <= IBAN.COUNTRY_CODE_LENGTH + IBAN.CHECK_DIGIT_LENGTH) {
return IbanValidationResult.MISSING_BBAN;
}
return null;
}
/**
* Validates Bban max length
*
* @param bban the BBAN part of the IBAN to check
* @return problem found or null if OK
* @since 7.9.7
*/
static IbanValidationResult validateBbanMaxLength(final String bban) {
if (bban.length() > MAX_BBAN_LENGTH) {
IbanValidationResult result = IbanValidationResult.BBAN_MAX_LENGTH;
result.setExpectedLength(MAX_BBAN_LENGTH);
result.setFoundLength(bban.length());
return result;
}
return null;
}
/**
* Validates Bban length
*
* @param bban the BBAN part of the IBAN to check
* @param structure structure to check
* @return problem found or null if OK
* @since 7.9.7
*/
static IbanValidationResult validateBban(final String bban, final BbanStructureDTO structure) {
final int expectedBbanLength = getBbanLengh(structure);
if (expectedBbanLength != bban.length()) {
IbanValidationResult result = IbanValidationResult.BBAN_INVALID_LENGTH;
result.setFound(bban);
result.setFoundLength(bban.length());
result.setExpectedLength(expectedBbanLength);
return result;
}
int bbanEntryOffset = 0;
for (final BbanStructureEntryDTO entry : structure.getValidation_rules()) {
final int entryLength = entry.getLength();
String entryValue = bban.substring(bbanEntryOffset, bbanEntryOffset + entryLength);
bbanEntryOffset = bbanEntryOffset + entryLength;
// validate character type
IbanValidationResult result = validateBbanEntryCharacterType(entry, entryValue);
if (result != null) {
return result;
}
}
return null;
}
/**
* Returns bban's length.
*
* @param bbanStructure BbanStructureDTO
* @return Returns bban's length
* @since 7.9.7
*/
private static int getBbanLengh(BbanStructureDTO bbanStructure) {
int length = 0;
for (BbanStructureEntryDTO entry : bbanStructure.getValidation_rules()) {
length += entry.getLength();
}
return length;
}
/**
* Checks the check digits are present
*
* @return problem found or null if OK
* @since 7.9.7
*/
private static IbanValidationResult validateBbanEntryCharacterType(
final BbanStructureEntryDTO entry, final String entryValue) {
if (SwiftCharsetUtils.is(entryValue, entry.getCharacterType()) != SwiftCharsetUtils.OK) {
IbanValidationResult result = null;
switch (entry.getCharacterType()) {
case a:
result = IbanValidationResult.BBAN_INVALID_UPPER_CASE_LETTERS;
break;
case c:
result = IbanValidationResult.BBAN_INVALID_DIGITS_OR_LETTERS;
break;
case n:
result = IbanValidationResult.BBAN_INVALID_DIGITS;
break;
default:
break;
}
if (result != null) {
result.setFound(entryValue);
result.setBbanEntryType(entry.getEntryType());
return result;
}
}
return null;
}
/**
* Validates the check digits
*
* @return problem found or null if OK
* @since 7.9.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;
result.setExpectedCheckDigit(expectedCheckDigit);
result.setFound(checkDigit);
return result;
}
return null;
}
/**
* Validates the IBAN characters numeric range
*
* @return problem found or null if OK
* @since 7.9.7
*/
static IbanValidationResult validateCharacters(final String iban) {
for (int i = 0; i < iban.length(); i++) {
final int numericValue = Character.getNumericValue(iban.charAt(i));
if (numericValue < 0 || numericValue > 35) {
IbanValidationResult result = IbanValidationResult.INVALID_CHARACTERS;
result.setFound(String.valueOf(iban.charAt(i)));
return result;
}
}
return null;
}
/**
* Calculates Iban
* Check Digit.
*
* @param iban string value
* @return check digit as String
* @since 7.9.7
*/
private static String calculateCheckDigit(final String iban) {
final String reformattedIban = replaceCheckDigit(iban, IBAN_DEFAULT_CHECK_DIGIT);
final int modResult = calculateMod(reformattedIban);
final int checkDigitIntValue = 98 - modResult;
final String checkDigit = Integer.toString(checkDigitIntValue);
return checkDigitIntValue > 9 ? checkDigit : "0" + checkDigit;
}
/**
* Returns an iban with replaced check digit.
*
* @param iban The iban
* @return The iban without the check digit
* @since 7.9.7
*/
private static String replaceCheckDigit(final String iban, final String checkDigit) {
return IBAN.getCountryCode(iban) + checkDigit + IBAN.getBban(iban);
}
/**
* Calculates
* Iban Modulo.
*
* @param iban String value
* @return modulo 97
* @since 7.9.7
*/
private static int calculateMod(final String iban) {
final String reformattedIban = IBAN.getBban(iban) + IBAN.getCountryCode(iban) + IBAN.getCheckDigits(iban);
long total = 0;
for (int i = 0; i < reformattedIban.length(); i++) {
final int numericValue = Character.getNumericValue(reformattedIban.charAt(i));
total = (numericValue > 9 ? total * 100 : total * 10) + numericValue;
if (total > MAX) {
total = total % MOD;
}
}
return (int) (total % MOD);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy