/*
* This file is part of JGAP.
*
* JGAP offers a dual license model containing the LGPL as well as the MPL.
*
* For licensing information please see the file license.txt included with JGAP
* or have a look at the top of class org.jgap.Chromosome which representatively
* includes the JGAP license policy applicable for any file delivered with JGAP.
*/
package org.jgap.data.config;
import java.lang.reflect.*;
import java.util.*;
import org.jgap.*;
/**
* The ConfigurationHandler for the Configuration class itself. This is the
* entry point for a Configuration.
* In other words this is for dynamically building up a Configuration.
*
* @author Siddhartha Azad
* @author Klaus Meffert
* @since 2.3
* */
public class RootConfigurationHandler
implements ConfigurationHandler {
/** String containing the CVS revision. Read out via reflection!*/
private final static String CVS_REVISION = "$Revision: 1.12 $";
// Namespace
private final static String CONFIG_NAMESPACE = "org.jgap.Configuration";
// constants to indicate various properties
// ----------------------------------------
private final static String GENETIC_OPS = "GeneticOperators";
private final static String NATURAL_SELS = "NaturalSelectors";
private Configurable m_configurable;
/**
* @return Name of this Configuration Object (name of what you are
* configuring) to be used in the properties file.
*
* @since 2.3
* */
public String getName() {
return "Configuration";
}
/**
* Return the information to generate the GUI for configuring this class.
* @return a list of ConfigProperty objects
* @since 2.3
* */
public List getConfigProperties() {
return null;
}
/**
* Get the namespace to be used in the config file for the Configurable
* this ConfigurationHandler belongs to.
* @return the namespace of the Configurable
*
* @author Siddhartha Azad
* @since 2.3
* */
public String getNS() {
return CONFIG_NAMESPACE;
}
/**
* Method that will populate an Configurable with the properties in the
* config file.
*
* @throws ConfigException
* @throws InvalidConfigurationException
*
* @author Siddhartha Azad
* @since 2.3
* */
public void readConfig()
throws ConfigException, InvalidConfigurationException {
// TODO adapt to new concept of configuration via reflection and marker
// interface
// set the namespace to get the properties from
ConfigFileReader.instance().setNS(CONFIG_NAMESPACE);
String value = ConfigFileReader.instance().getValue("m_populationSize");
try {
if (value != null) {
setConfigProperty(m_configurable, "m_populationSize", value);
}
} catch (IllegalAccessException ex) {
ex.printStackTrace();
throw new InvalidConfigurationException(ex.getMessage());
}
// go through all genetic operators and configure them
configureClass(GENETIC_OPS);
// go through all natural selectors and configure them
configureClass(NATURAL_SELS);
}
/**
* Set the Configurable to which this ConfigurationHandler belongs.
* @param a_configurable the Configurable to which this ConfigurationHandler
* belongs
*
* @author Siddhartha Azad
* @since 2.3
* */
public void setConfigurable(Configurable a_configurable) {
m_configurable = a_configurable;
}
/**
* Sets the property of a configurable to a given value. Uses reflection to
* do so. Queries the method getConfigVarName for the name of the field
* hosting the configurable properties.
*
* @param a_configurable the configurable to use
* @param a_propertyName the property to set
* @param a_value the value to assign to the property
* @throws IllegalAccessException
*
* @author Klaus Meffert
* @since 2.6
*/
public void setConfigProperty(Object a_configurable, String a_propertyName,
String a_value)
throws IllegalAccessException {
// Use following in case variable name "m_config" should be determined
// dynamically.
// Method m = null;
// try {
// m = a_configurable.getClass().getDeclaredMethod("getConfigVarName",
// new Class[0]);
// } catch (NoSuchMethodException nex) {
// // nothing to set here
// return;
// }
String configVarName = "m_config"; //(String)m.invoke(a_configurable, new Object[0]);
Field configVar = getPrivateField(a_configurable, configVarName);
configVar.setAccessible(true);
Object configObj = configVar.get(a_configurable);
Field propertyVar = getPrivateField(configObj, a_propertyName);
propertyVar.setAccessible(true);
Class type = propertyVar.getType();
if (type.equals(boolean.class)) {
propertyVar.setBoolean(configObj, Boolean.valueOf(a_value).booleanValue());
}
else if (type.equals(byte.class)) {
propertyVar.setByte(configObj, Byte.valueOf(a_value).byteValue());
}
else if (type.equals(char.class)) {
propertyVar.setChar(configObj, a_value.charAt(0));
}
else if (type.equals(double.class)) {
propertyVar.setDouble(configObj, Double.valueOf(a_value).doubleValue());
}
else if (type.equals(float.class)) {
propertyVar.setFloat(configObj, Float.valueOf(a_value).floatValue());
}
else if (type.equals(int.class)) {
propertyVar.setInt(configObj, Integer.valueOf(a_value).intValue());
}
else if (type.equals(long.class)) {
propertyVar.setLong(configObj, Long.valueOf(a_value).longValue());
}
else if (type.equals(short.class)) {
propertyVar.setShort(configObj, Short.valueOf(a_value).shortValue());
}
else if (type.equals(String.class)) {
propertyVar.set(configObj, a_value);
}
else {
throw new RuntimeException("Unknown field type: " + type.getName());
}
}
/**
* Helper method: Read a private field.
* @param a_instance the instance the field is contained with
* @param a_fieldName the name of the field to read
* @return the Field object or null, if none found
*
* @author Klaus Meffert
* @since 2.6
*/
public static Field getPrivateField(Object a_instance, String a_fieldName) {
final Field fields[] = a_instance.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; ++i) {
if (a_fieldName.equals(fields[i].getName())) {
fields[i].setAccessible(true);
return fields[i];
}
}
return null;
}
/**
* Retrieve all instances of a certain property from the config file reader
* and configure each of these.
* @param className the name of the property to configure
* @throws ConfigException
*
* @author Siddhartha Azad
* @since 2.4
* */
public static void configureClass(String className)
throws ConfigException {
List values = ConfigFileReader.instance().getValues(className);
if (values != null && values.size() > 0) {
String cName = "";
// iterate through all instances of this property and create Configurables
// for them, then configure these
for (Iterator iter = values.iterator(); iter.hasNext(); ) {
try {
cName = (String) iter.next();
Class genClass = Class.forName(cName);
Configurable conObj = (Configurable) genClass.newInstance();
//TODO ConfigurationHandler cHandler = conObj.getConfigurationHandler();
//TODO cHandler.readConfig();
} catch (Exception ex) {
throw new ConfigException("Error while configuring " + className +
"." + cName);
}
}
}
}
}