package main.settings.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Properties;
import java.util.Set;
import misc.Mask;
public abstract class AbstractSettingsContainerReflector
{
private SettingsContainer container;
private String path;
protected AbstractSettingsContainerReflector(SettingsContainer container, String path)
{
this.container = container;
this.path = path;
}
protected AbstractSettingsContainerReflector(SettingsContainer container)
{
this(container, null);
}
public void fetchProperties(Properties properties)
{
Set<Object> settings = properties.keySet();
for (Object setting : settings)
{
String settingName = setting.toString();
tryToSet(settingName, properties.getProperty(settingName));
}
}
private void tryToSet(String name, String value)
{
String[] path = name.split("\\.");
try
{
findAndSet(path, value);
}
catch (Exception e)
{
System.err.println("errors in settings.ini: " + name);
}
}
private void findAndSet(String[] path, String value) throws Exception
{
Field field = getField(path[0]);
if (isContainer(field))
{
SettingsContainer container = SettingsContainer.class.cast(field
.get(this.container));
AbstractSettingsContainerReflector containerReflector = new SettingsContainerReflector(
container);
String[] childPath = Arrays.copyOfRange(path, 1, path.length);
containerReflector.findAndSet(childPath, value);
}
else
{
setField(field, value);
}
}
protected abstract Field getField(String name) throws Exception;
private void setField(Field field, String value) throws Exception
{
Class<?> fieldType = field.getType();
if (fieldType.isArray())
{
throw new NoSuchFieldException();
}
else if (fieldType.isPrimitive())
{
setPrimitiveField(field, fieldType, value);
}
else if (fieldType.equals(String.class))
{
field.set(container, value);
}
else
{
throw new NoSuchFieldException();
}
}
private void setPrimitiveField(Field field, Class<?> fieldType, String value)
throws IllegalArgumentException, Exception
{
if (fieldType.equals(Boolean.TYPE))
{
field.setBoolean(container, new Boolean(value));
}
else if (fieldType.equals(Character.TYPE))
{
field.setChar(container, new Character(value.charAt(0)));
}
else if (fieldType.equals(Byte.TYPE))
{
field.setByte(container, new Byte(value));
}
else if (fieldType.equals(Short.TYPE))
{
field.setShort(container, new Short(value));
}
else if (fieldType.equals(Integer.TYPE))
{
field.setInt(container, new Integer(value));
}
else if (fieldType.equals(Long.TYPE))
{
field.setLong(container, new Long(value));
}
else if (fieldType.equals(Float.TYPE))
{
field.setFloat(container, new Float(value));
}
else if (fieldType.equals(Double.TYPE))
{
field.setDouble(container, new Double(value));
}
}
public void translateContainer(Properties properties)
{
Field[] fields = getFields();
for (Field field : fields)
{
try
{
translateField(field, properties);
}
catch (Exception e)
{
continue;
}
}
}
protected abstract Field[] getFields();
protected final SettingsContainer getContainer()
{
return container;
}
private void translateField(Field field, Properties properties) throws Exception
{
if (isContainer(field))
{
SettingsContainer subContainer = SettingsContainer.class.cast(field
.get(container));
String subContainerPath = getFieldPath(field);
AbstractSettingsContainerReflector subContainerReflector = new SettingsContainerReflector(
subContainer, subContainerPath);
subContainerReflector.translateContainer(properties);
}
else
{
translateSimpleField(field, properties);
}
}
private static boolean isContainer(Field field)
{
return SettingsContainer.class.isAssignableFrom(field.getType());
}
private void translateSimpleField(Field field, Properties properties)
throws Exception
{
Mask modifiersMask = new Mask(field.getModifiers());
if (!modifiersMask.contains(Modifier.FINAL))
{
String key = getFieldPath(field);
String value = field.get(container).toString();
properties.setProperty(key, value);
}
}
private String getFieldPath(Field field)
{
if (path.equals(""))
{
return field.getName();
}
else
{
return path + "." + field.getName();
}
}
}