com.itude.mobile.mobbl.core.controller.MBViewManager.java Source code

Java tutorial

Introduction

Here is the source code for com.itude.mobile.mobbl.core.controller.MBViewManager.java

Source

/*
 * (C) Copyright Itude Mobile B.V., The Netherlands
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.itude.mobile.mobbl.core.controller;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;

import com.itude.mobile.android.util.StringUtil;
import com.itude.mobile.mobbl.core.MBException;
import com.itude.mobile.mobbl.core.configuration.mvc.MBConfigurationDefinition;
import com.itude.mobile.mobbl.core.configuration.mvc.MBDialogDefinition;
import com.itude.mobile.mobbl.core.configuration.mvc.MBPageDefinition;
import com.itude.mobile.mobbl.core.configuration.mvc.MBToolDefinition;
import com.itude.mobile.mobbl.core.configuration.mvc.exceptions.MBInvalidPathException;
import com.itude.mobile.mobbl.core.controller.MBApplicationController.ApplicationState;
import com.itude.mobile.mobbl.core.controller.MBDialogManager.MBDialogChangeListener;
import com.itude.mobile.mobbl.core.controller.exceptions.MBExpressionNotBooleanException;
import com.itude.mobile.mobbl.core.controller.helpers.MBActivityHelper;
import com.itude.mobile.mobbl.core.controller.util.DefaultHomeButtonHandler;
import com.itude.mobile.mobbl.core.controller.util.MBBasicViewController;
import com.itude.mobile.mobbl.core.model.MBDocument;
import com.itude.mobile.mobbl.core.model.MBElement;
import com.itude.mobile.mobbl.core.services.MBDataManagerService;
import com.itude.mobile.mobbl.core.services.MBLocalizationService;
import com.itude.mobile.mobbl.core.services.MBMetadataService;
import com.itude.mobile.mobbl.core.util.Constants;
import com.itude.mobile.mobbl.core.util.MBParseUtil;
import com.itude.mobile.mobbl.core.util.helper.MBSecurityHelper;
import com.itude.mobile.mobbl.core.util.threads.MBThreadHandler;
import com.itude.mobile.mobbl.core.view.MBAlert;
import com.itude.mobile.mobbl.core.view.MBPage;
import com.itude.mobile.mobbl.core.view.MBPage.OrientationPermission;
import com.itude.mobile.mobbl.core.view.builders.MBContentViewWrapper;
import com.itude.mobile.mobbl.core.view.components.tabbar.MBActionBarBuilder;

/**
 * Default view manager
 *
 */
public abstract class MBViewManager extends ActionBarActivity implements MBDialogChangeListener {
    public enum MBActionBarInvalidationOption {
        SHOW_FIRST, RESET_HOME_DIALOG, NOTIFY_LISTENER
    }

    protected static MBViewManager _instance;

    private Dialog _currentAlert;
    private boolean _singlePageMode;
    private boolean _showDialogTitle = false;

    private boolean _activityExists = false;

    private int _defaultScreenOrientation;

    private MBDialogManager _dialogManager;
    private MBShutdownHandler _shutdownHandler = new MBDefaultShutdownHandler();

    private HomeButtonHandler _homeButtonHandler;
    private ViewGroup _container;

    ///////////////////// Android lifecycle methods

    @Override
    protected void onCreate(android.os.Bundle savedInstanceState) {
        onPreCreate();

        _actionBarBuilder = constructActionBarBuilder();

        _dialogManager = new MBDialogManager(this);

        _homeButtonHandler = new DefaultHomeButtonHandler();

        /*
         *  We store our default orientation. This will be used to determine how pages should be shown by default
         *  See setOrientation
         */
        _defaultScreenOrientation = getRequestedOrientation();

        super.onCreate(null);

        supportRequestWindowFeature(Window.FEATURE_PROGRESS);
        supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

        // makes sure the action bar is initialized (otherwise, the setProgressBar.. doesn't work)
        if (getSupportActionBar() != null) {
            setSupportProgressBarIndeterminateVisibility(false);
        }

        getDialogManager().addDialogChangeListener(this);

        _instance = this;

        MBApplicationController.getInstance().startController();
    }

