package com.android.pc.ioc.core.kernel; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; import com.android.pc.ioc.core.kernel.KernelLang.BreakException; import com.android.pc.ioc.core.kernel.KernelLang.CallbackBreak; @SuppressWarnings({ "rawtypes", "unchecked" }) public abstract class KernelClass { /** * @param classname * @return */ public static String parentName(Class cls) { return KernelString.rightSubString(cls.getName(), cls.getSimpleName().length() + 1); } /** * @param cls * @param types * @return */ public static boolean isAssignableFrom(Class cls, Class[] types) { for (Class type : types) { if (cls.isAssignableFrom(type)) { return true; } } return false; } /** * @param classes * @param type * @return */ public static boolean isAssignableFrom(Class[] classes, Class type) { for (Class cls : classes) { if (cls.isAssignableFrom(type)) { return true; } } return false; } /** * @param classes * @param types * @return */ public static boolean isAssignableFrom(Class[] classes, Class[] types) { int length = classes.length; if (length == types.length) { for (int i = 0; i < length; i++) { if (!classes[i].isAssignableFrom(types[i])) { return false; } } return true; } return false; } /** * @param cls * @param T * @return */ public static <T> Class<? extends T> classAssignable(Class cls, Class T) { return classAssignable(cls, null, T); } /** * @param cls * @param defaultValue * @param T * @return */ public static <T> Class<? extends T> classAssignable(Class cls, Class<? extends T> defaultValue, Class T) { if (cls == null || !T.isAssignableFrom(cls)) { return defaultValue; } return cls; } /** * @param cls * @param type * @return */ public static boolean isMatchableFrom(Class cls, Class type) { if (cls.isAssignableFrom(type)) { return true; } if (cls == Object.class) { return true; } else if (cls == byte.class) { return type == Byte.class; } else if (cls == Byte.class) { return type == byte.class; } else if (cls == short.class) { return type == Short.class; } else if (cls == Short.class) { return type == short.class; } else if (cls == int.class) { return type == Integer.class; } else if (cls == Integer.class) { return type == int.class; } else if (cls == float.class) { return type == Float.class; } else if (cls == Float.class) { return type == float.class; } else if (cls == double.class) { return type == Double.class; } else if (cls == Double.class) { return type == double.class; } else if (cls == boolean.class) { return type == Boolean.class; } else if (cls == Boolean.class) { return type == boolean.class; } else if (cls == char.class) { return type == Character.class; } else if (cls == Character.class) { return type == char.class; } else if (cls == long.class) { return type == Long.class; } else if (cls == Long.class) { return type == long.class; } else if (cls.isArray() && type.isArray()) { cls.getComponentType().isAssignableFrom(type.getComponentType()); } return false; } /** * @param cls * @param types * @return */ public static boolean isMatchableFrom(Class cls, Class[] types) { for (Class type : types) { if (isMatchableFrom(cls, type)) { return true; } } return false; } /** * @param classes * @param types * @return */ public static boolean isMatchableFrom(Class[] classes, Class[] types) { int length = classes.length; if (length == types.length) { for (int i = 0; i < length; i++) { if (!isMatchableFrom(classes[i], types[i])) { return false; } } return true; } return false; } /** * @param args * @return */ public static Class[] parameterTypes(Object... args) { int length = args.length; Class[] parameterTypes = new Class[length]; for (int i = 0; i < length; i++) { parameterTypes[i] = args[i].getClass(); } return parameterTypes; } /** * @param type * @return */ public static Class rawClass(Type type) { if (type instanceof ParameterizedType) { return (Class) ((ParameterizedType) type).getRawType(); } else if (type instanceof GenericArrayType) { try { return Array.newInstance(rawClass(((GenericArrayType) type).getGenericComponentType()), 0).getClass(); } catch (Exception e) { } } else if (type instanceof Class) { return (Class) type; } return Object.class; } /** * @param type * @return */ public static Type[] typeArguments(Type type) { if (type instanceof ParameterizedType) { return ((ParameterizedType) type).getActualTypeArguments(); } return null; } /** * @param types * @return */ public static Class[] rawClasses(Type[] types) { int length = types.length; Class[] classes = new Class[length]; for (int i = 0; i < length; i++) { classes[i] = rawClass(types[i]); } return classes; } /** * @param cls * @return */ public static Class componentClass(Class<?> cls) { if (cls.isArray()) { return cls.getComponentType(); } Class superClass = componentClass(cls.getGenericSuperclass()); return superClass == cls.getSuperclass() ? cls : superClass; } /** * @param cls * @return */ public static Class[] componentClasses(Class<?> cls) { if (cls.isArray()) { return new Class[] { cls.getComponentType() }; } Class[] superClasses = componentClasses(cls.getGenericSuperclass()); if (superClasses.length == 1 && superClasses[0] == cls.getSuperclass()) { superClasses[0] = cls; } return superClasses; } /** * @param type * @return */ public static Class componentClass(Type type) { Type componentType = type; while (type != null) { Type[] types = typeArguments(type); if (types == null || types.length <= 0) { Class cls = rawClass(type); if (cls.isArray()) { return cls.getComponentType(); } else { type = cls.getGenericSuperclass(); continue; } } return rawClass(types[0]); } return rawClass(componentType); } /** * @param type * @return */ public static Class[] componentClasses(Type type) { Type componentType = type; while (type != null) { Type[] types = typeArguments(type); if (types == null || types.length <= 0) { Class cls = rawClass(type); if (cls.isArray()) { return new Class[] { cls.getComponentType() }; } else { type = cls.getGenericSuperclass(); continue; } } return rawClasses(types); } return new Class[] { rawClass(componentType) }; } /** * @param cls * @param type * @return */ public static int similar(Class cls, Class type) { int similar = -1; while (cls != null) { if (similar < 0) { if (cls == type) { similar = 0; } else { for (Class iCls : cls.getInterfaces()) { if (iCls == type) { similar = 0; break; } } } } else { similar++; } cls = cls.getSuperclass(); } return similar; } /** * @param classes * @param types * @return */ public static int similar(Class[] classes, Class[] types) { int similar = -1; int length = classes.length; if (length == types.length) { for (int i = 0; i < length; i++) { similar += similar(classes[i], types[i]); } } return similar; } /** * @param className * @return */ public static Class forName(String className) { return forName(className, null); } /** * @param className * @param defaultValue * @return */ public static Class forName(String className, Class defaultValue) { try { return Class.forName(className); } catch (ClassNotFoundException e) { } return defaultValue; } /** * @param cls * @param annotationType * @return */ public static <T extends Annotation> T getAnnotation(Class<?> cls, Class<T> annotationType) { T annotation = cls.getAnnotation(annotationType); if (annotation == null && !Annotation.class.isAssignableFrom(cls)) { Annotation[] annotations = cls.getAnnotations(); if (annotations != null) { for (Annotation obj : annotations) { annotation = getAnnotation(obj.annotationType(), annotationType); if (annotation != null) { break; } } } } return annotation; } /** * @param cls * @return */ public static <T> T newInstance(Class<T> cls) { return newInstance(null, cls); } /** * @param defaultValue * @param cls * @return */ public static <T> T newInstance(T defaultValue, Class<T> cls) { try { return cls.newInstance(); } catch (InstantiationException e) { } catch (IllegalAccessException e) { } return defaultValue; } /** * @param cls * @param initargs * @return */ public static <T> T newInstance(Class<T> cls, Object... initargs) { return newInstance(cls, null, initargs); } /** * @param cls * @param defaultValue * @param initargs * @return */ public static <T> T newInstance(Class<T> cls, T defaultValue, Object... initargs) { if (initargs.length == 0) { return newInstance(defaultValue, cls); } return newInstance(cls, defaultValue, KernelClass.parameterTypes(initargs), true, initargs); } /** * @param cls * @param defaultValue * @param parameterTypes * @param initargs * @return */ public static <T> T newInstance(Class<T> cls, T defaultValue, Class[] parameterTypes, Object... initargs) { return newInstance(cls, defaultValue, parameterTypes, false, initargs); } /** * @param cls * @param defaultValue * @param parameterTypes * @param assignable * @param initargs * @return */ public static <T> T newInstance(Class<T> cls, T defaultValue, Class[] parameterTypes, boolean assignable, Object... initargs) { return declaredNew(cls, defaultValue, false, assignable, parameterTypes, initargs); } /** * @param cls * @param initargs * @return */ public static <T> T declaredNew(Class<T> cls, Object... initargs) { return declaredNew(cls, null, KernelClass.parameterTypes(initargs), true, initargs); } /** * @param cls * @param defaultValue * @param initargs * @return */ public static <T> T declaredNew(Class<T> cls, T defaultValue, Object... initargs) { return declaredNew(cls, defaultValue, KernelClass.parameterTypes(initargs), true, initargs); } /** * @param cls * @param parameterTypes * @param initargs * @return */ public static <T> T declaredNew(Class<T> cls, Class[] parameterTypes, Object... initargs) { return declaredNew(cls, null, parameterTypes, initargs); } /** * @param cls * @param defaultValue * @param parameterTypes * @param initargs * @return */ public static <T> T declaredNew(Class<T> cls, T defaultValue, Class[] parameterTypes, Object... initargs) { return declaredNew(cls, defaultValue, parameterTypes, false, initargs); } /** * @param cls * @param defaultValue * @param parameterTypes * @param assignable * @param initargs * @return */ public static <T> T declaredNew(Class<T> cls, T defaultValue, Class[] parameterTypes, boolean assignable, Object... initargs) { return declaredNew(cls, defaultValue, true, assignable, parameterTypes, initargs); } /** * @param cls * @param defaultValue * @param declared * @param assignable * @param parameterTypes * @param initargs * @return */ public static <T> T declaredNew(Class<T> cls, T defaultValue, boolean declared, boolean assignable, Class[] parameterTypes, Object... initargs) { Constructor<T> constructor = KernelReflect.assignableConstructor(cls, declared, assignable, parameterTypes); return KernelReflect.newInstance(constructor, initargs); } /** Class_Map_Instance */ static final Map<Class, Object> Class_Map_Instance = new HashMap<Class, Object>(); /** * @param cls * @return */ public static <T> T getInstance(Class<T> cls) { T instance = (T) Class_Map_Instance.get(cls); if (instance == null) { synchronized (cls) { instance = (T) Class_Map_Instance.get(cls); if (instance == null) { instance = newInstance(cls); Class_Map_Instance.put(cls, instance); } } } return instance; } /** * @param cls * @param initargs * @return */ public static <T> T getInstance(Class<T> cls, Object... initargs) { T instance = (T) Class_Map_Instance.get(cls); if (instance == null) { synchronized (cls) { instance = (T) Class_Map_Instance.get(cls); if (instance == null) { instance = newInstance(cls, initargs); Class_Map_Instance.put(cls, instance); } } } return instance; } /** * @param cls * @param name * @return */ public static Object declaredGet(Class cls, String name) { Field field = KernelReflect.declaredField(cls.getClass(), name); return KernelReflect.get(cls, field); } /** * @param cls * @param name * @param value * @return */ public static boolean declaredSet(Class cls, String name, Object value) { Field field = KernelReflect.declaredField(cls.getClass(), name); return KernelReflect.set(cls, field, value); } /** * @param cls * @param name * @param args * @return */ public static Object declaredSend(Class cls, String name, Object... args) { Method method = KernelReflect.assignableMethod(cls, name, 0, true, parameterTypes(args)); if (method != null) { return KernelReflect.invoke(cls, method, args); } return null; } /** * @param field * @return */ public static Method setter(Field field) { return setter(field.getDeclaringClass(), field); } /** * @param cls * @param field * @return */ public static Method setter(Class cls, Field field) { return setter(cls, field.getName(), field.getType()); } /** * @param cls * @param field * @param fieldType * @return */ public static Method setter(Class cls, String field, Class fieldType) { return KernelReflect.method(cls, "set" + KernelString.uncapitalize(field), fieldType); } /** * @param field * @return */ public static Method getter(Field field) { return getter(field.getDeclaringClass(), field); } /** * @param cls * @param field * @return */ public static Method getter(Class cls, Field field) { return getter(cls, field.getName(), field.getType()); } /** * @param cls * @param field * @return */ public static Method getter(Class cls, String field) { field = KernelString.uncapitalize(field); Method method = KernelReflect.method(cls, "get" + field); if (method == null) { method = KernelReflect.method(cls, "is" + field); } return method; } /** * @param cls * @param field * @param fieldType * @return */ public static Method getter(Class cls, String field, Class fieldType) { field = KernelString.uncapitalize(field); Method method = KernelReflect.method(cls, "get" + field); if (method == null || !fieldType.isAssignableFrom(method.getReturnType())) { if (fieldType == boolean.class || fieldType == Boolean.class) { method = KernelReflect.method(cls, "is" + field); } if (method != null && !fieldType.isAssignableFrom(method.getReturnType())) { method = null; } } return method; } /** * @param cls * @param obj * @return */ public static <T> T instanceOf(Class<T> cls, Object obj) { return instanceOf(cls, null, obj); } /** * @param cls * @param defaultValue * @param obj * @return */ public static <T> T instanceOf(Class<T> cls, T defaultValue, Object obj) { T value = newInstance(cls, obj); if (value == null) { value = valueOf(cls, obj); } if (value == null) { return defaultValue; } else { return value; } } /** * @param cls * @param obj * @return */ public static <T> T valueOf(Class<T> cls, Object obj) { return valueOf(cls, null, obj); } /** * @param cls * @param defaultValue * @param obj * @return */ public static <T> T valueOf(Class<T> cls, T defaultValue, Object obj) { Method method = KernelReflect.assignableMethod(cls, "valueOf", obj.getClass()); if (method != null && cls.isAssignableFrom(method.getReturnType())) { return (T) KernelReflect.invoke(cls, method, obj); } return defaultValue; } /** * @param cls * @param toClass * @return */ public static <T> Class<? extends T> cast(Class cls, Class<T> toClass) { return cast(cls, null, toClass); } /** * @param cls * @param defaultValue * @param toClass * @return */ public static <T> Class<? extends T> cast(Class cls, Class<? extends T> defaultValue, Class<T> toClass) { if (cls != null && toClass.isAssignableFrom(cls)) { return cls; } return defaultValue; } /** * @param cls * @param callback */ public static void doWithSuperClass(Class cls, CallbackBreak<Class<?>> callback) { try { while (!(cls == null || cls == Object.class)) { callback.doWith(cls); cls = cls.getSuperclass(); } } catch (BreakException e) { // TODO: handle exception } } /** * @param cls * @param callback */ public static void doWithAncestClass(Class cls, CallbackBreak<Class<?>> callback) { try { while (!(cls == null || cls == Object.class)) { callback.doWith(cls); for (Class c : cls.getInterfaces()) { callback.doWith(c); } cls = cls.getSuperclass(); } } catch (BreakException e) { // TODO: handle exception } } }