package net.onedaybeard.dominatrix.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Reflex
{
private final Map<Class<?>, FieldTypeWriter> fieldParsers;
public Reflex()
{
fieldParsers = new HashMap<Class<?>, FieldTypeWriter>();
addParser(new BooleanTypeWriter());
addParser(new FloatTypeWriter());
addParser(new IntTypeWriter());
addParser(new LongTypeWriter());
addParser(new StringTypeWriter());
addParser(new EnumTypeWriter());
}
public void addParser(FieldTypeWriter typeParser)
{
fieldParsers.put(typeParser.getType(), typeParser);
}
public boolean isEditable(Field field)
{
return !isTransient(field)
&& getFieldTypeWriter(field) != null;
}
private FieldTypeWriter getFieldTypeWriter(final Field field)
{
FieldTypeWriter fieldTypeWriter;
if (field.getType().isEnum())
fieldTypeWriter = fieldParsers.get(Enum.class);
else
fieldTypeWriter = fieldParsers.get(field.getType());
return fieldTypeWriter;
}
private static boolean isTransient(Field field)
{
return (field.getModifiers() & Modifier.TRANSIENT) > 0;
}
public FieldReflex on(final Object instance, final Field field)
{
return new FieldReflex()
{
@Override
public boolean set(String value)
{
if (!field.isAccessible())
field.setAccessible(true);
boolean success = true;
FieldTypeWriter fieldTypeWriter = getFieldTypeWriter(field);
if (fieldTypeWriter == null)
throw new RuntimeException("Missing FieldTypeWriter for " + field.getType());
try
{
field.set(instance, fieldTypeWriter.parse(value, field));
}
catch (Exception e)
{
success = false;
}
return success;
}
@Override @SuppressWarnings("unchecked")
public <T> T get()
{
if (!field.isAccessible())
field.setAccessible(true);
try
{
return (T)field.get(instance);
}
catch (IllegalArgumentException e)
{
throw new RuntimeException(e);
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
}
@Override
public String getAsString()
{
Object object = get();
if (object == null)
return "";
else if (object.getClass().isArray())
return formatArray(object);
else
return object.toString();
}
private String formatArray(Object array)
{
if (array instanceof boolean[])
return Arrays.toString((boolean[])array);
else if (array instanceof byte[])
return Arrays.toString((byte[])array);
else if (array instanceof char[])
return Arrays.toString((char[])array);
else if (array instanceof int[])
return Arrays.toString((int[])array);
else if (array instanceof long[])
return Arrays.toString((long[])array);
else if (array instanceof float[])
return Arrays.toString((float[])array);
else if (array instanceof double[])
return Arrays.toString((double[])array);
else
return Arrays.toString((Object[])array);
}
};
}
public FieldReflex on(final Object instance, String field)
{
try
{
return on(instance, instance.getClass().getDeclaredField(field));
}
catch (SecurityException e)
{
throw new RuntimeException(e);
}
catch (NoSuchFieldException e)
{
throw new RuntimeException(e);
}
}
public interface FieldReflex
{
<T> T get();
String getAsString();
boolean set(String value);
}
}