All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.schegge.bank.validator.IbanValidator Maven / Gradle / Ivy

The newest version!
package de.schegge.bank.validator;

import de.schegge.bank.BankService;
import de.schegge.bank.IbanLocale;
import de.schegge.bank.validator.IBAN.IbanType;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.math.BigInteger;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class IbanValidator implements ConstraintValidator {

    public static final Pattern PATTERN = Pattern.compile("([A-Z]{2})(\\d{2})([A-Z0-9]{11,30})");

    private static final BigInteger VALUE_97 = BigInteger.valueOf(97);
    private static final int[] CHAR_VALUES = charValues();

    private Check check;
    private IbanType type;

    private static int[] charValues() {
        String characterValues = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        int[] result = new int['Z' + 1];
        for (int i = 0; i < characterValues.length(); i++) {
            result[characterValues.charAt(i)] = i;
        }
        return result;
    }

    @Override
    public void initialize(IBAN constraintAnnotation) {
        check = constraintAnnotation.check();
        type = constraintAnnotation.type();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        if (value == null) {
            return true;
        }
        Matcher matcher = PATTERN.matcher(value);
        if (!matcher.matches()) {
            return false;
        }

        String countryCode = matcher.group(1);
        int checkDigit = Integer.parseInt(matcher.group(2));
        String basicBankAccountNumber = matcher.group(3);
        if (isValidChecksum(countryCode, basicBankAccountNumber, checkDigit)) {
            return false;
        }

        IbanLocale ibanLocale = IbanLocale.byCode(countryCode);
        if (ibanLocale == null) {
            return check == Check.LENIENT;
        }
        if (type == IbanType.SEPA && !IbanLocale.allSepaIbanLocales().contains(ibanLocale)) {
            return false;
        }
        if (type == IbanType.NO_SEPA && IbanLocale.allSepaIbanLocales().contains(ibanLocale)) {
            return false;
        }
        if (basicBankAccountNumber.length() != ibanLocale.getLength() - 4) {
            return false;
        }
        if (check == Check.LENIENT) {
            return true;
        }
        Optional bankService = BankService.byCountry(countryCode);
        if (bankService.isEmpty()) {
            return check == Check.PRAGMATIC;
        }
        return bankService.map(x -> x.byBasicBankAcountNumber(basicBankAccountNumber)).isPresent();
    }

    private static boolean isValidChecksum(String countryCode, String basicBankAccountNumber, int checkDigit) {
        StringBuilder builder = new StringBuilder(basicBankAccountNumber.length());
        basicBankAccountNumber.chars().mapToObj(c -> CHAR_VALUES[c]).map(String::valueOf).forEach(builder::append);
        countryCode.chars().mapToObj(c -> CHAR_VALUES[c]).map(String::valueOf).forEach(builder::append);
        return checkDigit != 98 - new BigInteger(builder.append("00").toString()).mod(VALUE_97).intValue();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy