package com.ebay.cloud.cms.typsafe.entity.internal;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.apache.commons.lang3.StringUtils;
import com.ebay.cloud.cms.typsafe.entity.GenericCMSEntity;
import com.ebay.cloud.cms.typsafe.entity.ICMSEntity;
public class ClassUtil {
// private static final Logger logger = LoggerFactory.getLogger(ClassUtil.class);
@SuppressWarnings("unchecked")
static Class<? extends ICMSEntity> getFieldClass(Class<? extends ICMSEntity> parentClass,
String fieldName) {
Class<?> clz = getGetterReturnType(parentClass, fieldName);
if (clz == null || !ICMSEntity.class.isAssignableFrom(clz)) {
// cause too much info for non-type-safe usage
// logger.info("Get reference field class is not a sub class of ICMSEntity, use GenericCMSEntity instead");
clz = GenericCMSEntity.class;
}
return (Class<? extends ICMSEntity>) clz;
}
private static Map<String, Map<String, Method>> classMethodMaps = Collections
.synchronizedMap(new WeakHashMap<String, Map<String, Method>>());
static Class<?> getGetterReturnType(Class<?> parentEntityClass, String fieldName) {
Class<?> clz;
String getterName = getBeanGetterMethod(fieldName);
String isName = getBeanIsMethod(fieldName);
try {
Map<String, Method> methods = loadMethods(parentEntityClass);
Method getter = methods.get(getterName);
if (getter == null) {
getter = methods.get(isName);
}
Class<?> type = getter.getReturnType();
if (type == List.class) {
ParameterizedType genericType = (ParameterizedType) getter.getGenericReturnType();
clz = (Class<?>) genericType.getActualTypeArguments()[0];
} else {
clz = type;
}
} catch (Exception e) {
// String str = MessageFormat.format("Can not find field getter {0} or {1} in metaclass {2}", getterName, isName, parentEntityClass.getSimpleName());
// logger.debug(str);
clz = null;
}
return clz;
}
private static Map<String, Method> loadMethods(Class<?> parentEntityClass) {
Map<String, Method> methodMaps = classMethodMaps.get(parentEntityClass.getCanonicalName());
if (methodMaps == null) {
Method[] methods = parentEntityClass.getMethods();
Map<String, Method> map = new HashMap<String, Method>();
for (Method m : methods) {
map.put(m.getName(), m);
}
classMethodMaps.put(parentEntityClass.getCanonicalName(), map);
methodMaps = map;
}
return methodMaps;
}
static String getBeanGetterMethod(String fieldName) {
if ("_oid".equals(fieldName)) {
return "get_id";
}
return "get" + StringUtils.capitalize(fieldName);
}
static String getBeanIsMethod(String fieldName) {
return "is" + StringUtils.capitalize(fieldName);
}
}