package openmods.reflection; import java.lang.reflect.Field; import java.lang.reflect.Modifier; public class FieldAccess<T> { public static class FieldAccessException extends RuntimeException { private static final long serialVersionUID = 3261757597754500600L; private static String createMessage(Field f, String action) { return "Failed to " + action + " field " + f; } public FieldAccessException(Field f, String action, Throwable cause) { super(createMessage(f, action), cause); } public FieldAccessException(Field f, String action) { super(createMessage(f, action)); } } public final Field field; public FieldAccess(Field field) { this(field, true); } private FieldAccess(Field field, boolean log) { if (log) ReflectionLog.logLoad(field); this.field = field; field.setAccessible(true); } @SuppressWarnings("unchecked") public T get(Object target) { try { return (T)field.get(target); } catch (Throwable t) { throw new FieldAccessException(field, "read", t); } } public void set(Object target, T value) { try { field.set(target, value); } catch (Throwable t) { throw new FieldAccessException(field, "set", t); } } public boolean isPublic() { return Modifier.isPublic(field.getModifiers()); } public boolean isPrivate() { return Modifier.isPrivate(field.getModifiers()); } public boolean isProtected() { return Modifier.isProtected(field.getModifiers()); } public boolean isFinal() { return Modifier.isFinal(field.getModifiers()); } public boolean isStatic() { return Modifier.isStatic(field.getModifiers()); } @SuppressWarnings("unchecked") public Class<T> getType() { return (Class<T>)field.getType(); } @SuppressWarnings("unchecked") public <C> FieldAccess<C> cast(Class<? extends C> cls) { final Class<?> fieldType = field.getType(); if (!cls.isAssignableFrom(fieldType)) throw new ClassCastException(field + " cannot be used as field of type " + cls); return (FieldAccess<C>)this; } public static <T> FieldAccess<T> create(Class<?> cls, String... names) { Field f = ReflectionHelper.getField(cls, names); return new FieldAccess<T>(f, false); // log done in ReflectionHelper } public static <T> FieldAccess<T> create(Field f) { return new FieldAccess<T>(f, true); } }