package org.nocket.gen.page.element.synchronizer;
import gengui.annotations.Modal;
import gengui.guiadapter.AbstractMethodActivator;
import java.io.Serializable;
import org.apache.commons.lang.BooleanUtils;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.nocket.NocketSession;
import org.nocket.gen.page.element.ButtonElement;
import org.nocket.gen.page.element.synchronizer.error.MethodExceptionHandlerI;
import org.nocket.gen.page.guiservice.DMDWebGenGuiServiceProvider;
import org.nocket.util.Assert;
import org.nocket.util.AssertionException;
// TODO: Auto-generated Javadoc
/**
* The Class ButtonCallback.
*/
@SuppressWarnings("serial")
public class ButtonCallback implements Serializable {
/** The helper. */
private final SynchronizerHelper helper;
/** The is closer. */
private boolean isCloser;
/** The interceptor. */
private ButtonCallbackInterceptor interceptor;
/**
* Instantiates a new button callback.
*
* @param element the element
* @param interceptor the interceptor
*/
public ButtonCallback(ButtonElement element, ButtonCallbackInterceptor interceptor) {
this.interceptor = interceptor != null ? interceptor : new ButtonCallbackInterceptor();
this.helper = new SynchronizerHelper(element);
//Performance improvement: The calls of AbstractMethodActivator.isCloserMethod take
// a mentionable amount of time on mask construction (about 16% in production mode,
// measured on 27.03.2013). As most masks are pages which can't be closed in org.nocket,
// we omit the call in that case.
//ATTENTION: Same improvement applies in TableButtonCallback
Boolean isCloserMethod = (element.getContext().isPage()) ? Boolean.FALSE :
AbstractMethodActivator.isCloserMethod(helper.getRef(), helper.getButtonMethod());
//TODO: according to gengui a method which is not clearly detected as being a closer
// derives its closing behavior from the start of the modal operation.
// This is not yet supported by web gengui. However, as closers are currently only
// supported for modal dialogs at all, the behavior simply defaults to true
isCloser = !BooleanUtils.isFalse(isCloserMethod);
}
/**
* Instantiates a new button callback.
*
* @param element the element
*/
public ButtonCallback(ButtonElement element) {
this(element, null);
}
/**
* Update all forms.
*
* @param target the target
*/
public void updateAllForms(AjaxRequestTarget target) {
SynchronizerHelper.updateAllFormsFromPage(helper.getContext(), target);
}
/**
* On submit.
*
* @param target the target
*/
public void onSubmit(AjaxRequestTarget target) {
interceptor.setButtonCallback(this);
interceptor.onSubmit(target);
}
/**
* Checks if is forced.
*
* @return true, if is forced
*/
public boolean isForced() {
return helper.isForced();
}
/**
* The Class MethodExceptionHandlerImpl.
*/
public class MethodExceptionHandlerImpl implements MethodExceptionHandlerI, Serializable {
/** The exception occured. */
private boolean exceptionOccured;
/**
* Instantiates a new method exception handler impl.
*/
private MethodExceptionHandlerImpl() {
}
/* (non-Javadoc)
* @see org.nocket.gen.page.element.synchronizer.error.MethodExceptionHandlerI#displayError(java.lang.Object, java.lang.Throwable, java.lang.String, java.lang.String)
*/
@Override
public void displayError(Object domainObject, Throwable exception, String title, String message) {
exceptionOccured = true;
helper.getContext().getMethodExceptionHandler().displayError(domainObject, exception, title, message);
}
/* (non-Javadoc)
* @see org.nocket.gen.page.element.synchronizer.error.MethodExceptionHandlerI#exceptionSwallowed(java.lang.Object, java.lang.Throwable)
*/
@Override
public void exceptionSwallowed(Object domainObject, Throwable exception) {
exceptionOccured = true;
helper.getContext().getMethodExceptionHandler().exceptionSwallowed(domainObject, exception);
}
/**
* Checks if is exception occured.
*
* @return true, if is exception occured
*/
public boolean isExceptionOccured() {
return exceptionOccured;
}
}
/**
* Interceptor für ButtonCallbacks um in den onSubmit-Process eingreifen zu
* können. Dabei gibt es mehrere Punkte an denen man eingreifen kann. Wird
* ein Button gedrückt, wird im Interceptor die Method
*
* <pre>
* <code> protected void onSubmit(AjaxRequestTarget target) {
* try {
* MethodExceptionHandlerImpl methodExceptionHandler = onSubmitPre(target);
* Object result = onSubmitProcess(methodExceptionHandler);
* onSubmitPost(methodExceptionHandler, result);
* } finally {
* onSubmitFinally(target);
* }
* }
* </code>
* </pre>
*
* aufgerufen. Darin wird der Prozess zum Registrieren des AjaxTargets
* <code>MethodExceptionHandlerImpl onSubmitPre(AjaxRequestTarget target)</code>
* , das Aufrufen der Button-Methode im Pojo
* <code>Object onSubmitProcess(MethodExceptionHandlerImpl methodExceptionHandler)</code>
* , das Verarbeiten von Exceptions bzw das Schliessen von Dialogen
* <code>onSubmitPost(MethodExceptionHandlerImpl methodExceptionHandler, Object result)</code>
* und schließlich das Deregistrieren des AjaxTargets
* <code>onSubmitFinally(AjaxRequestTarget target)</code> durchgeführt.<br>
* Alle diese Methode können überschrieben werden. Wird eine Methode nicht
* überschrieben, wird die entsprechende Methode am ButtonCallback
* ausgeführt. In den meisten Fällen wird die Methode
* <code>Object onSubmitProcess(MethodExceptionHandlerImpl methodExceptionHandler)</code>
* überschrieben werden. Gründe dafür könnten sein, es soll vor oder nach
* dem Aufruf der Pojo-Button-Methode noch eine Funktion durchgeführt
* werden.<br>
* Ein Beispiel ist in @see GeneratedPage
*
*
* @author meis026
*
*/
public static class ButtonCallbackInterceptor implements Serializable {
/** The button callback. */
private ButtonCallback buttonCallback;
/**
* Sets the button callback.
*
* @param buttonCallback the new button callback
*/
void setButtonCallback(ButtonCallback buttonCallback) {
this.buttonCallback = buttonCallback;
}
/**
* On submit.
*
* @param target the target
*/
protected void onSubmit(AjaxRequestTarget target) {
try {
MethodExceptionHandlerImpl methodExceptionHandler = onSubmitPre(target);
Object result = onSubmitProcess(methodExceptionHandler);
onSubmitPost(methodExceptionHandler, result);
} finally {
onSubmitFinally(target);
}
}
/**
* On submit finally.
*
* @param target the target
*/
protected void onSubmitFinally(AjaxRequestTarget target) {
DMDWebGenGuiServiceProvider webGuiServiceProvider = NocketSession.get().getDMDWebGenGuiServiceProvider();
try {
webGuiServiceProvider.unregisterAjaxRequestTarget(buttonCallback.helper.getContext(), target);
} catch (AssertionException e) {
String text = "WicketId = " + buttonCallback.helper.getWicketId() + " - ButtonMethod = "
+ buttonCallback.helper.getButtonMethod().getName();
throw new RuntimeException(text + " --- " + e.getMessage(), e);
}
}
/**
* On submit process.
*
* @param methodExceptionHandler the method exception handler
* @return the object
*/
protected Object onSubmitProcess(MethodExceptionHandlerImpl methodExceptionHandler) {
Object result = buttonCallback.helper.invokeButtonMethod(methodExceptionHandler);
return result;
}
/**
* On submit post.
*
* @param methodExceptionHandler the method exception handler
* @param result the result
*/
protected void onSubmitPost(MethodExceptionHandlerImpl methodExceptionHandler, Object result) {
DMDWebGenGuiServiceProvider webGuiServiceProvider = NocketSession.get().getDMDWebGenGuiServiceProvider();
if (methodExceptionHandler.isExceptionOccured()) {
return;
}
boolean hasModalAnnotation = buttonCallback.helper.getAnnotationOnButtonMethode(Modal.class) != null;
Assert.test(!hasModalAnnotation || !webGuiServiceProvider.isModalPanelActive(),
"One generic modal dialog over another is still not implemented. Button name = "
+ this.buttonCallback.helper.getButtonMethod().getName());
boolean modalPanelActive = webGuiServiceProvider.isModalPanelActive();
if (!modalPanelActive && !hasModalAnnotation) {
webGuiServiceProvider.showPage(result);
} else if (buttonCallback.isCloser && modalPanelActive) {
webGuiServiceProvider.closeModalPanel();
webGuiServiceProvider.showPage(result);
} else {
// if it is not a closer but a result of null, do nothing
if (result != null) {
/*
* While showing a modal dialog wicket will do no
* serialization of the models. So, it is possible to put a
* reference of data from the page to the dialog and let the
* dialog change it.
*/
webGuiServiceProvider.showModalPanel(result);
if (modalPanelActive) {
webGuiServiceProvider.closeModalPanel();
}
}
}
}
/**
* On submit pre.
*
* @param target the target
* @return the method exception handler impl
*/
protected MethodExceptionHandlerImpl onSubmitPre(AjaxRequestTarget target) {
DMDWebGenGuiServiceProvider webGuiServiceProvider = NocketSession.get().getDMDWebGenGuiServiceProvider();
webGuiServiceProvider.registerAjaxRequestTarget(buttonCallback.helper.getContext(), target);
return buttonCallback.new MethodExceptionHandlerImpl();
}
}
}