private BeanResolver createResolver() {
BeanResolver obj = null;
try {
ClassPool cp = DynamicBeanUtils.getClassPool();
CtClass ctClass = cp.makeClass(GuavaUtil.JOIN_DOLLAR.join(
_CreatedImpl, Math.abs(DynamicBeanUtils.random.nextInt()), System.currentTimeMillis()));
ctClass.addInterface(cp.get(_BeanResolver));
ctClass.addField(CtField.make("private String $prefix;", ctClass));
ctClass.addField(CtField.make("private " + _Separator + " $separator;", ctClass));
ctClass.addMethod(CtMethod.make("public void setSeparator(" + _Separator + " sp){$separator=sp;}", ctClass));
CtMethod makePath = CtMethod.make(
"private String makePath(String name) {" +
" return ($prefix == null) ? name : $separator.createParamKey(new Object[] { $prefix, name });" +
"}", ctClass);
ctClass.addMethod(makePath);
sb = new StringBuilder(1000);
line("public Object resolve({0} $inv, String $prefix) throws Exception { ", _Invocation);
line(" this.$prefix = $prefix; ");
line(" boolean $save = false; "); //$save为false返回null
line(" String $path, $value; ");
line(" {0} $bean = new {0}(); ", mappedClass.getName());
appendFieldsResolver();
line(" return ($save ? $bean : null); ");
line("} ");
logger.debug("\n{}:\n{}", mappedClass, sb);
CtMethod resolve = CtMethod.make(sb.toString(), ctClass);
ctClass.addMethod(resolve);
obj = (BeanResolver) ctClass.toClass().newInstance();
obj.setSeparator(this.separator);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return obj;
}
private void appendFieldsResolver() {
mappedFields.values().stream().forEach(fieldMeta -> {
String fieldName = fieldMeta.getFieldName();
line();
line(" $path = makePath(\"{0}\"); ", fieldName);
Class type = fieldMeta.getJavaType();
if (type.equals(List.class)) {
appendList(fieldMeta, fieldName);
} else if (type.isAnnotationPresent(WebBean.class)) {
ResolverHelper.init(type);
line(" {0} {1} = ({0}) {2}.resolve({0}.class, $inv, $path); ",
type.getName(), fieldName, _ResolverHelper);
appendSetter(fieldMeta, fieldName);
} else {
appendField(fieldMeta, type);
}
});
}
private void appendList(BeanField fieldMeta, String fieldName) {
Class pType = fieldMeta.getParameterizedType();
line(" java.util.List {0} = new java.util.ArrayList(); ", fieldName);
line(" for (int $i = 0; ; $i++) { ");
line(" String $_path = $separator.createParamKey(new Object[]{ $path, new Integer($i) });");
if (pType.isAnnotationPresent(WebBean.class)) {
ResolverHelper.init(pType);
line(" {1} _{0} = ({1}) {2}.resolve({1}.class, $inv, $_path);", fieldName, pType.getName(), _ResolverHelper);
} else {
// TODO: Int Long Boolean String 都支持valueOf, 其他类型的话得扩展valueOf
line(" {1} _{0} = {1}.valueOf($inv.getParameter($_path));", fieldName, pType.getName());
}
line(" if (_{0} == null) break; ", fieldName);
line(" {0}.add(_{0});", fieldName);
line(" } "); //end for
line(" if ({0}.size() > 0) { ", fieldName);
line(" $save = true; ");
appendSetter(fieldMeta, fieldName);
line(" } ");
}
private void appendField(BeanField fieldMeta, Class type) {
line(" $value = $inv.getParameter($path); ");
line(" if ($value != null) { ");
line(" $save = true; ");
appendSetter(fieldMeta, appendValue("$value", type));
line(" } ");
}
private void appendSetter(BeanField fieldMeta, String value) {
line(" $bean.{0}({1});", fieldMeta.getWriteName(), value);
}
// TODO: 暂支持 String int long boolean, 需要其他类型再添加
private String appendValue(String value, Class type) {
if (type.equals(String.class))
return value;
else if (type.equals(int.class) || type.equals(Integer.class))
return MessageFormat.format("Integer.parseInt({0})", value);
else if (type.equals(long.class) || type.equals(Long.class))
return MessageFormat.format("Long.parseLong({0})", value);
else if (type.equals(boolean.class) || type.equals(Boolean.class))
return MessageFormat.format("org.apache.commons.lang3.BooleanUtils.toBoolean({0})", value);
return value;
}
private void line(Object... args) {
String line = "";
if (args.length > 0) {
line = (String) args[0];
args = ArrayUtils.remove(args, 0);
}
if (args.length > 0) {
line = StringUtil.format(line, args);
}
sb.append(line).append("\n");
}