package br.com.caelum.stella.validation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import br.com.caelum.stella.MessageProducer;
import br.com.caelum.stella.ValidationMessage;
public class LogicOrComposedValidator<T> implements Validator<T> {
public Validator<T>[] validators;
public MessageProducer messageProducer;
public InvalidValue invalidFormat = new InvalidValue() {
public String name() {
return "INVALID_FORMAT";
}
};
@SuppressWarnings("unchecked")
public LogicOrComposedValidator(MessageProducer messageProducer, boolean isFormatted,
Class<? extends Validator<T>>... validatorClasses) {
if (validatorClasses.length == 0) {
throw new IllegalArgumentException(
"Ao menos um validador deve ser passado como argumento na construção");
}
this.messageProducer = messageProducer;
this.validators = new Validator[validatorClasses.length];
int i = 0;
for (Class<? extends Validator<T>> clazz : validatorClasses) {
Constructor<? extends Validator<T>> constructor;
try {
constructor = clazz.getConstructor(MessageProducer.class, boolean.class);
constructor.setAccessible(true);
validators[i++] = constructor.newInstance(messageProducer, isFormatted);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
public void assertValid(T value) {
InvalidStateException lastException = null;
boolean isValid = false;
for (Validator<T> v : validators) {
if (v.isEligible(value)) {
try {
v.assertValid(value);
isValid = true;
break;
} catch (InvalidStateException e) {
lastException = e;
}
}
}
if (!isValid) {
if (lastException != null) {
throw lastException;
} else {
throw new InvalidStateException(messageProducer.getMessage(invalidFormat));
}
}
}
public List<ValidationMessage> invalidMessagesFor(T value) {
List<ValidationMessage> result = null;
for (Validator<T> v : validators) {
if (v.isEligible(value)) {
List<ValidationMessage> invalidMessages = v.invalidMessagesFor(value);
result = invalidMessages;
if (invalidMessages.isEmpty()) {
break;
}
}
}
if (result == null) {
result = new ArrayList<ValidationMessage>();
result.add(messageProducer.getMessage(invalidFormat));
}
return result;
}
public boolean isEligible(T object) {
boolean result = false;
for (Validator<T> v : validators) {
if (v.isEligible(object)) {
result = true;
break;
}
}
return result;
}
public void setInvalidFormat(InvalidValue invalidFormat) {
this.invalidFormat = invalidFormat;
}
/**
* @see Validator#generateRandomValid()
* @return um documento válido de acordo com as regras do primeiro validador passado como
* argumento na construção deste validador
*/
@Override
public T generateRandomValid() {
return validators[0].generateRandomValid();
}
}