package nl.ipo.cds.validation.format;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import nl.ipo.cds.validation.Expression;
import nl.ipo.cds.validation.ValidationMessage;
import nl.ipo.cds.validation.Validator;
import nl.ipo.cds.validation.ValidatorContext;
public abstract class ValidatorFormatter<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>> {
private final Map<Class<?>, Method> methods = new HashMap<Class<?>, Method> ();
public final Validator<K, C> validator;
public ValidatorFormatter (final Validator<K, C> validator) {
this.validator = validator;
this.reflect ();
}
public String format () {
return formatExpression (validator);
}
public String formatExpression (final Expression<K, C, ?> expression) {
final List<Class<?>> classes = new ArrayList<Class<?>> (1);
classes.add (expression.getClass ());
try {
return invokeFormatter (expression, classes);
} catch (IllegalAccessException e) {
throw new RuntimeException (e);
} catch (IllegalArgumentException e) {
throw new RuntimeException (e);
} catch (InvocationTargetException e) {
throw new RuntimeException (e);
}
}
public String format (final Expression<K, C, ?> expression) {
return "";
}
private String invokeFormatter (final Expression<K, C, ?> exp, final List<Class<?>> classes) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (classes.size () == 0) {
return format (exp);
}
final List<Class<?>> newClasses = new ArrayList<Class<?>> ();
for (final Class<?> cls: classes) {
if (methods.containsKey (cls)) {
return (String)methods.get (cls).invoke (this, exp);
}
final Class<?> superClass = cls.getSuperclass ();
if (superClass != null) {
newClasses.add (superClass);
}
for (final Class<?> iface: cls.getInterfaces ()) {
newClasses.add (iface);
}
}
return invokeFormatter (exp, newClasses);
}
private void reflect () {
for (final Method method: getClass ().getDeclaredMethods ()) {
if (!method.getReturnType ().equals (String.class)) {
continue;
}
final Class<?>[] parameters = method.getParameterTypes ();
if (parameters.length != 1) {
continue;
}
if (!Expression.class.isAssignableFrom (parameters[0])) {
continue;
}
methods.put (parameters[0], method);
}
}
}