/*
* Databinder: a simple bridge from Wicket to Hibernate
* Copyright (C) 2008 Nathan Hamblen nathan@technically.us
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.databinder.valid.hib;
import java.io.Serializable;
import net.databinder.components.hib.DataForm;
import net.databinder.models.hib.HibernateObjectModel;
import net.databinder.valid.hib.DatabinderValidator.UnrecognizedModelException;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.hibernate.Hibernate;
import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
/**
* Form that adds a {@link DatabinderValidator} to all its components that
* do not have any other validator in place. To exempt a component from
* this validation, add to it the dummy validator returned by {@link #nonValidator()}.
* Components are inspected in {@link #onBeforeRender()}. Those that do not have
* a usable model (see {@link DatabinderValidator#DatabinderValidator()}
* at that time are ignored.
* @author Nathan Hamblen
* @author Rodolfo Hansen
* @param <T> the model object type
* @see DatabinderValidator
*/
public class ValidDataForm<T> extends DataForm<T> {
/** Hibernate Validator to use. */
private final ClassValidator<T> validator;
/** */
private static final long serialVersionUID = 1L;
/**
* Instantiates this form and a new, blank instance of the given class as a persistent model
* object. By default the model object created is serialized and retained between requests until
* it is persisted.
* @param id wicket:id
* @param modelClass for the persistent object
* @see HibernateObjectModel#setRetainUnsaved(boolean)
*/
public ValidDataForm(final String id, final Class<T> modelClass) {
this(id, modelClass, new ClassValidator<T>(modelClass));
}
public ValidDataForm(final String id, final Class<T> modelClass, final ClassValidator<T> validator) {
super(id, modelClass);
this.validator = validator;
}
public ValidDataForm(final String id, final HibernateObjectModel<T> model) {
super(id, model);
this.validator = null;
}
public ValidDataForm(final String id, final HibernateObjectModel<T> model, final ClassValidator<T> validator) {
super(id, model);
this.validator = validator;
}
/**
* Instantiates this form with a persistent object of the given class and id.
* @param id Wicket id
* @param modelClass for the persistent object
* @param persistentObjectId id of the persistent object
*/
public ValidDataForm(final String id, final Class<T> modelClass, final Serializable persistentObjectId) {
this(id, modelClass, persistentObjectId, new ClassValidator<T>(modelClass));
}
/**
* Instantiates this form with a persistent object of the given class and id.
* @param id Wicket id
* @param modelClass for the persistent object
* @param persistentObjectId id of the persistent object
* @param validator ClassValidator to use
*/
public ValidDataForm(final String id, final Class<T> modelClass, final Serializable persistentObjectId, final ClassValidator<T> validator) {
super(id, modelClass, persistentObjectId);
this.validator = validator;
}
/**
* Form that is nested below a component with a compound model containing a Hibernate
* model.
* @param id wicket:id
*/
public ValidDataForm(final String id) {
super(id);
this.validator = null;
}
/**
* Form that is nested below a component with a compound model containing a Hibernate
* model.
* @param id wicket:id
* @param validator ClassValidator to use
*/
public ValidDataForm(final String id, final ClassValidator<T> validator) {
super(id);
this.validator = validator;
}
@SuppressWarnings("unchecked")
protected void validateModelObject() {
final T o = getPersistentObjectModel().getObject();
ClassValidator<T> v = validator == null
? v = new ClassValidator(Hibernate.getClass(o))
: validator;
for (final InvalidValue iv : v.getInvalidValues(o)) {
error(iv.getPropertyName() + " " + iv.getMessage());
}
}
/**
* Add a validator to any form components that have no existing validator
* and whose model is recognized by {@link DatabinderValidator#addTo(FormComponent)}.
*/
@Override
protected void onBeforeRender() {
super.onBeforeRender();
visitFormComponents(new FormComponent.AbstractVisitor() {
@Override
protected void onFormComponent(final FormComponent<?> formComponent) {
if (formComponent.getValidators().isEmpty()) {
try {
DatabinderValidator.addTo(formComponent, validator);
} catch (final UnrecognizedModelException e) { }
}
}
});
}
/**
* @return dummy validator that can be used to exempt a component
* from this form's inspection in {@link #onBeforeRender()}
*/
public static IValidator<?> nonValidator() {
return new IValidator<Object>() {
private static final long serialVersionUID = 1L;
public void validate(final IValidatable<Object> validatable) { }
};
}
}