// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.mdm.repository.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
/**
* DOC hbhong class global comment. Detailled comment
*/
class BeanClassUtil {
static Logger log = Logger.getLogger(BeanClassUtil.class);
Map<Class, Map<Object, Method[]>> map = new HashMap<Class, Map<Object, Method[]>>();
private Bean2EObjUtil mapUtil;
/**
* DOC hbhong BeanClassUtil constructor comment.
*
* @param mapUtil
*/
public BeanClassUtil(Bean2EObjUtil mapUtil) {
this.mapUtil = mapUtil;
}
public Map<Object, Method[]> findFieldMap(Class cls) {
return map.get(cls);
}
private String calGetMethodName(Field field) {
String name = field.getName();
if (name.startsWith("_")) {
name = name.substring(1);
}
Class type = field.getType();
// in normal the var name's length>1 ,there is a potential bug
return (((type.isPrimitive() && type.getName().equals("boolean")) || type.getName().equals("java.lang.Boolean")) ? "is" : "get") + name.substring(0, 1).toUpperCase() + name.substring(1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
private String calSetMethodName(Field field) {
String name = field.getName();
if (name.startsWith("_")) {
name = name.substring(1);
}
// in normal the var name's length>1 ,there is a potential bug
return "set" + name.substring(0, 1).toUpperCase() + name.substring(1); //$NON-NLS-1$
}
private void fillMap(Class cls, Object member, Method[] methods) {
Map<Object, Method[]> fieldMap = map.get(cls);
if (fieldMap == null) {
fieldMap = new HashMap<Object, Method[]>();
map.put(cls, fieldMap);
}
//
fieldMap.put(member, methods);
}
private Method findMethod(Class cls, String methodName, Class... paramTypes) {
for (Method method : cls.getMethods()) {
String name = method.getName();
if (methodName.equalsIgnoreCase(name)) {
if (paramTypes == null) {
return method;
} else {
Class<?>[] curParamTypes = method.getParameterTypes();
if (curParamTypes.length == paramTypes.length) {
boolean isOK = true;
for (int i = 0; i < curParamTypes.length; i++) {
if (curParamTypes[i] != paramTypes[i]) {
isOK = false;
break;
}
}
if (isOK) {
return method;
}
}
}
}
}
return null;
}
private Method[] getEnumMethods(Class cls) {
Method[] methods = new Method[2];
for (Method method : cls.getDeclaredMethods()) {
String methodName = method.getName();
if (methodName.equals("value")) { //$NON-NLS-1$
methods[0] = method;
} else if (methodName.equals("fromValue")) { //$NON-NLS-1$
methods[1] = method;
}
}
return methods;
}
public void refactorClassStructure(Class cls) {
if (map.containsKey(cls)) {// map.clear()
return;
}
// Enum
if (cls.isEnum()) {
Method[] enumMethods = getEnumMethods(cls);
fillMap(cls, cls, enumMethods);
} else {
// other class
for (Field field : cls.getDeclaredFields()) {
if (field.isEnumConstant()) {
continue;
}
try {
String getMethodName = calGetMethodName(field);
Method getMethod = findMethod(cls, getMethodName);
Method[] methods = new Method[2];
Class fieldType = field.getType();
if (getMethod != null && getMethod.getReturnType() == fieldType) {
// System.out.println(field + "\n\t" + getMethod); //$NON-NLS-1$
methods[0] = getMethod;
} else {
log.debug("can't find getMethod for " + field); //$NON-NLS-1$
}
if (!isCollectionField(field)) {
//
String setMethodName = calSetMethodName(field);
Method setMethod = findMethod(cls, setMethodName, fieldType);
if (setMethod != null) {
// System.out.println(field + "\n\t" + setMethod); //$NON-NLS-1$
methods[1] = setMethod;
} else {
log.debug("can't find setMethod for " + field); //$NON-NLS-1$
}
} else {
// List field
methods[1] = methods[0];
}
if (methods[0] != null && methods[1] != null) {
fillMap(cls, field, methods);
handleChildClass(field);
}
//
} catch (SecurityException e) {
log.error(e.getMessage(), e);
}
// catch (NoSuchMethodException e) {
// log.debug(e.getMessage() + "=>Skip it"); //$NON-NLS-1$
// }
}
}
}
private Class getComponentType(Field field) {
if (isCollectionField(field)) {
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
Type[] types = ((ParameterizedType) genericType).getActualTypeArguments();
if (types != null && types.length > 0) {
return (Class) types[0];
}
}
}
if (isArrayField(field)) {
Class<?> cls = field.getType();
if (cls.isArray()) {
return cls.getComponentType();
}
}
return field.getType();
}
private Class getComponentType(Class cls) {
if (cls.isArray()) {
return cls.getComponentType();
}
return cls;
}
private void handleChildClass(Field field) {
Class childCls = getComponentType(field);
if (!isJavaClass(childCls)) {
if (!map.containsKey(childCls)) {
if (mapUtil != null) {
mapUtil.registerClassMap(childCls);
}
}
}
}
public boolean isArrayField(Field field) {
return field.getType().isArray();
}
public boolean isCollectionField(Field field) {
String typeName = field.getType().getName();
return typeName.equals("java.util.List");
}
public boolean isJavaField(Field field) {
return isJavaClass(field);
}
public boolean isJavaClass(Field field) {
if (field.getType().isPrimitive()) {
return true;
}
return getComponentType(field).getName().startsWith("java"); //$NON-NLS-1$
}
public boolean isJavaClass(Class cls) {
if (cls.isPrimitive()) {
return true;
}
return getComponentType(cls).getName().startsWith("java"); //$NON-NLS-1$
}
public void dumpMap() {
for (Class cls : map.keySet()) {
System.out.println(cls.getName());
Map<Object, Method[]> fieldMap = map.get(cls);
for (Object field : fieldMap.keySet()) {
System.out.println("\t|--- " + field); //$NON-NLS-1$
Method[] methods = fieldMap.get(field);
System.out.println("\t\t\t" + methods[0].getName()); //$NON-NLS-1$
System.out.println("\t\t\t" + methods[1].getName()); //$NON-NLS-1$
}
}
}
}