package com.baidu.unbiz.common.genericdao.mapper;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.baidu.unbiz.common.genericdao.annotation.Column;
import com.baidu.unbiz.common.genericdao.annotation.Table;
import com.baidu.unbiz.common.genericdao.annotation.Table.ColumnStyle;
import com.baidu.unbiz.common.genericdao.util.ClassUtils;
import com.github.knightliao.apollo.db.bo.BaseObject;
/**
* 一个映射项的对象
*/
public class MappingItem {
public MappingItem(Field field, Method setterMethod, Method getterMethod, ColumnStyle columnStyle) {
this(field, setterMethod, getterMethod, columnStyle, false);
}
public MappingItem(Field field, Method setterMethod, Method getterMethod, ColumnStyle columnStyle,
boolean columnsModified) {
this.field = field;
this.getter = getterMethod;
this.setter = setterMethod;
// 获取字段的注解,如果没有,则从getter或者setter上获取注解
Column column = getColumnAnnotation(field, setter, getter);
// 如果数据库映射字段不为空,则按照映射关系设置字段
if (column == null) {
// generate column name by ColumnStyle
// 1:to lower case(default);2:camel to underscores;3:and may be
// others
this.dbColumn = columnStyle.convert(field.getName());
modifiable = columnsModified;
} else if (column.value().equals("ignore") || column.ignore()) {
// ignore
// 当annotation为ignore时,dbColumn的value为null,这时表示这个MappingItem是一个无效的item
} else {
this.dbColumn = column.value();
modifiable = column.maybeModified();
}
}
private String dbColumn;
private boolean modifiable;
private Field field;
private Method getter;
private Method setter;
public Method getGetter() {
return getter;
}
public Method getSetter() {
return setter;
}
public String getDbColumn() {
return dbColumn;
}
public Field getField() {
return field;
}
public boolean isModifiable() {
return modifiable;
}
/**
* 获取某个字段的annotation,从继承链最下面获取
*
* @param f
* @param set
* @param get
*
* @return
*/
static Column getColumnAnnotation(Field f, Method set, Method get) {
// 三个地方都有可能出现column
Column column = f.getAnnotation(Column.class);
// FIXME 如果不遵循java bean规范,get set 可能为 null,抛出NullPointerException
Column gColumn = get.getAnnotation(Column.class);
Column sColumn = set.getAnnotation(Column.class);
// 预先获取出get与set所在的类
Class<?> sClass = set.getDeclaringClass();
Class<?> gClass = get.getDeclaringClass();
// 如果get上定义了annotation,且get定义的地方是子类
if (gColumn != null && !gClass.isAssignableFrom(sClass)) {
return gColumn;
}
// 如果是set上定义的annotation,且set方法不在父类中定义
if (sColumn != null && !sClass.isAssignableFrom(gClass)) {
return sColumn;
}
return column;
}
public static List<MappingItem> getMappingItems(Class<?> clazz) {
if (!ClassUtils.isBaiduClass(clazz)) {
return new ArrayList<MappingItem>(0);
}
// 如果不是BaseObject的子類,則一定是keyClass
boolean isKeyClass = !BaseObject.class.isAssignableFrom(clazz);
List<MappingItem> mappingItems = new ArrayList<MappingItem>(32);
Set<Field> fields = ClassUtils.getAllFiled(clazz);
Set<Method> methods = ClassUtils.getAllMethod(clazz);
Map<String, Method> methodMap = ClassUtils.filter2Map(methods);
Table table = isKeyClass ? null : clazz.getAnnotation(Table.class);
String keyColumn = isKeyClass ? null : table.keyColumn();
// 循环处理所有字段,过滤出该类加载为对象时需要调用的setter方法map
for (Field f : fields) {
// 静态字段则自动pass
if (Modifier.isStatic(f.getModifiers())) {
continue;
}
// 不做关联加载的工作
Class<?> fType = f.getType();
boolean isBaiduClass = ClassUtils.isBaiduClass(fType);
if (isBaiduClass || Collection.class.isAssignableFrom(fType) || fType.isArray()) {
continue;
}
// 字段名字
String name = f.getName().toLowerCase();
boolean isKey = name.equals("id");
if (isKey && isBaiduClass) {
continue;
}
// 其他字段获取field,getter,setter
Method set = methodMap.get("set" + name);
Method get = methodMap.get("get" + name);
if (get == null) {
get = methodMap.get("is" + name);
}
// FIXME
MappingItem item =
new MappingItem(f, set, get, (table != null) ? table.columnStyle() : ColumnStyle.LOWER_CASE,
(table != null) ? table.columnsModified() : false);
if (item.isIgnore()) {
continue;
}
item.dbColumn = isKey ? keyColumn : item.dbColumn;
mappingItems.add(item);
}
return mappingItems;
}
/**
* 判断该item是否是有效item 当property上注释为ignore时,这个接口会返回true,这时会将其在mapping中省略掉。
*
* @return
*/
private boolean isIgnore() {
return dbColumn == null;
}
public static void main(String[] args) {
System.out.println(Object.class.isAssignableFrom(Integer.class));
}
}