/**
* Copyright (C) 2003-2011 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.webui.form.validator;
import org.exoplatform.commons.serialization.api.annotations.Serialized;
import org.exoplatform.web.application.CompoundApplicationMessage;
import org.exoplatform.webui.form.UIFormInput;
/**
* Validate username whether the value is only alpha lower, digit, dot and underscore with first, last character is alpha lower
* or digit and cannot contain consecutive underscore, dot or both.
*
* @author <a href="mailto:haint@exoplatform.com">Nguyen Thanh Hai</a>
* @date Sep 28, 2011
*/
@Serialized
public class UsernameValidator extends MultipleConditionsValidator {
protected static final int DEFAULT_MIN_LENGTH = 3;
protected static final int DEFAULT_MAX_LENGTH = 30;
protected Integer min = DEFAULT_MIN_LENGTH;
protected Integer max = DEFAULT_MAX_LENGTH;
public static final String ALLOWED_SYMBOLS = "'_', '.'";
// required by @Serialized
public UsernameValidator() {
}
public UsernameValidator(Integer min, Integer max) {
this.min = min;
this.max = max;
}
protected void validate(String value, String label, CompoundApplicationMessage messages, UIFormInput uiInput) {
validate(value, label, messages, min, max);
}
static void validate(String value, String label, CompoundApplicationMessage messages, Integer min, Integer max) {
char[] buff = value.toCharArray();
if (buff.length < min || buff.length > max) {
messages.addMessage("StringLengthValidator.msg.length-invalid",
new Object[] { label, min.toString(), max.toString() });
}
if (!Character.isLowerCase(buff[0])) {
messages.addMessage("FirstCharacterUsernameValidator.msg", new Object[] { label });
}
char c = buff[buff.length - 1];
if (!isLowerCaseLetterOrDigit(c)) {
messages.addMessage("LastCharacterUsernameValidator.msg", new Object[] { label, c });
}
boolean hasConsecutive = false;
boolean hasInvalid = false;
for (int i = 1; i < buff.length - 1; i++) {
c = buff[i];
if (isLowerCaseLetterOrDigit(c)) {
continue;
}
if (isSymbol(c)) {
char next = buff[i + 1];
if (isSymbol(next)) {
if (!hasConsecutive) {
messages.addMessage("ConsecutiveSymbolValidator.msg", new Object[] { label, ALLOWED_SYMBOLS });
hasConsecutive = true;
}
} else if (!Character.isLetterOrDigit(next)) {
if (!hasInvalid) {
messages.addMessage("UsernameValidator.msg.Invalid-char", new Object[] { label });
hasInvalid = true;
}
}
} else {
if (!hasInvalid) {
messages.addMessage("UsernameValidator.msg.Invalid-char", new Object[] { label });
hasInvalid = true;
}
}
// if we have both error conditions, fail "fast" instead of going on
if (hasConsecutive && hasInvalid) {
break;
}
}
}
private static boolean isLowerCaseLetterOrDigit(char character) {
return Character.isDigit(character) || (character >= 'a' && character <= 'z');
}
private static boolean isSymbol(char c) {
return c == '_' || c == '.';
}
}