package com.aggrepoint.winlet.form;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Vector;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.aggrepoint.utils.StringUtils;
import com.aggrepoint.winlet.spring.WinletExceptionResolver;
import com.aggrepoint.winlet.utils.BeanProperty;
import com.aggrepoint.winlet.utils.PropertyTypeCode;
/**
*
* @author Jiangming Yang (yangjm@gmail.com)
*/
public class FormValidator implements PropertyTypeCode {
/** 日志 */
static final Log logger = LogFactory.getLog(WinletExceptionResolver.class);
static final Class<?>[] PARAMS = new Class<?>[] { HttpServletRequest.class,
Form.class };
Object controller;
String strName;
Pattern pattern;
String strId;
String strMethod;
ValidateResultType passSkip;
ValidateResultType failSkip;
String strErrorMsg;
Vector<String> vecArgs;
Method method;
boolean methodWithParam;
Object methodObject;
public FormValidator(Object c, String n, String p, String id,
String method, String ps, String fs, String error,
Vector<String> args) {
controller = c;
strName = n;
if ("".equals(strName))
pattern = Pattern.compile(p);
strId = id;
if (strId != null)
strId = strId.trim();
strMethod = method;
if ("property".equalsIgnoreCase(ps)
|| ValidateResultType.PASS_SKIP_PROPERTY.name().equals(ps))
passSkip = ValidateResultType.PASS_SKIP_PROPERTY;
else if ("all".equalsIgnoreCase(ps)
|| ValidateResultType.PASS_SKIP_ALL.name().equals(ps))
passSkip = ValidateResultType.PASS_SKIP_ALL;
else
passSkip = ValidateResultType.PASS_CONTINUE;
if ("continue".equalsIgnoreCase(fs)
|| ValidateResultType.FAILED_CONTINUE.name().equals(fs))
failSkip = ValidateResultType.FAILED_CONTINUE;
else if ("all".equalsIgnoreCase(fs)
|| ValidateResultType.FAILED_SKIP_ALL.name().equals(fs))
failSkip = ValidateResultType.FAILED_SKIP_ALL;
else
failSkip = ValidateResultType.FAILED_SKIP_PROPERTY;
strErrorMsg = error;
if (strErrorMsg == null)
strErrorMsg = "";
vecArgs = args;
String m = strMethod;
if (strMethod != null && !strMethod.equals("")) {
try {
int idx = strMethod.lastIndexOf(".");
if (idx == -1) {
methodObject = controller;
} else {
String name = strMethod.substring(0, idx);
m = strMethod.substring(idx + 1);
if (name.indexOf(".") > 0)
methodObject = PropertyUtils.getNestedProperty(
controller, name);
else
methodObject = PropertyUtils.getSimpleProperty(
controller, name);
}
try {
this.method = methodObject.getClass().getMethod(m, PARAMS);
methodWithParam = true;
} catch (NoSuchMethodException e) {
this.method = methodObject.getClass().getMethod(m);
methodWithParam = false;
}
} catch (Exception e) {
logger.error("Unable to find validation method \"" + strMethod
+ "\" in winlet \"" + controller.getClass().getName()
+ "\".", e);
}
}
}
public boolean matches(String field) {
if (pattern != null)
return pattern.matcher(field).find();
return strName.equals(field);
}
static Hashtable<String, Pattern> PATTERNS = new Hashtable<String, Pattern>();
static Pattern EMAIL = Pattern.compile(
"^[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$",
Pattern.CASE_INSENSITIVE);
static Pattern INT = Pattern.compile("^\\-?\\d+$");
static Pattern FLOAT = Pattern.compile("^\\-?\\d+(\\.\\d+)?$");
static Pattern getPattern(Vector<String> args) {
if (args == null || args.size() == 0)
return null;
String key = args.elementAt(0);
if (args.size() > 1)
key = key + "_" + args.elementAt(1);
Pattern p = PATTERNS.get(key);
if (p == null) {
if (args.size() == 1)
p = Pattern.compile(args.elementAt(0));
else
p = Pattern.compile(args.elementAt(0),
Integer.parseInt(args.elementAt(1)));
PATTERNS.put(key, p);
}
return p;
}
public ValidateResult validate(HttpServletRequest req, Form data,
Object value) {
if (strId != null && !strId.equals("")) {
try {
if (strId.equalsIgnoreCase("ne")) {
if (value == null || value.toString().equals(""))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("tne")) {
if (value == null || value.toString().trim().equals(""))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("eq")) {
if (value == null && !vecArgs.elementAt(0).equals(""))
return new ValidateResult(failSkip, strErrorMsg);
if (value != null
&& !vecArgs.elementAt(0).equals(value.toString()))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("neq")) {
if (value != null
&& vecArgs.elementAt(0).equals(value.toString()))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("teq")) {
if (value == null && !vecArgs.elementAt(0).equals(""))
return new ValidateResult(failSkip, strErrorMsg);
if (value != null
&& !vecArgs.elementAt(0).equals(
value.toString().trim()))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("maxlen")) { // 最大长度
int len = 0;
if (value != null)
if (vecArgs.size() > 1)
len = StringUtils.getDBLength(value.toString(),
Integer.parseInt(vecArgs.elementAt(1)));
else
len = value.toString().length();
if (len > Integer.parseInt(vecArgs.elementAt(0)))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("minlen")) { // 最小长度
int len = 0;
if (value != null)
if (vecArgs.size() > 1)
len = StringUtils.getDBLength(value.toString(),
Integer.parseInt(vecArgs.elementAt(1)));
else
len = value.toString().length();
if (len < Integer.parseInt(vecArgs.elementAt(0)))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("regexp")) { // 正则表达式
if (value == null)
return new ValidateResult(failSkip, strErrorMsg);
if (!getPattern(vecArgs).matcher(value.toString()).find())
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("email")) { // 电子邮件
if (value == null)
return new ValidateResult(failSkip, strErrorMsg);
if (!EMAIL.matcher(value.toString()).find())
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("int")) { // 整数
if (value == null)
return new ValidateResult(failSkip, strErrorMsg);
if (!INT.matcher(value.toString().replaceAll(",", ""))
.find())
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("float")) { // 浮点数
if (value == null)
return new ValidateResult(failSkip, strErrorMsg);
// 接受,在数字中
if (!FLOAT.matcher(value.toString().replaceAll(",", ""))
.find())
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase(">")
|| strId.equalsIgnoreCase("gt")) { // 大于
if (value == null)
return new ValidateResult(failSkip, strErrorMsg);
boolean noValue[] = new boolean[1];
boolean error = false;
Double val = 0d;
try {
val = (Double) BeanProperty.convert(value, DOUBLE,
noValue);
} catch (Exception e) {
error = true;
}
if (error || noValue[0]
|| val <= Double.parseDouble(vecArgs.elementAt(0)))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase(">=")
|| strId.equalsIgnoreCase("gteq")) { // 大于等于
if (value == null)
return new ValidateResult(failSkip, strErrorMsg);
boolean noValue[] = new boolean[1];
boolean error = false;
Double val = 0d;
try {
val = (Double) BeanProperty.convert(value, DOUBLE,
noValue);
} catch (Exception e) {
error = true;
}
if (error || noValue[0]
|| val < Double.parseDouble(vecArgs.elementAt(0)))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("<")
|| strId.equalsIgnoreCase("lt")) { // 小于
if (value == null)
return new ValidateResult(failSkip, strErrorMsg);
boolean noValue[] = new boolean[1];
boolean error = false;
Double val = 0d;
try {
val = (Double) BeanProperty.convert(value, DOUBLE,
noValue);
} catch (Exception e) {
error = true;
}
if (error || noValue[0]
|| val >= Double.parseDouble(vecArgs.elementAt(0)))
return new ValidateResult(failSkip, strErrorMsg);
} else if (strId.equalsIgnoreCase("<=")
|| strId.equalsIgnoreCase("lteq")) { // 小于等于
if (value == null)
return new ValidateResult(failSkip, strErrorMsg);
boolean noValue[] = new boolean[1];
boolean error = false;
Double val = 0d;
try {
val = (Double) BeanProperty.convert(value, DOUBLE,
noValue);
} catch (Exception e) {
error = true;
}
if (error || noValue[0]
|| val > Double.parseDouble(vecArgs.elementAt(0)))
return new ValidateResult(failSkip, strErrorMsg);
} else {
logger.error("Unsupported validation id \"" + strId + "\".");
return new ValidateResult(failSkip, strErrorMsg);
}
} catch (Exception e) {
logger.error("Error running validation id \"" + strId
+ "\" in winlet \"" + controller.getClass().getName()
+ "\".", e);
return new ValidateResult(failSkip, strErrorMsg);
}
} else if (method != null) {
try {
if (methodWithParam)
return (ValidateResult) method.invoke(methodObject, req,
data);
else
return (ValidateResult) method.invoke(methodObject);
} catch (Exception e) {
logger.error("Error running validation method \"" + strMethod
+ "\" in winlet \"" + controller.getClass().getName()
+ "\".", e);
return new ValidateResult(failSkip, strErrorMsg);
}
}
return new ValidateResult(passSkip);
}
}