nl.strohalm.cyclos.mobile.client.Navigation.java Source code

Java tutorial

Introduction

Here is the source code for nl.strohalm.cyclos.mobile.client.Navigation.java

Source

/*
   This file is part of Cyclos.
    
   Cyclos is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
    
   Cyclos 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 General Public License for more details.
    
   You should have received a copy of the GNU General Public License
   along with Cyclos; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    
 */
package nl.strohalm.cyclos.mobile.client;

import nl.strohalm.cyclos.mobile.client.accounts.AccountDetailsPage;
import nl.strohalm.cyclos.mobile.client.accounts.AccountsPage;
import nl.strohalm.cyclos.mobile.client.configuration.ConfigurationPage;
import nl.strohalm.cyclos.mobile.client.contacts.ContactDetailsPage;
import nl.strohalm.cyclos.mobile.client.contacts.ContactSelectPage;
import nl.strohalm.cyclos.mobile.client.contacts.ContactsPage;
import nl.strohalm.cyclos.mobile.client.help.HelpPage;
import nl.strohalm.cyclos.mobile.client.loadgeneraldata.LoadGeneralDataPage;
import nl.strohalm.cyclos.mobile.client.login.LoginPage;
import nl.strohalm.cyclos.mobile.client.model.AppState;
import nl.strohalm.cyclos.mobile.client.model.Parameters;
import nl.strohalm.cyclos.mobile.client.payments.MakePaymentPage;
import nl.strohalm.cyclos.mobile.client.payments.PaymentDetailsPage;
import nl.strohalm.cyclos.mobile.client.payments.PaymentPreviewPage;
import nl.strohalm.cyclos.mobile.client.payments.PaymentsPage;
import nl.strohalm.cyclos.mobile.client.ui.Page;
import nl.strohalm.cyclos.mobile.client.ui.PageAnchor;
import nl.strohalm.cyclos.mobile.client.ui.widgets.LogoutDialog;
import nl.strohalm.cyclos.mobile.client.users.UserDetailsPage;
import nl.strohalm.cyclos.mobile.client.users.UserSearchPage;
import nl.strohalm.cyclos.mobile.client.users.UserSelectPage;
import nl.strohalm.cyclos.mobile.client.users.UsersPage;
import nl.strohalm.cyclos.mobile.client.utils.StringHelper;

import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.History;

/**
 * Manages the history events, instantiating corresponding components according to them.
 * 
 * @author luis
 */
public class Navigation {

    public static final String PARAMETERS_SEPARATOR = "!";
    private static Navigation INSTANCE;
    private boolean exitOnHistoryChange = false;

    /**
     * Returns the HistoryManager instance
     */
    public static Navigation get() {
        if (INSTANCE == null) {
            INSTANCE = new Navigation();
            History.addValueChangeHandler(new ValueChangeHandler<String>() {
                @Override
                public void onValueChange(ValueChangeEvent<String> event) {
                    INSTANCE.handle(event.getValue());
                }
            });
        }
        // Reset exitOnHistoryChange if user attempts to navigate
        INSTANCE.exitOnHistoryChange = false;
        return INSTANCE;
    }

    /**
     * Navigates to the given page
     */
    public void go(PageAnchor anchor) {
        go(anchor, null);
    }

    /**
     * Navigates to the given page without history
     * and without checks
     */
    public void goNoHistory(PageAnchor anchor) {
        goNoHistory(anchor, null);
    }

    /**
     * Navigates to the given page with the given parameters, without history
     * and without checks
     */
    public void goNoHistory(PageAnchor anchor, Parameters parameters) {
        Page page = resolvePage(anchor);
        page.setPageAnchor(anchor);
        if (parameters != null) {
            page.setParameters(parameters);
        }
        go(page);
    }

    /**
     * Navigates to the given page with custom parameters
     */
    public void go(PageAnchor anchor, Parameters parameters) {
        if (anchor != null) {
            String newToken = anchor.toToken(parameters);
            goToken(newToken);
        }
    }

    /**
     * Go to a page using it's token
     */
    public void goToken(String token) {
        String currentToken = History.getToken();
        if (StringHelper.isNotEmpty(currentToken) && currentToken.equals(token)) {
            // State has not changed
            History.fireCurrentHistoryState();
        } else {
            History.newItem(token);
        }
    }

    /**
     * Loads the initial page
     */
    public void loadInitialPage() {
        PageAnchor anchor = getInitialPageAnchor();
        go(anchor);
    }

    /**
     * Returns the initial page token, that is, the one used when no page is specified
     */
    private PageAnchor getInitialPageAnchor() {
        return getInitialPageAnchor(CyclosMobile.get().getAppState());
    }

    /**
     * Returns the initial page token, that is, the one used when no page is specified
     */
    private PageAnchor getInitialPageAnchor(AppState appStatus) {
        switch (appStatus) {
        case SERVER_NOT_CONFIGURED:
            // The server root URL is not configured - go to the configuration page.
            return PageAnchor.CONFIGURATION;
        }
        if (LoggedUser.get().isLoggedIn()) {
            // There is a logged user - go to the accounts.
            return PageAnchor.ACCOUNTS;
        }
        // No logged user - go to login page.
        return PageAnchor.LOGIN;
    }

