//import org.apache.log4j.Logger;
import org.apache.commons.lang.StringUtils;
import java.util.Set;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.List;
/**
*/
public class UserValidator {
public static final int PHONE_NUMBER_MIN_LENGTH = 8;
public static final int PASSWORD_MIN_LENGTH = 6;
public static final int PASSWORD_MAX_LENGTH = 15;
public static final int IMEISV_LENGTH = 17;
public static final int IMEI_LENGTH = 15;
// private static Logger logger = Logger.getLogger(UserValidator.class);
private UserProductDao userProductDao;
private AddressDao addressDao;
private OperatorDao operatorDao;
public UserValidator(UserProductDao userProductDao, AddressDao addressDao, OperatorDao operatorDao) {
this.userProductDao = userProductDao;
this.addressDao = addressDao;
this.operatorDao = operatorDao;
}
public boolean validateApiUserForRegister(ApiUser apiUser,
List<ApiStatusMessage> messages) {
int initialSize = messages.size();
String email = apiUser.getEmailAddress();
if(isEmail(email)) {
if(email.length() > User.EMAIL_ADDRESS_MAX_LENGTH) {
messages.add(new ApiStatusMessage(EMAIL_ADDRESS_TOO_LONG_MESSAGE, EMAIL_ADDRESS_TOO_LONG));
} else {
apiUser.setEmailAddress(email.toLowerCase());
}
} else {
messages.add(new ApiStatusMessage(INVALID_EMAIL_ADDRESS_MESSAGE, INVALID_EMAIL_ADDRESS));
}
if(apiUser.getLocale() == null
&& apiUser.getLocationId() == null
&& (apiUser.getAddress() == null || apiUser.getAddress().getCountryCode() == null)) {
messages.add(new ApiStatusMessage(LOCALE_IS_NULL_MESSAGE, LOCALE_IS_NULL));
}
if(apiUser.getMsisdn() != null && !isPhoneNumber(apiUser.getMsisdn())) {
messages.add(new ApiStatusMessage(INVALID_PHONE_NUMBER_MESSAGE, INVALID_PHONE_NUMBER));
}
validateOperator(apiUser, messages);
String gender = apiUser.getGender();
if(gender != null && !isGender(gender.toLowerCase())) {
messages.add(new ApiStatusMessage(
INVALID_GENDER_MESSAGE + ": " + gender,
INVALID_GENDER));
}
validateAddress(apiUser.getAddress(), messages);
validatePhones(apiUser, messages);
validateAccessories(apiUser, messages);
ApiUserApplication currentApplication = apiUser.getCurrentApplication();
if(currentApplication != null) {
validateApplicationAttributes(currentApplication.getAttributes(), messages);
validateSubscriptions(currentApplication.getSubscriptions(), messages);
}
ApiUserApplication commonApplication = apiUser.getCommonApplication();
if(commonApplication != null) {
validateApplicationAttributes(commonApplication.getAttributes(), messages);
validateSubscriptions(commonApplication.getSubscriptions(), messages);
}
return messages.size() == initialSize;
}
private void validateOperator(ApiUser apiUser, List<ApiStatusMessage> messages) {
ApiOperator apiOperator = apiUser.getOperator();
if(apiOperator == null || ( apiOperator.getName() == null && apiOperator.getOperatorId() == null)) {
return;
}
if(apiOperator.getOperatorId() == null) {
Operator operator = operatorDao.findOperatorByName(apiOperator.getName());
if(operator == null) {
messages.add(new ApiStatusMessage(INVALID_OPERATOR_NAME_MESSAGE, INVALID_OPERATOR_NAME));
} else {
apiOperator.setOperatorId(operator.getOperatorId());
}
} else if(operatorDao.findOperatorByOperatorId(apiOperator.getOperatorId()) == null) {
messages.add(new ApiStatusMessage(INVALID_OPERATOR_ID_MESSAGE, INVALID_OPERATOR_ID));
}
}
public boolean validateApiUserForUpdate(ApiUser apiUser,
List<ApiStatusMessage> messages) {
int initialSize = messages.size();
if(apiUser.getGender() != null) {
String gender = apiUser.getGender().toLowerCase().trim();
if(!("".equals(gender) || UserValidator.isGender(gender))) {
messages.add(new ApiStatusMessage(
INVALID_GENDER_MESSAGE + ": " + apiUser.getGender(),
INVALID_GENDER));
}
}
if(apiUser.getMsisdn() != null && !isPhoneNumber(apiUser.getMsisdn())) {
messages.add(new ApiStatusMessage(INVALID_PHONE_NUMBER_MESSAGE, INVALID_PHONE_NUMBER));
}
validateOperator(apiUser, messages);
validateAddress(apiUser.getAddress(), messages);
ApiUserApplication currentApplication = apiUser.getCurrentApplication();
if(currentApplication != null) {
validateApplicationAttributes(currentApplication.getAttributes(), messages);
validateSubscriptions(currentApplication.getSubscriptions(), messages);
}
ApiUserApplication commonApplication = apiUser.getCommonApplication();
if(commonApplication != null) {
validateApplicationAttributes(commonApplication.getAttributes(), messages);
validateSubscriptions(commonApplication.getSubscriptions(), messages);
}
validatePhones(apiUser, messages);
validateAccessories(apiUser, messages);
return messages.size() == initialSize;
}
public boolean validateEmailVerificationPolicy(VerificationPolicyRegisterUser policy,
List<ApiStatusMessage> messages) {
boolean valid;
switch(policy.getEmailOption()) {
case SEND_DEFAULT_ACTIVATION_EMAIL:
valid = policy.getEmailVerificationStatus() == EmailVerificationStatus.NOT_VERIFIED ||
policy.getEmailVerificationStatus() == EmailVerificationStatus.VERIFICATION_IN_PROGRESS;
break;
case SEND_DEFAULT_CONFIRMATION_EMAIL:
case SEND_NO_REGISTRATION_EMAIL:
valid = policy.getEmailVerificationStatus() == EmailVerificationStatus.NOT_VERIFIED ||
policy.getEmailVerificationStatus() == EmailVerificationStatus.VERIFIED;
break;
case SEND_DEFAULT_BATCH_IMPORT_EMAIL:
valid = policy.getEmailVerificationStatus() == EmailVerificationStatus.VERIFICATION_IN_PROGRESS ||
policy.getEmailVerificationStatus() == EmailVerificationStatus.VERIFIED;
break;
case SEND_CUSTOM_BATCH_IMPORT_EMAIL:
valid = policy.getEmailVerificationStatus() == EmailVerificationStatus.VERIFICATION_IN_PROGRESS ||
policy.getEmailVerificationStatus() == EmailVerificationStatus.VERIFIED;
valid &= policy.getCustomEmailMessagentId() != null;
break;
default:
throw new RuntimeException("Unexpected new user option " + policy.getEmailOption());
}
if(!valid) {
messages.add(new ApiStatusMessage(INVALID_POLICY_REGISTER_USER_MESSAGE, INVALID_POLICY_REGISTER_USER));
}
return valid;
}
public boolean validateEmailVerificationPolicy(VerificationPolicyUpdateUser policy,
List<ApiStatusMessage> messages) {
boolean valid = true;
if(policy.getEmailOption() == EmailOptionUpdateUser.SEND_CUSTOM_WELCOME_EMAIL && policy.getWelcomeEmailMessagentId() == null) {
valid = false;
messages.add(new ApiStatusMessage(INVALID_POLICY_UPDATE_USER_MESSAGE,
INVALID_POLICY_UPDATE_USER));
}
return valid;
}
public boolean validatePhones(ApiUser apiUser, List<ApiStatusMessage> messages) {
List<ApiPhone> phones = apiUser.getPhones();
if (phones == null || isDeleteMarker(phones)) {
return true;
}
boolean success = true;
for (ApiPhone phone : phones) {
success &= validatePhone(phone, messages);
}
return success & validateOnePrimaryPhone(phones, messages);
}
/**
* @param products The product list to test
* @return true if the phone is a delete marker and false otherwise
*/
public boolean isDeleteMarker(List products) {
if(products == null || products.size() != 1) return false;
ApiProduct product = (ApiProduct) products.get(0);
return product.getContentServicesId() == null && product.getName() == null && product.getGpdId() == 0;
}
public boolean validatePhone(ApiPhone apiPhone, List<ApiStatusMessage> messages) {
boolean validPhone = true;
String imei = apiPhone.getImei();
if(imei != null && !UserValidator.isIMEINumber(imei)) {
messages.add(new ApiStatusMessage(
INVALID_IMEI_NUMBER_MESSAGE + ": " + imei,
INVALID_IMEI_NUMBER));
validPhone = false;
}
// use brand name as first choise vs. brandId
String phoneBrandName = apiPhone.getBrandName();
short brandId = (short)apiPhone.getGpdBrandId();
if(StringUtils.isEmpty(phoneBrandName)) {
phoneBrandName = userProductDao.getPhoneBrandName(brandId);
if(phoneBrandName == null) {
messages.add(new ApiStatusMessage(
INVALID_PHONE_BRAND_ID_MESSAGE + ": " + apiPhone.getGpdBrandId(),
INVALID_PHONE_BRAND_ID));
validPhone = false;
}
} else {
brandId = userProductDao.getPhoneBrandId(phoneBrandName);
}
if(brandId == UserProductDao.UNKNOWN_PHONE_BRAND_ID) {
messages.add(new ApiStatusMessage(
INVALID_PHONE_BRAND_NAME_MESSAGE + ": " + phoneBrandName,
INVALID_PHONE_BRAND_NAME));
validPhone = false;
}
return validPhone;
}
public boolean validateAccessories(ApiUser apiUser, List<ApiStatusMessage> messages) {
List<ApiAccessory> accessories = apiUser.getAccessories();
if (accessories == null || isDeleteMarker(accessories)) {
return true;
}
boolean success = true;
for (ApiAccessory apiAccessory : accessories) {
Product product = userProductDao.getProductByApiProduct(apiAccessory);
if(product == null) {
messages.add(new ApiStatusMessage(
INVALID_ACCESSORY_MESSAGE,
INVALID_ACCESSORY));
success = false;
}
}
return success;
}
/**
* Validates that the phones array contains exactly one phone which is primary OR no phones (null or zero length array).
* A user does not have to have any phones.
*
* @param phones the phones to validate
* @param messages the message collection to put possible error messages in
* @return true if phones is null or empty, or if it contains exactly one primary phone
*/
public boolean validateOnePrimaryPhone(List<ApiPhone> phones, List<ApiStatusMessage> messages) {
if(phones == null || phones.size() == 0) {
return true;
}
boolean isValid = true;
int primaryPhonesCount = 0;
for (ApiPhone phone : phones) {
if (phone.isPrimary()) {
primaryPhonesCount++;
}
}
if(primaryPhonesCount == 0) {
isValid = false;
messages.add(new ApiStatusMessage(NO_PRIMARY_PHONE_MESSAGE, NO_PRIMARY_PHONE));
} else if(primaryPhonesCount > 1) {
isValid = false;
messages.add(new ApiStatusMessage(MORE_THAN_ONE_PRIMARY_PHONE_MESSAGE, MORE_THAN_ONE_PRIMARY_PHONE));
}
return isValid;
}
/**
* Validates and AddressBean.
* @param address The AddressBean to validate
* @param messages the message collection to put possible error messages in
* @return true if address is null or valid
*/
public boolean validateAddress(ApiAddress address, List<ApiStatusMessage> messages) {
if(address == null) return true;
boolean isValid = true;
if(!isState(address.getUSState())) {
isValid = false;
messages.add(new ApiStatusMessage(
INVALID_STATE_MESSAGE +": " + address.getUSState(),
INVALID_STATE));
}
if(!isCountryCode(address.getCountryCode())) {
isValid = false;
messages.add(new ApiStatusMessage(
INVALID_COUNTRY_CODE_MESSAGE + ": " + address.getCountryCode(),
INVALID_COUNTRY_CODE));
}
return isValid;
}
public boolean isState(String state) {
return state == null || "".equals(state.trim()) || addressDao.checkState(state);
}
public boolean isCountryCode(String countryCode) {
return countryCode == null || "".equals(countryCode.trim()) || addressDao.checkCountryCode(countryCode);
}
/**
* Verifies that application attribute keys are unique.
* @param pairs The collection of aplication-specific attributes.
* @param messages the message collection to put possible error messages in
* @return true if pairs is a valid application attribute collection, otherwise false
*/
public boolean validateApplicationAttributes(List<ApiKeyValuePair> pairs, List<ApiStatusMessage> messages) {
if(pairs == null) {
// no attributes to create/update
return true;
}
// if(pairs.size() == 1 && pairs.get(0).getKey() == null && pairs.get(0).getValue() == null) {
// attempt to remove all attributes: accepted
// return true;
// }
boolean isValid = true;
Set<String> keys = new HashSet<String>();
for (ApiKeyValuePair pair : pairs) {
if(pair == null) {
messages.add(new ApiStatusMessage(
APPLICATION_ATTRIBUTE_NULL_MESSAGE,
APPLICATION_ATTRIBUTE_NULL));
isValid = false;
continue;
}
String key = pair.getKey();
if(StringUtils.isEmpty(key)) {
messages.add(new ApiStatusMessage(
APPLICATION_ATTRIBUTE_KEY_IS_EMPTY_MESSAGE + ", key: " + key,
APPLICATION_ATTRIBUTE_KEY_IS_EMPTY));
isValid = false;
continue;
}
if(keys.contains(key)) {
messages.add(new ApiStatusMessage(
APPLICATION_ATTRIBUTE_KEY_NOT_UNIQUE_MESSAGE + ": " + key,
APPLICATION_ATTRIBUTE_KEY_NOT_UNIQUE ));
isValid = false;
}
keys.add(key);
}
return isValid;
}
/**
* Verifies that application attribute keys are unique.
* @param subscriptions The set of subscriptions.
* @param messages the message collection to put possible error messages in
* @return true if pairs is a valid application attribute collection, otherwise false
*/
public boolean validateSubscriptions(Set<Integer> subscriptions, List<ApiStatusMessage> messages) {
if(subscriptions == null) {
// no subscriptions to create/update
return true;
}
if(subscriptions.size() == 1 && subscriptions.contains(0)) {
// delete marker, attempt to remove all attributes: accepted
return true;
}
boolean isValid = true;
for (Integer subscription : subscriptions) {
if(subscription <= 0) {
messages.add(new ApiStatusMessage(
INVALID_SUBSCRIPTION_ID_MESSAGE + ": " + subscription,
INVALID_SUBSCRIPTION_ID));
isValid = false;
}
}
return isValid;
}
/**
* Validates that a string contains an email address.
* These must be in the format a@b.c
* @param input The email address
* @return True if the input is an email address.
*/
public static boolean isEmail(String input) {
if(input == null) return false;
// Divide string into two elements around the hyhpen
StringTokenizer tokenizerAt = new StringTokenizer(input, "@");
// Accept only one @-character, two elements
if (tokenizerAt.countTokens() != 2) return false;
// First (local) part of address
// Cannot contain controls or space chars
String firstElement = (String) tokenizerAt.nextElement();
char[] firstChars = firstElement.toCharArray();
for (char aChar : firstChars) {
if (Character.isISOControl(aChar) || Character.isSpaceChar(aChar)) {
return false;
}
}
// Second (domain) part of address
String secondElement = (String) tokenizerAt.nextElement();
// Must not start or end with periods
if (isPeriod(secondElement.charAt(0))) return false;
if (isPeriod(secondElement.charAt(secondElement.length() - 1)))
return false;
// Divide into sub-domains
StringTokenizer tokenizerPeriod = new StringTokenizer(secondElement, ".");
// Must be at least two elements
// Note: This is not necessary according to RFC822 but a much
// more realistic test
if (tokenizerPeriod.countTokens() < 2) return false;
// Each domain cannot contain controls or space chars
while (tokenizerPeriod.hasMoreElements()) {
String element = (String) tokenizerPeriod.nextElement();
char[] domainChars = element.toCharArray();
for (char aChar : domainChars) {
if (Character.isISOControl(aChar) || Character.isSpaceChar(aChar)) {
return false;
}
}
}
return true;
}
/**
* A valid phone number starts with '+' sign and is followed by at least 8 digits.
* @param input The phone number
* @return True if the input is a valid phone number
*/
public static boolean isPhoneNumber(String input) {
return input != null && input.startsWith("+")
&& StringUtils.isNumeric(input.substring(1)) && input.length() > PHONE_NUMBER_MIN_LENGTH;
}
/**
*
* @param input Supposed to contain a positive long
* @return True if the input is a positive long
*/
public static boolean isPositiveLong(String input) {
if(input == null)
return false;
try {
long locationId = Long.parseLong(input);
if(locationId < 0)
return false;
} catch(NumberFormatException e) {
return false;
}
return true;
}
/**
* A valid password has the following properties:
*
* <ul>
* <li>it is between 6 and 15 characters long</li>
* <li>it contains at least one letter and at least one digit</li>
* <li>it does not contain white space</li>
* </ul>
*
* @param input The password to be verified
* @return true if input is a password, false otherwise
*/
public static boolean isPassword(String input) {
if (input == null || input.length() < PASSWORD_MIN_LENGTH || input.length() > PASSWORD_MAX_LENGTH) {
return false;
}
boolean someLetters = false;
boolean someDigits = false;
for (int i = 0; i < input.length(); ++i) {
char ch = input.charAt(i);
if (Character.isLetter(ch)) {
someLetters = true;
} else if(Character.isDigit(ch)){
someDigits = true;
} else if (Character.isWhitespace(input.charAt(i)))
return false;
}
return someLetters && someDigits;
}
/**
* Accept 15 (IMEI with checksum), 16 digits(IMEISV without checksum with software version) and
* 17 digits (IMEISV with checksum and software version), along with any number of hyphens ('-').
*
* @param number The IMEI number to validate
* @return true if the number is valid, false otherwise.
*/
public static boolean isIMEINumber(String number) {
if(number == null) return false;
String stripped = number.replaceAll("-","");
stripped = stripped.replaceAll(" ","");
if(!StringUtils.isNumeric(stripped)) {
return false;
} else if(stripped.length() == IMEI_LENGTH) {
return checkIMEINumber(stripped);
} else if(stripped.length() == IMEISV_LENGTH) {
return checkIMEINumber(stripped.substring(0, IMEI_LENGTH));
} else if(stripped.length() == IMEISV_LENGTH -1) {
return true;
}
return false;
}
/**
* Checks whether a string of digits is a valid IMEI number according
* to the Luhn algorithm, see [url=http://en.wikipedia.org/wiki/Luhn_algorithm]http://en.wikipedia.org/wiki/Luhn_algorithm[/url]
*
* 1. Starting with the second to last digit and moving left, double the
* value of all the alternating digits. For any digits that thus become
* 10 or more, add their digits together. For example, 1111 becomes 2121,
* while 8763 becomes 7733 (from (1+6)7(1+2)3).
*
* 2. Add all these digits together. For example, 1111 becomes 2121, then
* 2+1+2+1 is 6; while 8763 becomes 7733, then 7+7+3+3 is 20.
*
* 3. If the total ends in 0 (put another way, if the total modulus 10 is
* 0), then the number is valid according to the Luhn formula, else it is
* not valid. So, 1111 is not valid (as shown above, it comes out to 6),
* while 8763 is valid (as shown above, it comes out to 20).
*
* @param number the IMEI number to validate.
* @return true if the number is valid, false otherwise.
*/
public static boolean checkIMEINumber(String number) {
int sum = 0;
boolean alternate = false;
for (int i = number.length() - 1; i >= 0; i--) {
int digit;
try {
digit = Integer.parseInt(number.substring(i, i + 1));
} catch (NumberFormatException e) {
return false;
}
if (alternate) {
digit *= 2;
if (digit > 9) {
digit = (digit % 10) + 1;
}
}
sum += digit;
alternate = !alternate;
}
return (sum % 10 == 0);
}
public static boolean isGender(String input) {
return input != null &&
(input.equals(FEMALE_GENDER) || input.equals(MALE_GENDER));
}
// Private helper methods
private static boolean isPeriod(char aChar) {
return areEqual(aChar, '.');
}
private static boolean areEqual(char left, char right) {
return new Character(left).compareTo(right) == 0;
}
}
Mod Edit: Fixed code tags:

New Topic/Question
Reply




MultiQuote




|