package edu.ualberta.med.biobank.mvp.model.validation;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.pietschy.gwt.pectin.client.condition.Condition;
import com.pietschy.gwt.pectin.client.condition.DelegatingCondition;
import com.pietschy.gwt.pectin.client.form.validation.HasValidation;
import com.pietschy.gwt.pectin.client.form.validation.ValidationEvent;
import com.pietschy.gwt.pectin.client.form.validation.ValidationHandler;
import com.pietschy.gwt.pectin.client.form.validation.ValidationResultImpl;
import edu.ualberta.med.biobank.mvp.util.HandlerRegistry;
public class ValidationTree extends AbstractValidation {
private static final Condition TRUE = new DelegatingCondition(true);
private final ConditionMonitor conditionMonitor = new ConditionMonitor();
private final ValidationMonitor validationMonitor = new ValidationMonitor();
private final HandlerRegistry handlerReg = new HandlerRegistry();
private final Map<HasValidation, Condition> validators =
new LinkedHashMap<HasValidation, Condition>();
public void add(HasValidation validator) {
add(validator, TRUE);
}
public void add(HasValidation validator, Condition condition) {
// TODO: figure out what to do if added twice?
if (!validators.containsKey(validator)) {
validators.put(validator, condition);
// TODO: don't listen to the same condition twice?
handlerReg.add(validator.addValidationHandler(validationMonitor));
handlerReg.add(condition.addValueChangeHandler(conditionMonitor));
}
}
@Override
public boolean validate() {
try {
validationMonitor.setIgnoreEvents(true);
boolean valid = runValidators();
updateValidationResult();
return valid;
} finally {
validationMonitor.setIgnoreEvents(false);
}
}
@Override
public void clear() {
try {
// don't want to pay attention to all the events fired when we clear
// our validators
validationMonitor.setIgnoreEvents(true);
for (HasValidation validator : validators.keySet()) {
validator.clear();
}
super.clear();
} finally {
validationMonitor.setIgnoreEvents(false);
}
}
public void dispose() {
handlerReg.dispose();
}
private boolean runValidators() {
boolean valid = true;
for (Entry<HasValidation, Condition> entry : validators.entrySet()) {
HasValidation validator = entry.getKey();
Condition condition = entry.getValue();
if (Boolean.TRUE.equals(condition.getValue())) {
valid = valid && validator.validate();
}
else {
validator.clear();
}
}
return valid;
}
private void updateValidationResult() {
ValidationResultImpl validationResult = new ValidationResultImpl();
for (HasValidation validator : validators.keySet()) {
validationResult.addAll(validator.getValidationResult()
.getMessages());
}
setValidationResult(validationResult);
}
private class ValidationMonitor implements ValidationHandler {
private boolean ignoreEvents = false;
@Override
public void onValidate(ValidationEvent event) {
doUpdate();
}
private void doUpdate() {
if (!isIgnoreEvents()) {
updateValidationResult();
}
}
public boolean isIgnoreEvents() {
return ignoreEvents;
}
public void setIgnoreEvents(boolean ignoreEvents) {
this.ignoreEvents = ignoreEvents;
}
}
private class ConditionMonitor implements ValueChangeHandler<Boolean> {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
updateValidationResult();
}
}
}