package org.appfuse.webapp.client.application;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.appfuse.webapp.client.application.base.request.RequestEvent;
import org.appfuse.webapp.client.application.base.security.AuthRequiredEvent;
import org.appfuse.webapp.client.application.base.security.LoginEvent;
import org.appfuse.webapp.client.application.base.security.LogoutEvent;
import org.appfuse.webapp.client.application.base.security.RequestForbidenEvent;
import org.appfuse.webapp.client.proxies.LookupConstantsProxy;
import org.appfuse.webapp.client.proxies.UserProxy;
import org.appfuse.webapp.client.requests.ApplicationRequestFactory;
import org.appfuse.webapp.client.ui.Shell;
import org.appfuse.webapp.client.ui.home.HomePlace;
import org.appfuse.webapp.client.ui.login.LoginPlace;
import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.google.gwt.activity.shared.ActivityManager;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.logging.client.LogConfiguration;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceChangeEvent;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.place.shared.PlaceHistoryHandler;
import com.google.gwt.place.shared.PlaceHistoryMapper;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryLogHandler;
import com.google.web.bindery.requestfactory.shared.LoggingRequest;
import com.google.web.bindery.requestfactory.shared.Receiver;
/**
* Application for browsing entities.
*/
public class DesktopApplication extends Application implements LoginEvent.Handler, LogoutEvent.Handler {
private static final Logger LOGGER = Logger.getLogger(DesktopApplication.class.getName());
@Inject
public DesktopApplication(
final Shell shell,
final ApplicationMenu menu,
final ApplicationRequestFactory requestFactory,
final EventBus eventBus,
final PlaceController placeController,
final PlaceHistoryMapper placeHistoryMapper,
final PlaceHistoryHandler placeHistoryHandler,
final ActivityManager activityManager,
final ApplicationProxyFactory proxyFactory,
final ApplicationValidatorFactory validatorFactory) {
super(shell, menu, requestFactory, eventBus, placeController, placeHistoryMapper, placeHistoryHandler, activityManager, proxyFactory,
validatorFactory);
}
@Override
public void run() {
setProgress(50);
/* Add handlers */
initHandlers();
setProgress(60);
/* load application constants */
requestFactory.lookupRequest().getApplicationConstants().fire(new Receiver<LookupConstantsProxy>() {
@Override
public void onSuccess(final LookupConstantsProxy lookupConstants) {
setLookupConstants(lookupConstants);
setProgress(70);
/* Authentication */
requestFactory.userRequest().getCurrentUser().with("roles").fire(new Receiver<UserProxy>() {
@Override
public void onSuccess(final UserProxy currentUser) {
setProgress(85);
if(currentUser != null) {
setCurrentUser(currentUser);
setProgress(100);
showShell();
/* Register home place and parse url for current place token */
final Place defaultPlace = new HomePlace();
placeHistoryHandler.register(placeController, eventBus, defaultPlace);
placeHistoryHandler.handleCurrentHistory();
shell.onLoginEvent(new LoginEvent());
} else {
showShell();
/* Register home place and parse url for current place token */
final Place defaultPlace = new LoginPlace(History.getToken());
placeHistoryHandler.register(placeController, eventBus, defaultPlace);
placeController.goTo(defaultPlace);
}
}
});
}
});
}
protected void showShell() {
final Element loading = Document.get().getElementById("loading");
loading.getParentElement().removeChild(loading);
/* And show the user the shell */
RootLayoutPanel.get().add(shell);
RootLayoutPanel.get().getElement().setId("rootPanel");
// remove gwt extra divs and place shell nodes directly into the document body,
// (and hope for the best about xbrowser compatibility..)
shell.getElement().setId("shell");
final Element shellElement = Document.get().getElementById("shell");
shellElement.removeFromParent();
Document.get().getElementById("rootPanel").removeFromParent();
Element shellChildElement = shellElement.getFirstChildElement();
while (shellChildElement != null) {
shellChildElement.removeFromParent();
Document.get().getBody().appendChild(shellChildElement);
shellChildElement = shellElement.getFirstChildElement();
}
}
protected void initHandlers() {
GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
@Override
public void onUncaughtException(final Throwable e) {
Window.alert("Error: " + e.getMessage());
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
});
if (LogConfiguration.loggingIsEnabled()) {
// Add remote logging handler
final RequestFactoryLogHandler.LoggingRequestProvider provider = new RequestFactoryLogHandler.LoggingRequestProvider() {
@Override
public LoggingRequest getLoggingRequest() {
return requestFactory.loggingRequest();
}
};
Logger.getLogger("").addHandler(new RequestFactoryLogHandler(provider, Level.WARNING, new ArrayList<String>()));
}
RequestEvent.register(eventBus, new RequestEvent.Handler() {
// Only show loading status if a request isn't serviced in 250ms.
private static final int LOADING_TIMEOUT = 250;
@Override
public void onRequestEvent(final RequestEvent requestEvent) {
if (requestEvent.getState() == RequestEvent.State.SENT) {
DOM.setStyleAttribute(shell.getElement(), "cursor", "wait");
shell.getMole().showDelayed(LOADING_TIMEOUT);
} else {
DOM.setStyleAttribute(shell.getElement(), "cursor", "default");
shell.getMole().hide();
}
}
});
if(shell instanceof PlaceChangeEvent.Handler) {
eventBus.addHandler(PlaceChangeEvent.TYPE, (PlaceChangeEvent.Handler)shell);
}
LoginEvent.register(eventBus, this);
LogoutEvent.register(eventBus, this);
AuthRequiredEvent.register(eventBus, new AuthRequiredEvent.Handler() {
@Override
public void onAuthRequiredEvent(final AuthRequiredEvent authRequiredEvent) {
placeController.goTo(new LoginPlace(History.getToken()));
}
});
RequestForbidenEvent.register(eventBus, new RequestForbidenEvent.Handler() {
@Override
public void onRequestForbidenEvent(final RequestForbidenEvent requestForbidenEvent) {
shell.addMessage(i18n._03_title(), AlertType.ERROR);
}
});
}
@Override
public void onLoginEvent(final LoginEvent loginEvent) {
requestFactory.userRequest().getCurrentUser().with("roles").fire(new Receiver<UserProxy>() {
@Override
public void onSuccess(final UserProxy currentUser) {
if(currentUser != null) {
setCurrentUser(currentUser);
/* re-load application constants */
requestFactory.lookupRequest().getApplicationConstants().fire(new Receiver<LookupConstantsProxy>() {
@Override
public void onSuccess(final LookupConstantsProxy lookupConstants) {
setLookupConstants(lookupConstants);
shell.onLoginEvent(loginEvent);
final Place currentPlace = placeController.getWhere();
if(currentPlace instanceof LoginPlace) {// explicit login
final LoginPlace loginPlace = (LoginPlace) currentPlace;
if(loginPlace.getHistoryToken() != null && !"".equals(loginPlace.getHistoryToken())) {
History.newItem(loginPlace.getHistoryToken());
} else {
placeController.goTo(new HomePlace());
}
}else {
//this was an intercepted login so we leave user on current page
}
}
});
}
}
});
}
@Override
public void onLogoutEvent(final LogoutEvent logoutEvent) {
setCurrentUser(null);
shell.onLogoutEvent(logoutEvent);
placeController.goTo(new LoginPlace());
}
/* The progressbar */
private Element progressbar;
private void setProgress(final int progress) {
if(progressbar == null) {
progressbar = Document.get().getElementById("progressbar");
}
progressbar.setAttribute("style", "width: " + progress + "%;");
}
}