    public void prepareForApplicationStart() {
        _dialogManager.onCreate();
    }

    @Override
    public void setContentView(View view) {

        if (_container == null) {
            FrameLayout container = new FrameLayout(this);
            LayoutParams layout = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.MATCH_PARENT);
            container.setLayoutParams(layout);

            MBContentViewWrapper wrapper = MBApplicationFactory.getInstance().createContentViewWrapper();
            super.setContentView(wrapper.buildContentView(this, container));

            _container = container;
        }

        _container.removeAllViews();
        _container.addView(view);
    }

    @Override
    protected void onResume() {
        if (!_activityExists) {
            _activityExists = true;
        } else {
            _dialogManager.onResume();
        }
        super.onResume();
    }

    @Override
    protected void onRestart() {
        super.onRestart();

        MBApplicationController.getInstance().startOutcomeHandler();
    }

    @Override
    protected void onStop() {
        MBThreadHandler.getInstance().stopAllRunningThreads();

        MBApplicationController.getInstance().stopOutcomeHandler();

        super.onStop();
    }

    @Override
    protected void onDestroy() {
        // Our application is closing so after this point our ApplicationState should return that the application is not started.
        MBApplicationController.getInstance().setApplicationState(ApplicationState.NOTSTARTED);

        _dialogManager.onDestroy();

        super.onDestroy();
    }

    @Override
    protected void onPause() {
        if (MBActivityHelper.isApplicationBroughtToBackground(this)) {
            stopAlert();
            MBSecurityHelper.getInstance().logOutIfCheckNotSelected();
        }

        _dialogManager.onPause();

        super.onPause();
    }

    private void stopAlert() {
        Dialog currentAlert = getCurrentAlert();
        if (currentAlert != null)
            currentAlert.dismiss();
    }

    ///////////////////// 

    ///////////////////// Android method

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);

        final MBApplicationController appController = MBApplicationController.getInstance();

        if (Intent.ACTION_SEARCH.equals(intent.getAction()) || Intent.ACTION_VIEW.equals(intent.getAction())) {
            appController.handleSearchRequest(intent);
        }

        final String outcomeName = intent.getStringExtra(Constants.C_INTENT_POST_INITIALOUTCOMES_OUTCOMENAME);
        if (StringUtil.isNotBlank(outcomeName)) {

            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    if (appController.getOutcomeHandler() == null) {
                        appController.startOutcomeHandler();
                    }
                    appController.handleOutcome(new MBOutcome(outcomeName, null));
                }
            });
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (getActiveDialog() != null)
            for (MBBasicViewController controller : getActiveDialog().getAllFragments()) {
                controller.onActivityResult(requestCode, resultCode, data);
            }
    }

    /***
     * Only sets a flag to invalidate the menu on first invocation. The menu is built in {@link #onPrepareOptionsMenu(Menu)}
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return buildOptionsMenu(menu);
    }

    public void finishFromChild(MBDialogController childController) {
        MBDialogDefinition firstDialogDefinition = MBMetadataService.getInstance().getHomeDialogDefinition();
        final String firstDialog = firstDialogDefinition.getName();
        if (!childController.getName().equals(firstDialog)) {
            getDialogManager().activateHome();
        } else {
            getShutdownHandler().onShutdown();
        }

    }

    ///// Event handling /////

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
            // Take care of calling this method on earlier versions of
            // the platform where it doesn't exist.
            onBackPressed();

            return true;
        } else {
            // Pass this onKeyDown event trough to the underlying fragments
            if (!getActiveDialog().onKeyDown(keyCode, event))
                return super.onKeyDown(keyCode, event);
            else
                return true;
        }

    }

    @Override
    public void onBackPressed() {
        if (!getActiveDialog().onBackPressed()) {
            super.onBackPressed();
        }
    }

    public boolean onMenuKeyDown(int keyCode, KeyEvent event, View callingView) {
        boolean onKeyDown = super.onKeyDown(keyCode, event);

        if (!onKeyDown) {
            hideSoftKeyBoard(callingView);
            this.openOptionsMenu();
            return true;
        }

        return false;
    }

    @Override
    public boolean onSearchRequested() {
        if (getActiveDialog() != null)
            return getActiveDialog().onSearchRequested();
        else
            return false;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean handled = false;
        if (getActiveDialog() != null)
            handled = getActiveDialog().dispatchTouchEvent(ev);
        if (!handled)
            return super.dispatchTouchEvent(ev);
        return handled;
    }

    /////////////////////////////////////////////////////

    public void showAlert(MBAlert alert, boolean backStackEnabled) {
        alert.buildAlertDialog().show();
    }

    @SuppressLint("NewApi")
    public void invalidateOptionsMenu(boolean resetHomeDialog, final boolean selectHome) {
        super.supportInvalidateOptionsMenu();

        if (selectHome)
            getDialogManager().activateHome();

    }

    public Dialog getCurrentAlert() {
        return _currentAlert;
    }

    public void setCurrentAlert(Dialog currentAlert) {
        _currentAlert = currentAlert;
    }

    public boolean getSinglePageMode() {
        return _singlePageMode;
    }

    public void setSinglePageMode(boolean singlePageMode) {
        _singlePageMode = singlePageMode;
    }

    public void showPage(MBPage page, String displayMode, boolean addToBackStack) {

        Log.d(Constants.APPLICATION_NAME,
                "MBViewManager: showPage name=" + page.getPageName() + " pagestackName=" + page.getPageStackName()
                        + " mode=" + displayMode + " type=" + page.getPageType() + " orientation="
                        + ((MBPageDefinition) page.getDefinition()).getOrientationPermissions() + " backStack="
                        + addToBackStack);

        if (page.getPageType() == MBPageDefinition.MBPageType.MBPageTypesErrorPage || "POPUP".equals(displayMode)) {
            showAlertView(page);
        } else {
            addPageToPageStack(page, displayMode, addToBackStack);
        }
    }

    private void showAlertView(MBPage page) {

        if (getCurrentAlert() != null) {
            getCurrentAlert().dismiss();
        }

        String title = null;
        String message = null;

        MBDocument pageDoc = page.getDocument();
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        boolean buildDefault = true;
        if (pageDoc.getName().equals(MBConfigurationDefinition.DOC_SYSTEM_EXCEPTION)) {
            title = pageDoc.getValueForPath(MBConfigurationDefinition.PATH_SYSTEM_EXCEPTION_NAME);
            message = pageDoc.getValueForPath(MBConfigurationDefinition.PATH_SYSTEM_EXCEPTION_DESCRIPTION);
        } else {
            title = page.getTitle();
            message = MBLocalizationService.getInstance()
                    .getTextForKey((String) pageDoc.getValueForPath("/message[0]/@text"));
            if (message == null) {
                message = MBLocalizationService.getInstance()
                        .getTextForKey((String) pageDoc.getValueForPath("/message[0]/@text()"));
            }

            try {
                MBElement buttons = pageDoc.getValueForPath("/buttons[0]");
                MBElement neutral = buttons.getValueForPath("/neutral[0]");
                MBElement negative = buttons.getValueForPath("/negative[0]");
                MBElement positive = buttons.getValueForPath("/positive[0]");

                builder.setMessage(message).setTitle(title).setCancelable(true);

                buildAlertDialogButtons(builder, neutral);
                buildAlertDialogButtons(builder, negative);
                buildAlertDialogButtons(builder, positive);

                buildDefault = false;
            } catch (MBInvalidPathException e) {
                Log.w(Constants.APPLICATION_NAME, "Popup document " + pageDoc.getName()
                        + " has no buttons defined. Adding neutral button Ok");
            }
        }

        if (buildDefault) {
            builder.setMessage(message).setTitle(title).setCancelable(true).setNeutralButton("Ok",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });
        }

        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                Dialog dialog = builder.create();
                dialog.show();
                setCurrentAlert(dialog);
            }
        });

    }

    private void buildAlertDialogButtons(AlertDialog.Builder builder, final MBElement element) {
        String label = element.getValueForAttribute("label");
        if (StringUtil.isNotBlank(label)) {
            if ("neutral".equals(element.getName())) {
                builder.setNeutralButton(MBLocalizationService.getInstance().getTextForKey(label),
                        new OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                String outcome = element.getValueForAttribute("outcome");
                                if (StringUtil.isBlank(outcome)) {
                                    dialog.cancel();
                                } else {
                                    MBApplicationController.getInstance()
                                            .handleOutcome(new MBOutcome(outcome, null));
                                }
                            }
                        });
            } else if ("positive".equals(element.getName())) {
                builder.setPositiveButton(MBLocalizationService.getInstance().getTextForKey(label),
                        new OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                String outcome = element.getValueForAttribute("outcome");
                                if (StringUtil.isBlank(outcome)) {
                                    dialog.cancel();
                                } else {
                                    MBApplicationController.getInstance()
                                            .handleOutcome(new MBOutcome(outcome, null));
                                }
                            }
                        });

            } else if ("negative".equals(element.getName())) {
                builder.setNegativeButton(MBLocalizationService.getInstance().getTextForKey(label),
                        new OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                String outcome = element.getValueForAttribute("outcome");
                                if (StringUtil.isBlank(outcome)) {
                                    dialog.cancel();
                                } else {
                                    MBApplicationController.getInstance()
                                            .handleOutcome(new MBOutcome(outcome, null));
                                }
                            }
                        });

            }

        }

    }

    private void addPageToPageStack(MBPage page, String displayMode, boolean addToBackStack) {
        //MBDialogDefinition topDefinition = MBMetadataService.getInstance().getTopDialogDefinitionForDialogName(page.getDialogName());
        MBPageStackController pageStack = _dialogManager.getPageStack(page.getPageStackName());
        MBDialogController dialogController = pageStack.getParent();
        dialogController.showPage(page, displayMode, page.getPageStackName() + page.getPageName(),
                page.getPageStackName(), addToBackStack);
    }

    @Override
    public void supportInvalidateOptionsMenu() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                ActivityCompat.invalidateOptionsMenu(MBViewManager.this);
            }
        });
    }

    public boolean activateDialogWithName(String dialogName) {
        MBOutcome outcome = new MBOutcome(dialogName, null);
        outcome.setOrigin(new MBOutcome.Origin().withDialog(dialogName));
        MBApplicationController.getInstance().handleOutcome(outcome);
        return false;
    }

    public void endDialog(String dialogName, boolean keepPosition) {
        if (keepPosition)
            _dialogManager.getDialog(dialogName).popAll();
        else
            _dialogManager.getDialog(dialogName).dismiss();
    }

    public void popPage(String dialogName) {
        _dialogManager.getDialog(dialogName).popView();
    }

    public void makeKeyAndVisible() {
    }

    public String getActiveDialogName() {
        return _dialogManager.getActiveDialog() != null ? _dialogManager.getActiveDialog().getName() : null;
    }

    public void resetView() {
    }

    public void resetViewPreservingCurrentDialog() {
        // Walk trough all dialogControllers
        for (MBDialogController dc : _dialogManager.getDialogs()) {
            dc.clearAllViews();
        }

    }

    public static MBViewManager getInstance() {
        return _instance;
    }

    @Deprecated
    public List<String> getSortedDialogNames() {
        return _dialogManager.getSortedDialogNames();
    }

    public void removeDialog(String dialogName) {
        _dialogManager.removeDialog(dialogName);

    }

    public void hideSoftKeyBoard(View triggeringView) {
        InputMethodManager imm = (InputMethodManager) triggeringView.getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(triggeringView.getWindowToken(), 0);
    }

    public void showSoftKeyBoard(View triggeringView) {
        InputMethodManager imm = (InputMethodManager) triggeringView.getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    }

    /**
     * Method can be used to manually request an orientation
     * @param orientation use {@link ActivityInfo} to set your requested orientation.
     */
    public void setOrientation(int orientation) {
        Log.d(Constants.APPLICATION_NAME, "MBViewManager.setOrientation: Changing to " + orientation);
        setRequestedOrientation(orientation);
    }

    public void setOrientation(MBPage page) {

        MBPage.OrientationPermission orientationPermissions = page.getOrientationPermissions();

        /*
         *  If no orientation permissions have been set on a Page level we want to use the permission that is defined in the the AndroidManifest.xml (if any)
         */
        if (orientationPermissions == MBPage.OrientationPermission.UNDEFINED) {
            if (_defaultScreenOrientation != getRequestedOrientation()) {
                setRequestedOrientation(_defaultScreenOrientation);
            }

        } else if (orientationPermissions == MBPage.OrientationPermission.ANY) {
            if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
                Log.d(Constants.APPLICATION_NAME, "MBViewManager.setOrientation: Changing to SENSOR");
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
            }
        } else if (orientationPermissions == OrientationPermission.PORTRAIT) {
            Log.d(Constants.APPLICATION_NAME, "MBViewManager.setOrientation: Changing to PORTRAIT");
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else if (orientationPermissions == OrientationPermission.LANDSCAPE) {
            Log.d(Constants.APPLICATION_NAME, "MBViewManager.setOrientation: Changing to LANDSCAPE");
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Log.d(Constants.APPLICATION_NAME, "MBViewManager.onConfigurationChanged");

        invalidateActionBar();

        super.onConfigurationChanged(newConfig);

        _dialogManager.onConfigurationChanged(newConfig);
    }

    public List<MBBasicViewController> getAllFragments() {
        List<MBBasicViewController> list = new ArrayList<MBBasicViewController>();
        // Walk trough all dialogControllers
        for (MBDialogController dc : _dialogManager.getDialogs()) {

            //TODO Duplicaten er nog eens uit halen.
            if (dc != null && !dc.getAllFragments().isEmpty())
                list.addAll(dc.getAllFragments());
        }

        return list;
    }

    @Override
    public void setTitle(CharSequence title) {
        CharSequence titleToSet = null;
        if (isShowDialogTitle()) {
            titleToSet = title;
        }
        super.setTitle(titleToSet);
    }

    ////// Dialog management ////////

    public MBDialogController getActiveDialog() {
        return _dialogManager.getActiveDialog();
    }

    public boolean isShowDialogTitle() {
        return _showDialogTitle;
    }

    public void setShowDialogTitle(boolean showDialogTitle) {
        _showDialogTitle = showDialogTitle;
    }

    // Tablet specific methods. Some methods are implemented also to run on smartphone.
    // Others are for tablet only.

    public void invalidateActionBar() {
        invalidateActionBar(null);
    }

    /***
     * 
     * @param showFirst
     * 
     * @deprecated please use {@link #invalidateActionBar(EnumSet)}
     */
    @Deprecated
    public void invalidateActionBar(boolean showFirst) {
        EnumSet<MBActionBarInvalidationOption> options = EnumSet.noneOf(MBActionBarInvalidationOption.class);
        if (showFirst) {
            options.add(MBActionBarInvalidationOption.SHOW_FIRST);
        }

        invalidateActionBar(options);
    }

    /**
     * @param showFirst
     * @param notifyListener
     * 
     * @deprecated please use {@link #invalidateActionBar(EnumSet)}
     */
    @Deprecated
    public void invalidateActionBar(boolean showFirst, boolean notifyListener) {
        EnumSet<MBActionBarInvalidationOption> options = EnumSet.noneOf(MBActionBarInvalidationOption.class);
        if (showFirst) {
            options.add(MBActionBarInvalidationOption.SHOW_FIRST);
        }

        if (notifyListener) {
            options.add(MBActionBarInvalidationOption.NOTIFY_LISTENER);
        }

        invalidateActionBar(options);
    }

    /**
     * @param showFirst
     * @param notifyListener
     * @param resetHomeDialog
     * 
     * @deprecated please use {@link #invalidateActionBar(EnumSet)}
     */
    @Deprecated
    public void invalidateActionBar(boolean showFirst, boolean notifyListener, final boolean resetHomeDialog) {
        EnumSet<MBActionBarInvalidationOption> options = EnumSet.noneOf(MBActionBarInvalidationOption.class);
        if (showFirst) {
            options.add(MBActionBarInvalidationOption.SHOW_FIRST);
        }

        if (notifyListener) {
            options.add(MBActionBarInvalidationOption.NOTIFY_LISTENER);
        }

        if (resetHomeDialog) {
            options.add(MBActionBarInvalidationOption.RESET_HOME_DIALOG);
        }

        invalidateActionBar(options);
    }

    public void hideSearchView() {
        throw new UnsupportedOperationException("This method is not supported on smartphone");
    }

    public void reset() {
        _dialogManager.reset();
        MBApplicationController.getInstance().fireInitialOutcomes();
    }

    public MBDialogManager getDialogManager() {
        return _dialogManager;
    }

    public MBShutdownHandler getShutdownHandler() {
        return _shutdownHandler;
    }

    public void setShutdownHandler(MBShutdownHandler shutdownHandler) {
        _shutdownHandler = shutdownHandler;
    }

    /////// STUFF MERGED IN FROM MBNextGenViewManager ////////////

    private Menu _menu = null;

    private MBActionBarBuilder _actionBarBuilder;

    protected void onPreCreate() {
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    }

    private MBActionBarBuilder constructActionBarBuilder() {
        Class<? extends MBActionBarBuilder> customBuilder = MBApplicationFactory.getInstance()
                .getActionBarBuilder();
        try {

            if (customBuilder == null)
                return getDefaultActionBar();
            Constructor<? extends MBActionBarBuilder> constructor = customBuilder.getConstructor(Context.class);
            return constructor.newInstance(this);
        } catch (Exception e) {
            throw new MBException("Error instantiating " + customBuilder.getName() + " with constructor "
                    + customBuilder.getSimpleName() + "(Context)..", e);
        }
    }

    protected abstract MBActionBarBuilder getDefaultActionBar();

    protected boolean buildOptionsMenu(Menu menu) {
        _menu = menu;

        _actionBarBuilder.fillActionBar(getSupportActionBar(), menu);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            onHomeSelected();
            return true;
        }

        for (MBToolDefinition def : MBMetadataService.getInstance().getTools()) {
            if (item.getItemId() == def.getName().hashCode()) {
                if (def.getOutcomeName() != null) {
                    handleOutcome(def);
                    return true;
                }
                return false;
            }
        }

        return super.onOptionsItemSelected(item);
    }

    public void onHomeSelected() {
        if (_homeButtonHandler != null) {
            _homeButtonHandler.handleButton();
        }
    }

    protected void handleOutcome(MBToolDefinition def) {
        MBOutcome outcome = new MBOutcome();
        outcome.setOrigin(new MBOutcome.Origin().withAction(def.getName()));
        outcome.setOutcomeName(def.getOutcomeName());

        MBApplicationController.getInstance().handleOutcome(outcome);
    }

    @Override
    public void onDialogSelected(String dialogName) {
        if (dialogName != null) {
            _actionBarBuilder.selectTabWithoutReselection(dialogName);

        }

    }

    public void showProgressIndicatorInTool() {
        _actionBarBuilder.showProgressIndicatorInTool();
    }

    public void hideProgressIndicatorInTool() {
        _actionBarBuilder.hideProgressIndicatorInTool();
    }

    /***
     * @deprecated please use {@link com.itude.mobile.mobbl.core.configuration.MBConditionalDefinition#isPreConditionValid()
     * 
     * @param def
     * @return
     */
    @Deprecated
    protected final boolean isPreConditionValid(MBToolDefinition def) {
        if (def.getPreCondition() == null) {
            return true;
        }

        MBDocument doc = MBDataManagerService.getInstance()
                .loadDocument(MBConfigurationDefinition.DOC_SYSTEM_EMPTY);

        String result = doc.evaluateExpression(def.getPreCondition());
        Boolean bool = MBParseUtil.strictBooleanValue(result);
        if (bool != null)
            return bool;
        String msg = "Expression of tool with name=" + def.getName() + " precondition=" + def.getPreCondition()
                + " is not boolean (result=" + result + ")";
        throw new MBExpressionNotBooleanException(msg);
    }

    protected Menu getMenu() {
        return _menu;
    }

    public void invalidateActionBar(EnumSet<MBActionBarInvalidationOption> flags) {
        _actionBarBuilder.invalidateActionBar(flags);
    }

    public void setHomeButtonHandler(HomeButtonHandler handler) {
        _homeButtonHandler = handler;
    }

    public void resetDefaultHomeButtonHandler() {
        _homeButtonHandler = new DefaultHomeButtonHandler();
    }

    public static interface HomeButtonHandler {
        public void handleButton();
    }
}