package com.metrink.croquet.examples.crm.pages;
import java.lang.reflect.InvocationTargetException;
import javax.persistence.EntityManager;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.hibernate.HibernateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.metrink.croquet.examples.crm.data.Identifiable;
import com.metrink.croquet.wicket.CroquetPage;
/**
* An abstract page that has a form which is updated by the extending page.
*
* @param <T> the type of the object the form represents.
*/
public abstract class AbstractFormPage<T extends Identifiable> extends CroquetPage {
private static final long serialVersionUID = -3136579068845135299L;
private static final Logger LOG = LoggerFactory.getLogger(AbstractFormPage.class);
private final Class<T> beanClass;
private IModel<T> formModel;
private Form<T> form;
private Button updateSaveButton;
/*
public AbstractFormPage() {
beanClass = null;
entityManager = null;
}
*/
/**
* Constructor.
* @param beanClass the class of the type objects stored in the form.
* @param entityManager the {@link EntityManager} that will create and update the objects.
*/
public AbstractFormPage(final Class<T> beanClass, final EntityManager entityManager) {
this.beanClass = beanClass;
try {
this.formModel = Model.of(createNewBean());
} catch (final InstantiationException e) {
LOG.error("Error creating new bean: {}", e.getMessage());
getSession().error("Error creating new bean: " + e.getMessage());
AbstractFormPage.this.setResponsePage(AbstractFormPage.this.getClass());
return;
}
form = new Form<T>("form", this.formModel) {
private static final long serialVersionUID = -3564662582656203263L;
@Override
protected void onSubmit() {
final T bean = getModelObject();
LOG.debug("Entity manager: {}", entityManager.isOpen());
try {
entityManager.getTransaction().begin();
// decide if we're creating a new one or updating
if(bean.getId() == null) {
entityManager.persist(bean);
LOG.debug("{} created", bean);
getSession().success(bean + " was added");
} else { // updating
entityManager.merge(bean);
LOG.debug("{} updated", bean);
getSession().success(bean + " was updated");
}
entityManager.getTransaction().commit();
} catch(final HibernateException e) {
final String msg = e.getMessage();
LOG.error("Error communicating with database: {}", msg);
getSession().error("Error communicating with database: " + msg);
entityManager.getTransaction().rollback();
}
// get any page params
final PageParameters params = getRedirectPageParameters();
// just redirect to ourself
this.setResponsePage(AbstractFormPage.this.getClass(), params);
}
};
// add in all the form's components
addFormComponents(form);
updateSaveButton = new Button("update-button", Model.of("New"));
form.add(updateSaveButton);
form.add(new AjaxButton("cancel-button", form) {
private static final long serialVersionUID = 1L;
@Override
protected void onSubmit(final AjaxRequestTarget target, final Form<?> submitForm) {
LOG.debug("Clearing form");
// set the model to a new object
try {
formModel.setObject(createNewBean());
} catch (final InstantiationException e) {
LOG.error("Error creating new bean: {}", e.getMessage());
getSession().error("Error creating new bean: " + e.getMessage());
AbstractFormPage.this.setResponsePage(AbstractFormPage.this.getClass());
return;
}
form.modelChanged();
form.clearInput();
target.add(form);
// update the button
updateSaveButton.setModel(Model.of("New"));
target.add(updateSaveButton);
}
}.setDefaultFormProcessing(false));
add(form);
}
/**
* Callback used to add all the components of the form.
* @param form the form to add components to.
*/
protected abstract void addFormComponents(final Form<T> form);
/**
* Returns the form's model.
* @return the form's model.
*/
protected IModel<T> getFormModel() {
return formModel;
}
/**
* Allows extending classes the ability to inject any page parameters for the redirect.
* @return blank {@link PageParameters}.
*/
protected PageParameters getRedirectPageParameters() {
return new PageParameters();
}
/**
* Creates a new bean.
* @return a new bean.
* @throws InstantiationException if anything goes wrong.
*/
protected T createNewBean() throws InstantiationException {
try {
return beanClass.getConstructor().newInstance();
} catch (final InstantiationException |
IllegalAccessException |
IllegalArgumentException |
InvocationTargetException |
NoSuchMethodException |
SecurityException e) {
// fold it all into one type of exception
throw new InstantiationException(e.getMessage());
}
}
/**
* Sets the form to the bean passed in, updating the form via AJAX.
* @param bean the bean to set the form to.
* @param target the target of whatever triggers the form fill action.
*/
protected void setForm(final T bean, final AjaxRequestTarget target) {
LOG.debug("Setting form to {}", bean);
// update the model with the new bean
formModel.setObject(bean);
// add the form to the target
target.add(form);
// update the button
updateSaveButton.setModel(Model.of("Update"));
target.add(updateSaveButton);
}
}