package droidkit.util; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; /** * @author Daniel Serdyukov */ public final class DynamicField { private DynamicField() { } @Nullable @SuppressWarnings("unchecked") public static <T> T get(@NonNull Object target, @NonNull String fieldName) throws DynamicException { return get(target, find(target.getClass(), fieldName)); } @Nullable @SuppressWarnings("unchecked") public static <T> T get(@Nullable Object target, @NonNull Field field) throws DynamicException { final boolean isAccessible = field.isAccessible(); try { field.setAccessible(true); return (T) field.get(target); } catch (IllegalAccessException e) { throw new DynamicException(e); } finally { field.setAccessible(isAccessible); } } @Nullable @SuppressWarnings("unchecked") public static <T> T getStatic(@NonNull Class<?> clazz, @NonNull String fieldName) throws DynamicException { return get(null, find(clazz, fieldName)); } @SuppressWarnings("unchecked") public static void set(@NonNull Object target, @NonNull String fieldName, @Nullable Object value) throws DynamicException { set(target, find(target.getClass(), fieldName), value); } @SuppressWarnings("unchecked") public static void set(@Nullable Object target, @NonNull Field field, @Nullable Object value) throws DynamicException { final boolean isAccessible = field.isAccessible(); try { field.setAccessible(true); field.set(target, value); } catch (IllegalAccessException e) { throw new DynamicException(e); } finally { field.setAccessible(isAccessible); } } @SuppressWarnings("unchecked") public static void setStatic(@NonNull Class<?> clazz, @NonNull String fieldName, @Nullable Object value) throws DynamicException { set(null, find(clazz, fieldName), value); } @NonNull public static Field find(@NonNull Class<?> clazz, @NonNull String name) throws DynamicException { do { try { return clazz.getDeclaredField(name); } catch (NoSuchFieldException ignored) { } } while ((clazz = clazz.getSuperclass()) != null); throw new DynamicException(new NoSuchFieldException(name)); } @NonNull public static Field find(@NonNull String className, @NonNull String name) throws DynamicException { return find(Dynamic.forName(className), name); } @NonNull public static List<Field> annotatedWith(@NonNull Class<?> type, @NonNull Class<? extends Annotation> annotation) { final List<Field> annotatedMethods = new ArrayList<>(); do { final Field[] methods = type.getDeclaredFields(); for (final Field field : methods) { if (field.isAnnotationPresent(annotation)) { annotatedMethods.add(field); } } } while ((type = type.getSuperclass()) != null); return annotatedMethods; } }