package edu.ualberta.med.biobank.mvp.presenter.validation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.user.client.ui.HasValue;
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.Severity;
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 com.pietschy.gwt.pectin.client.value.ValueHolder;
import com.pietschy.gwt.pectin.client.value.ValueModel;
import edu.ualberta.med.biobank.mvp.presenter.IValidatablePresenter;
/**
* Created so presenters can use the validation of other presenters, possibly
* based on a condition.
*
* @author jferland
*
*/
public class ValidationTree extends AbstractValidation {
private final ValidationMonitor validationMonitor = new ValidationMonitor();
private final Map<HasValue<?>, ValueValidation<?>> valueValidations =
new HashMap<HasValue<?>, ValueValidation<?>>();
private final List<HasValidation> validations =
new ArrayList<HasValidation>();
private final ValueHolder<Boolean> valid = new ValueHolder<Boolean>(true);
public <T> ValueValidationBuilder<T> validate(HasValue<T> source) {
return new ValueValidationBuilder<T>(this, source);
}
public DelegatingConditionBuilder add(IValidatablePresenter presenter) {
HasValidation validation = presenter.getValidation();
DelegatingCondition condition = new DelegatingCondition(true);
add(new ConditionalValidation(validation, condition));
return new DelegatingConditionBuilder(condition);
}
public ValueModel<Boolean> valid() {
return valid;
}
public <T> ValueValidation<T> getValueValidation(HasValue<T> source) {
@SuppressWarnings("unchecked")
ValueValidation<T> validation =
(ValueValidation<T>) valueValidations.get(source);
if (validation == null) {
validation = new ValueValidation<T>(source);
add(validation);
}
return validation;
}
@Override
public boolean validate() {
try {
validationMonitor.setIgnoreEvents(true);
boolean valid = runValidations();
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 validation : validations) {
validation.clear();
}
super.clear();
} finally {
validationMonitor.setIgnoreEvents(false);
}
}
private void add(HasValidation validation) {
validations.add(validation);
handlerRegistry.add(validation.addValidationHandler(validationMonitor));
}
private boolean runValidations() {
boolean valid = true;
for (HasValidation validation : validations) {
valid = valid && validation.validate();
}
return valid;
}
private void updateValidationResult() {
ValidationResultImpl result = new ValidationResultImpl();
for (HasValidation validation : validations) {
result.addAll(validation.getValidationResult().getMessages());
}
setValidationResult(result);
valid.setValue(!result.contains(Severity.ERROR));
}
private class ValidationMonitor implements ValidationHandler {
private boolean ignoreEvents = false;
public boolean isIgnoreEvents() {
return ignoreEvents;
}
public void setIgnoreEvents(boolean ignoreEvents) {
this.ignoreEvents = ignoreEvents;
}
@Override
public void onValidate(ValidationEvent event) {
if (!isIgnoreEvents()) {
doUpdate();
}
}
public void doUpdate() {
updateValidationResult();
}
}
}