package com.creditcard4j.tools;
import com.creditcard4j.exception.CreditCard4JException;
import static com.creditcard4j.tools.Preconditions.checkIsDigitsOnly;
import static com.creditcard4j.tools.Preconditions.checkLongerThan;
/**
* Implementation of the Luhn Algorithm.
*
* @author Vincent DURMONT [vdurmont@gmail.com]
*/
public class Luhn {
/**
* Checks the given number against the Luhn algorithm.
*
* @param number the number to study
*
* @return true if the number is valid
* @throws java.lang.IllegalArgumentException if the card number is malformed
* @throws com.creditcard4j.exception.CreditCard4JException is the card number is less than 2 digits long
*/
public static boolean isValid(String number) {
checkLongerThan("The number must have at least 2 characters.", number, 2);
checkIsDigitsOnly("Only digits are allowed", number);
int length = number.length();
// We will study all the digits but the last
char[] chars = number.substring(0, length - 1).toCharArray();
// Init the sum with the check digit
int sum = Character.getNumericValue(number.charAt(length - 1));
for (int i = 0; i < length - 1; i++) {
// Get the digit
int value = Character.getNumericValue(chars[length - i - 2]);
// For each other digit multiply the value by 2
value *= (i % 2 == 1) ? 1 : 2;
// If the result has 2 digits, we replace it by the sum of the 2 digits
// Incrementing the sum by the result.
sum += value < 10 ? value : value - 9;
}
// If the sum % 10 == 0, the number is valid
return sum % 10 == 0;
}
/**
* Checks the validity of the card number against the Luhn algorithm.
*
* @param number the card number
*
* @return the validated number
* @throws java.lang.IllegalArgumentException if the number is malformed
* @throws com.creditcard4j.exception.CreditCard4JException if the number is invalid
*/
public static String checkValidity(String number) {
if (!isValid(number)) {
throw new CreditCard4JException("Invalid card number (Luhn Algorithm failed)");
}
return number;
}
}