package br.com.caelum.stella.bean.validation.xml.logic;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import net.vidageek.mirror.dsl.Mirror;
import br.com.caelum.stella.bean.validation.xml.Choice;
import br.com.caelum.stella.bean.validation.xml.ChoiceItem;
public class StellaChoiceValidator implements ConstraintValidator<Choice, Object> {
public void initialize(final Choice annotation) {
}
public boolean isValid(final Object toValidate, ConstraintValidatorContext context) {
Class<? extends Object> type = toValidate.getClass();
if (!hasChoiceItens(toValidate)) {
return validateChoice(toValidate, new Mirror().on(type).reflectAll().fields());
}
return validateChoice(toValidate, getChoiceItemAnnotatedFields(type));
}
private List<Field> getChoiceItemAnnotatedFields(final Class<? extends Object> type) {
List<Field> result = new ArrayList<Field>();
for (Field field : new Mirror().on(type).reflectAll().fields()) {
if (new Mirror().on(field).reflect().annotation(ChoiceItem.class) != null) {
result.add(field);
}
}
return result;
}
private boolean validateChoice(final Object toValidate, final List<Field> fields) {
int nonNullFields = 0;
for (Field field : fields) {
if (!field.getClass().isPrimitive()) {
Object object = new Mirror().on(toValidate).get().field(field);
if (object != null) {
nonNullFields++;
}
}
}
return nonNullFields == 1;
}
private boolean hasChoiceItens(final Object toValidate) {
for (Field f : new Mirror().on(toValidate.getClass()).reflectAll().fields()) {
if (new Mirror().on(f).reflect().annotation(ChoiceItem.class) != null) {
return true;
}
}
return false;
}
}