I have a requirement to write a password validation service, which is to accept certain rules: I wrote code:
@Service
public class PasswordValidatonServiceImpl implements PasswordValidationService {
public static final String EMPTY_OR_NULL_PASSWORD = "Password Should not be empty";
public static final String ERROR_PASSWORD_LENGTH = "Password must be betwee 5 and 12 characters long.";
public static final String ERROR_PASSWORD_CASE = "Password must only contain lowercase letters.";
public static final String ERROR_LETTER_AND_DIGIT = "Password must contain both a letter and a digit.";
public static final String ERROR_PASSWORD_SEQUENCE_REPEATED = "Password must not contain any sequence of characters immediately followed by the same sequence.";
private Pattern checkCasePattern = Pattern.compile("[A-Z]");
private Pattern checkLetterAndDigit = Pattern
.compile("(?=.*[a-z])(?=.*[0-9])");
private Pattern checkSequenceRepetition = Pattern.compile("(\\w{2,})\\1");
/**
* @param password
* @return List<String> This method calls 4 more methods which validates
* password and return list of errors if any.
*/
public List<String> validatePassword(String password) {
List<String> failures = new ArrayList<String>();
if (StringUtils.isEmpty(password)) {
failures.add(EMPTY_OR_NULL_PASSWORD);
return failures;
} else {
checkLength(password, failures);
checkCase(password, failures);
checkLetterAndDigit(password, failures);
checkSequenceRepetition(password, failures);
return failures;
}
}
/**
* @param password
* @param failures
* This method will validate if there are any repeated character
* sequence, if found it will add error message to failures list.
*/
private void checkSequenceRepetition(String password, List<String> failures) {
Matcher matcher = checkSequenceRepetition.matcher(password);
if (matcher.find()) {
failures.add(ERROR_PASSWORD_SEQUENCE_REPEATED);
}
}
/**
* @param password
* @param failures
* This method will validate both letters and characters in
* password, if not found add a error message to the failures
* list.
*/
private void checkLetterAndDigit(String password, List<String> failures) {
Matcher matcher = checkLetterAndDigit.matcher(password);
if (!matcher.find()) {
failures.add(ERROR_LETTER_AND_DIGIT);
}
}
/**
* @param password
* @param failures
* This Method checks upper case and lower case letters in the
* password if there are any Upper case letters it will add error
* message to failures list.
*/
private void checkCase(String password, List<String> failures) {
Matcher matcher = checkCasePattern.matcher(password);
if (matcher.find()) {
failures.add(ERROR_PASSWORD_CASE);
}
}
/**
* @param string
* @param failures
* This Method will checks the length of the string, if string is
* less than 5 or more than 12 characters then it will add error
* message into failures list
*/
private void checkLength(String string, List<String> failures) {
if (string.length() < 5 || string.length() > 12) {
failures.add(ERROR_PASSWORD_LENGTH);
}
}
}
Now my requirement is to make this class is extensible, so, in future, if I want to add more rules/take out some rules, code changes should be minimal. How can I achieve this? any suggestions are appreciated.