package com.intrbiz.bergamot.compat.config.builder.object;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.apache.log4j.Logger;
import com.intrbiz.bergamot.compat.config.builder.metadata.ParameterName;
import com.intrbiz.bergamot.compat.config.builder.metadata.TypeName;
import com.intrbiz.bergamot.compat.config.builder.parameter.BooleanParameterParser;
import com.intrbiz.bergamot.compat.config.builder.parameter.FloatParameterParser;
import com.intrbiz.bergamot.compat.config.builder.parameter.IntParameterParser;
import com.intrbiz.bergamot.compat.config.builder.parameter.ListParameterParser;
import com.intrbiz.bergamot.compat.config.builder.parameter.LongParameterParser;
import com.intrbiz.bergamot.compat.config.builder.parameter.ParameterParser;
import com.intrbiz.bergamot.compat.config.builder.parameter.StringParameterParser;
import com.intrbiz.bergamot.compat.config.model.ConfigObject;
import com.intrbiz.bergamot.compat.config.parser.model.ObjectDefinition;
import com.intrbiz.bergamot.compat.config.parser.model.ObjectParameter;
public class ObjectBuilder
{
private Logger logger = Logger.getLogger(ObjectBuilder.class);
private final Class<? extends ConfigObject<?>> typeClass;
private final String type;
private Map<String, ParameterParser> parameters = new TreeMap<String, ParameterParser>();
public ObjectBuilder(Class<? extends ConfigObject<?>> typeClass, String type)
{
super();
this.typeClass = typeClass;
this.type = type;
}
public Class<? extends ConfigObject<?>> getTypeClass()
{
return typeClass;
}
public String getType()
{
return type;
}
public Set<String> getParameterNames()
{
return this.parameters.keySet();
}
public void addParameter(ParameterParser parser)
{
this.parameters.put(parser.getName(), parser);
logger.trace("Adding parameter " + parser.getName() + " to object " + this.getType());
}
public ConfigObject<?> build(ObjectDefinition def)
{
try
{
ConfigObject<?> obj = this.typeClass.newInstance();
for (ObjectParameter param : def.getParameters())
{
ParameterParser pp = this.parameters.get(param.getName());
if (pp != null)
{
pp.build(obj, param);
}
else if (! obj.unhandledObjectParameter(param))
{
logger.warn("Unsupported parameter " + param.getName() + " of object " + this.getType() + ", ignoring it");
}
}
return obj;
}
catch (Exception e)
{
throw new RuntimeException("Error building " + this.getType() + " object", e);
}
}
public static ObjectBuilder create(Class<? extends ConfigObject<?>> typeClass)
{
TypeName typeName = typeClass.getAnnotation(TypeName.class);
ObjectBuilder builder = new ObjectBuilder(typeClass, typeName.value());
for (Method method : typeClass.getMethods())
{
if (method.getName().startsWith("set") && method.getParameterTypes().length == 1)
{
ParameterName paramName = method.getAnnotation(ParameterName.class);
if (paramName != null)
{
Class<?> paramType = method.getParameterTypes()[0];
// select a parser based on the parameter type
if (paramType == String.class)
{
builder.addParameter(new StringParameterParser(paramName.value(), paramType, method));
}
else if (paramType == Long.class)
{
builder.addParameter(new LongParameterParser(paramName.value(), paramType, method));
}
else if (paramType == Integer.class)
{
builder.addParameter(new IntParameterParser(paramName.value(), paramType, method));
}
else if (paramType == Float.class)
{
builder.addParameter(new FloatParameterParser(paramName.value(), paramType, method));
}
else if (List.class.isAssignableFrom(paramType))
{
builder.addParameter(new ListParameterParser(paramName.value(), paramType, method));
}
else if (paramType == Boolean.class)
{
builder.addParameter(new BooleanParameterParser(paramName.value(), paramType, method));
}
}
}
}
return builder;
}
}