    /**
     * Handles a History token change
     */
    private void handle(String token) {

        // Check an empty token or if exit application is set
        if (StringHelper.isEmpty(token) || exitOnHistoryChange) {
            // If it is empty exit application
            CyclosMobile.get().getPhoneGap().exitApp();
            return;
        }

        // Check if we have parameters
        int separatorPosition = token.indexOf(PARAMETERS_SEPARATOR);

        // Get the page token
        String pageToken = separatorPosition < 0 ? token : token.substring(0, separatorPosition);

        // Get the page parameters
        String pageParams = separatorPosition < 0 ? null
                : token.substring(separatorPosition + PARAMETERS_SEPARATOR.length());

        PageAnchor pageAnchor = null;
        Parameters parameters = null;
        try {
            // Find the page anchor
            pageAnchor = PageAnchor.valueOf(pageToken.toUpperCase());

            // Parse the parameters
            if (StringHelper.isNotEmpty(pageParams)) {
                parameters = Parameters.parse(pageParams);
            }
        } catch (Exception e) {
            // When there is an error handling the history token, just use the initial anchor and no parameters
            pageAnchor = getInitialPageAnchor();
        }

        Page page = resolvePage(pageAnchor);

        // If no valid page return
        if (page == null) {
            return;
        }

        // Check if the new page is not the same as current page
        Page currentPage = CyclosMobile.get().getMainLayout().getCurrentPage();
        if (currentPage != null && page.getPageAnchor() == currentPage.getPageAnchor()
                && !isAlwaysNavigable(pageAnchor)) {
            return;
        }

        // Check if page is Login
        if (pageAnchor == PageAnchor.LOGIN) {
            if (LoggedUser.get().isLoggedIn()) {
                // Display logout confirmation prompt
                LogoutDialog logoutDialog = new LogoutDialog();
                logoutDialog.display();
                return;
            }
        }

        // Check if page is accessible
        if (isPageAllowed(page)) {
            // Prepare the page
            page.setParameters(parameters);
        } else {
            // Go to allowed page
            AppState status = CyclosMobile.get().getAppState();
            page = resolvePage(getInitialPageAnchor(status));
        }

        go(page);
    }

    /**
     * Check if the given page is allowed to be accessed with the current application status     
     */
    private boolean isPageAllowed(Page page) {
        AppState appStatus = CyclosMobile.get().getAppState();

        switch (page.getPageAnchor()) {
        // To access configuration's page server must not be configured or user must not be logged in
        case CONFIGURATION:
            return appStatus == AppState.SERVER_NOT_CONFIGURED || !LoggedUser.get().isLoggedIn();
        // Help page always can be accessed
        case HELP:
            return true;
        }

        // To access a ready state page user must be logged in
        if (page.getMinimumAppState() == AppState.READY) {
            return LoggedUser.get().isLoggedIn();
        }

        // Any other page can be accessed if page status matches application status
        return page.getMinimumAppState().matches(appStatus);
    }

    /**
     * Maps the given token into a page
     */
    private Page resolvePage(PageAnchor anchor) {
        Page page = null;
        switch (anchor) {
        case ACCOUNTS:
            page = new AccountsPage();
            break;
        case ACCOUNT_DETAILS:
            page = new AccountDetailsPage();
            break;
        case CONFIGURATION:
            page = new ConfigurationPage();
            break;
        case CONTACTS:
            page = new ContactsPage();
            break;
        case CONTACT_DETAILS:
            page = new ContactDetailsPage();
            break;
        case CONTACT_SELECT:
            page = new ContactSelectPage();
            break;
        case HELP:
            page = new HelpPage();
            break;
        case LOAD_GENERAL_DATA:
            page = new LoadGeneralDataPage();
            break;
        case LOGIN:
            page = new LoginPage();
            break;
        case MAKE_PAYMENT:
            page = new MakePaymentPage();
            break;
        case PAYMENTS:
            page = new PaymentsPage();
            break;
        case PAYMENT_DETAILS:
            page = new PaymentDetailsPage();
            break;
        case PAYMENT_PREVIEW:
            page = new PaymentPreviewPage();
            break;
        case USERS:
            page = new UsersPage();
            break;
        case USER_DETAILS:
            page = new UserDetailsPage();
            break;
        case USER_SELECT:
            page = new UserSelectPage();
            break;
        case USER_SEARCH:
            page = new UserSearchPage();
            break;
        }
        page.setPageAnchor(anchor);
        return page;
    }

    /**
     * Exits the application on the next history change
     */
    public void exitOnHistoryChange() {
        exitOnHistoryChange = true;
    }

    /**
     * Returns whether navigation always should work for the actual page
     */
    private boolean isAlwaysNavigable(PageAnchor anchor) {
        if (anchor != null) {
            switch (anchor) {
            case HELP:
                return true;
            }
        }
        return false;
    }

    /**
     * Go to the given page and checks session before continue 
     */
    private void go(Page page) {
        AppState status = CyclosMobile.get().getAppState();
        // If a session exists check timeout
        if (status == AppState.READY) {
            // User is active, reset timeout
            LoggedUser.get().initSessionTimeout();
        }
        CyclosMobile.get().getMainLayout().show(page);
    }

}