com.wit.and.dialog.manage.DialogFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.wit.and.dialog.manage.DialogFactory.java

Source

/*
 * =================================================================================
 * Copyright (C) 2013 Martin Albedinsky [Wolf-ITechnologies]
 * =================================================================================
 * Licensed under the Apache License, Version 2.0 or later (further "License" only);
 * ---------------------------------------------------------------------------------
 * You may use this file only in compliance with the License. More details and copy
 * of this License you may obtain at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 * You can redistribute, modify or publish any part of the code written in this
 * file but as it is described in the License, the software distributed under the 
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES or CONDITIONS OF
 * ANY KIND.
 * 
 * See the License for the specific language governing permissions and limitations
 * under the License.
 * =================================================================================
 */
package com.wit.and.dialog.manage;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.support.v4.app.DialogFragment;

import com.wit.and.dialog.Dialog;
import com.wit.and.dialog.Dialog.Buttons;
import com.wit.and.dialog.EditDialog;
import com.wit.and.dialog.IDialog;
import com.wit.and.dialog.ListDialog;
import com.wit.and.dialog.LoginDialog;
import com.wit.and.dialog.ProgressDialog;
import com.wit.and.dialog.WebDialog;

import java.util.ArrayList;
import java.util.List;

/**
 * <h4>Class Overview</h4>
 * <p>
 * Dialogs factory to handle creating instances of {@link com.wit.and.dialog.Dialog}.
 * Factory provides these instances for the {@link DialogManager} which provides
 * basic operations with dialog fragments (showing and dismissing).
 * </p>
 * <p>
 * <b>TAG</b><br/>
 * If you want to show more dialog fragments at the same time on the screen, you
 * must provide for these dialog instances different tags, because if you want
 * to show some dialog fragment but there is some right now showing and the new
 * one have the same tag, than the new one don't be showed. See
 * {@link #getDialogTag(int)}.
 * </p>
 * <p>
 * Factory also provides support methods to obtain all types of the useful
 * dialogs like {@link com.wit.and.dialog.WebDialog}, {@link com.wit.and.dialog.ProgressDialog}
 * and so on. The buttons type for these dialogs will be auto-resolved from the given
 * {@link com.wit.and.dialog.manage.DialogOptions}.
 * </p>
 *
 * @author Martin Albedinsky
 * @see DialogManager
 */
public abstract class DialogFactory implements DialogManager.IDialogFactory {
    /**
     * Constants =============================
     */

    /**
     * Log TAG.
     */
    // private static final String TAG = DialogFactory.class.getSimpleName();

    /**
     * Indicates if debug private output trough log-cat is enabled.
     */
    // private static final boolean DEBUG = true;

    /**
     * Indicates if logging for user output trough log-cat is enabled.
     */
    // private static final boolean USER_LOG = true;

    /**
     * Enums =================================
     */

    /**
     * Possible included dialog fragment implementation to create.
     */
    private enum DialogType {
        /**
         *
         */
        COMMON(0, Buttons.NONE),
        /**
         *
         */
        INFO(DialogOptions.DIALOG_ICON_INFO, Buttons.SINGLE),
        /**
         *
         */
        ALERT(DialogOptions.DIALOG_ICON_ALERT, Buttons.PAIR),
        /**
         *
         */
        ERROR(DialogOptions.DIALOG_ICON_ERROR, Buttons.SINGLE),
        /**
         *
         */
        PROGRESS(DialogOptions.DIALOG_ICON_PROGRESS, Buttons.NONE),
        /**
         *
         */
        WEB(DialogOptions.DIALOG_ICON_WEB, Buttons.SINGLE),
        /**
         *
         */
        LIST(DialogOptions.DIALOG_ICON_LIST, Buttons.SINGLE),
        /**
         *
         */
        SELECTION(0, Buttons.SINGLE),
        /**
         *
         */
        LOGIN(DialogOptions.DIALOG_ICON_LOGIN, Buttons.PAIR),
        /**
         *
         */
        EDIT(DialogOptions.DIALOG_ICON_EDIT, Buttons.PAIR);

        private final int defIcon;

        private final Buttons defButtons;

        private DialogType(int icon, Buttons buttons) {
            this.defIcon = icon;
            this.defButtons = buttons;
        }
    }

    /**
     * Static members ========================
     */

    /**
     * Members ===============================
     */

    /**
     * Application mResources to handle obtaining of strings and so on.
     */
    private Resources mResources;

    /**
     * Context in which is this factory placed.
     */
    private Context mContext;

    /**
     * Listeners -----------------------------
     */

    /**
     * Arrays --------------------------------
     */

    /**
     * Array with joined dialog factories. Instances and tags are first obtained
     * from these factories.
     */
    private List<DialogManager.IDialogFactory> aJoinedFactories = new ArrayList<DialogManager.IDialogFactory>();

    /**
     * Booleans ------------------------------
     */

    /**
     * Constructors ==========================
     */

    /**
     * <p>
     * Creates factory with the given context and accessible
     * application mResources.
     * </p>
     *
     * @param context {@link Activity} or {@link Context} are allowed.
     */
    public DialogFactory(Context context) {
        this.mContext = context;

        if (context != null) {
            this.mResources = context.getResources();
        }
    }

    /**
     * Methods ===============================
     */

    /**
     * Public --------------------------------
     */

    /**
     * <p>
     * Creates dialog tag in required format depends on the passed
     * <var>factory</var> package name and <var>dialogName</var>.
     * </p>
     * <p>
     * Example format: <u>com.android.app.dialog.factories.ScreenLoginFactory.ConfirmDialog.TAG</u><br/><br/>
     * - where <b>com.android.app.dialog.factories</b> is name of package where <var>factory</var> is placed,
     * <b>ScreenLoginFactory</b> is factory class name, <b>ConfirmDialog</b> is <var>dialogName</var> and
     * <b>TAG</b> is tag identifier.
     * </p>
     *
     * @param factoryClass Class of factory for which is creation of dialog tag requested.
     * @param dialogName   Dialog name (can be dialog class name) for which tag should be created.
     * @return Dialog tag in required format, or <code>null</code> if <var>dialogName</var> is <code>null</code> or empty.
     */
    public static String createDialogTag(Class<? extends DialogManager.IDialogFactory> factoryClass,
            String dialogName) {
        // Only valid dialog name is allowed.
        if (dialogName == null || dialogName.length() == 0) {
            return null;
        }
        return factoryClass.getPackage().getName() + "." + factoryClass.getSimpleName() + "." + dialogName + ".TAG";
    }

    /**
     * <p>
     * Same as {@link #dialog(DialogOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty
     * listeners.
     * </p>
     *
     * @param options Dialog options with dialog data.
     * @return New instance of {@link Dialog}.
     */
    public static Dialog dialog(DialogOptions options) {
        return dialog(options, new DialogManager.ListenerOptions());
    }

    /**
     * <p>
     * Returns new instance of the {@link Dialog}.
     * Dialog options will be created from the given fast options.
     * </p>
     *
     * @param options   Dialog options with dialog data.
     * @param listeners Set of listeners for requested dialog.
     * @return New instance of {@link Dialog}.
     */
    public static Dialog dialog(DialogOptions options, DialogManager.ListenerOptions listeners) {
        return createDialog(DialogType.COMMON, options, listeners);
    }

    /**
     * <p>
     * Same as {@link #info(DialogOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty
     * listeners.
     * </p>
     *
     * @param options Dialog options with dialog data.
     * @return New instance of {@link Dialog}.
     */
    public static Dialog info(DialogOptions options) {
        return info(options, new DialogManager.ListenerOptions());
    }

    /**
     * <p>
     * Returns new instance of the {@link Dialog} with info icon and neutral button.
     * Dialog options will be created from the given fast options.
     * </p>
     *
     * @param options   Dialog options with dialog data.
     * @param listeners Set of listeners for requested dialog.
     * @return New instance of {@link Dialog}.
     */
    public static Dialog info(DialogOptions options, DialogManager.ListenerOptions listeners) {
        return createDialog(DialogType.INFO, options, listeners);
    }

    /**
     * <p>
     * Same as {@link #alert(DialogOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty
     * listeners.
     * </p>
     *
     * @param options Dialog options with dialog data.
     * @return New instance of {@link Dialog}.
     */
    public static Dialog alert(DialogOptions options) {
        return alert(options, new DialogManager.ListenerOptions());
    }

    /**
     * <p>
     * Returns new instance of the {@link Dialog} wit alert icon and negative
     * + positive button. Dialog options will be created from the given fast options.
     * </p>
     *
     * @param options   Dialog options with dialog data.
     * @param listeners Set of listeners for requested dialog.
     * @return New instance of {@link Dialog}.
     */
    public static Dialog alert(DialogOptions options, DialogManager.ListenerOptions listeners) {
        return createDialog(DialogType.ALERT, options, listeners);
    }

    /**
     * <p>
     * Same as {@link #error(DialogOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty
     * listeners.
     * </p>
     *
     * @param options Dialog options with dialog data.
     * @return New instance of {@link Dialog}.
     */
    public static Dialog error(DialogOptions options) {
        return createDialog(DialogType.ERROR, options, new DialogManager.ListenerOptions());
    }

    /**
     * <p>
     * Returns new instance of the {@link Dialog} with error icon and neutral button.
     * Dialog options will be created from the given fast options.
     * </p>
     *
     * @param options   Dialog options with dialog data.
     * @param listeners Set of listeners for requested dialog.
     * @return New instance of {@link Dialog}.
     */
    public static Dialog error(DialogOptions options, DialogManager.ListenerOptions listeners) {
        return createDialog(DialogType.ERROR, options, listeners);
    }

    /**
     * <p>
     * Same as {@link #progress(ProgressDialog.ProgressOptions)}, where default
     * {@link com.wit.and.dialog.ProgressDialog.ProgressOptions} will be used and message will be included
     * into that options.
     * </p>
     * <p>
     * This actually shows the dialog with circle progress bar without title (booth icon and title text are
     * hided).
     * </p>
     *
     * @param message Message to show at the right of circle progress bar.
     * @return New instance of {@link com.wit.and.dialog.ProgressDialog} with circle progress bar.
     */
    public static ProgressDialog loading(String message) {
        return progress(new ProgressDialog.ProgressOptions().message(message).icon(0));
    }

    /**
     * <p>
     * Same as {@link #progress(ProgressDialog.ProgressOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with
     * empty listeners.
     * </p>
     *
     * @param progressOptions Progress options specific for progress dialog.
     * @return New instance of {@link ProgressDialog}.
     */
    public static ProgressDialog progress(ProgressDialog.ProgressOptions progressOptions) {
        return progress(progressOptions, new DialogManager.ListenerOptions());
    }

    /**
     * <p>
     * Returns new instance of the {@link ProgressDialog}. Dialog options will
     * be created from the given fast options.
     * </p>
     *
     * @param progressOptions Progress options specific for progress dialog.
     * @param listeners       Set of listeners for requested dialog.
     * @return New instance of {@link ProgressDialog}.
     */
    public static ProgressDialog progress(ProgressDialog.ProgressOptions progressOptions,
            DialogManager.ListenerOptions listeners) {
        // Prepare options for dialog and create and set-up new instance of dialog.
        final ProgressDialog dialog = ProgressDialog
                .newInstance(prepareOptions(DialogType.PROGRESS, progressOptions));
        // Resolve listeners and return.
        return DialogManager.resolveListeners(dialog, listeners);
    }

    /**
     * <p>
     * Same as {@link #list(ListDialog.ListOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)}, but with empty
     * listeners.
     * </p>
     *
     * @param listOptions List options specific for list dialog.
     * @return New instance of {@link ListDialog}.
     */
    public static ListDialog list(ListDialog.ListOptions listOptions) {
        return list(listOptions, new DialogManager.ListenerOptions());
    }

    /**
     * <p>
     * Returns new instance of the {@link ListDialog} with list icon and no button.
     * Dialog options will be created from the given fast options.
     * </p>
     *
     * @param listOptions List options specific for list dialog.
     * @param listeners   Set of listeners for requested dialog.
     * @return New instance of {@link ListDialog}.
     */
    public static ListDialog list(ListDialog.ListOptions listOptions, DialogManager.ListenerOptions listeners) {
        // Prepare options for dialog and create and set-up new instance of dialog.
        final ListDialog dialog = ListDialog.newInstance(prepareOptions(DialogType.LIST, listOptions));
        // Resolve listeners and return.
        return DialogManager.resolveListeners(dialog, listeners);
    }

    /**
     * <p>
     * Same as {@link #web(WebDialog.WebOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)},
     * but with empty listeners.
     * </p>
     *
     * @param webOptions Web options specific for web dialog.
     * @return New instance of {@link WebDialog}.
     */
    public static WebDialog web(WebDialog.WebOptions webOptions) {
        return web(webOptions, new DialogManager.ListenerOptions());
    }

    /**
     * <p>
     * Returns new instance of the {@link WebDialog} with web icon
     * and neutral button. Dialog options will be created from the given fast options.
     * </p>
     *
     * @param webOptions Web options specific for web dialog.
     * @param listeners  Set of listeners for requested dialog.
     * @return New instance of {@link WebDialog}.
     */
    public static WebDialog web(WebDialog.WebOptions webOptions, DialogManager.ListenerOptions listeners) {
        // Prepare options for dialog and create and set-up new instance of dialog.
        final WebDialog dialog = WebDialog.newInstance(prepareOptions(DialogType.WEB, webOptions));
        // Resolve listeners and return.
        return DialogManager.resolveListeners(dialog, listeners);
    }

    /**
     * <p>
     * Same as {@link #login(com.wit.and.dialog.LoginDialog.LoginOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)},
     * but with empty listeners.
     * </p>
     *
     * @param loginOptions Login options specific for login dialog.
     * @return New instance of {@link com.wit.and.dialog.LoginDialog}.
     */
    public static Dialog login(LoginDialog.LoginOptions loginOptions) {
        return login(loginOptions, new DialogManager.ListenerOptions());
    }

    /**
     * <p>
     * Returns new instance of the {@link LoginDialog} with login
     * icon and negative + positive button.
     * </p>
     *
     * @param loginOptions Login options specific for login dialog.
     * @param listeners    Set of listeners for requested dialog.
     * @return New instance of {@link LoginDialog}.
     */
    public static LoginDialog login(LoginDialog.LoginOptions loginOptions,
            DialogManager.ListenerOptions listeners) {
        // Prepare options for dialog and create and set-up new instance of dialog.
        final LoginDialog dialog = LoginDialog.newInstance(prepareOptions(DialogType.LOGIN, loginOptions));
        // Resolve listeners and return.
        return DialogManager.resolveListeners(dialog, listeners);
    }

    /**
     * <p>
     * Same as {@link #edit(com.wit.and.dialog.EditDialog.EditOptions, com.wit.and.dialog.manage.DialogManager.ListenerOptions)},
     * but with empty listeners.
     * </p>
     *
     * @param editOptions Edit options specific for login dialog.
     * @return New instance of {@link com.wit.and.dialog.EditDialog}.
     */
    public static EditDialog edit(EditDialog.EditOptions editOptions) {
        return edit(editOptions, new DialogManager.ListenerOptions());
    }

    /**
      * <p>
      * Returns new instance of the {@link EditDialog} with edit
      * icon and negative + positive button.
      * </p>
      *
      * @param editOptions  Edit options specific for edit dialog.
      * @param listeners    Set of listeners for requested dialog.
      * @return New instance of {@link EditDialog}.
      */
    public static EditDialog edit(EditDialog.EditOptions editOptions, DialogManager.ListenerOptions listeners) {
        // Prepare options for dialog and create and set-up new instance of dialog.
        final EditDialog dialog = EditDialog.newInstance(prepareOptions(DialogType.EDIT, editOptions));
        // Resolve listeners and return.
        return DialogManager.resolveListeners(dialog, listeners);
    }

    /**
     */
    @Override
    public DialogFragment createDialogInstance(int dialogID, DialogOptions options) {
        DialogFragment dialog = null;

        // Try to obtain dialog fragment from the joined factories.
        for (DialogManager.IDialogFactory factory : aJoinedFactories) {
            dialog = factory.createDialogInstance(dialogID, options);
            if (dialog != null)
                break;
        }

        if (dialog == null) {
            // Get dialog from this factory.
            dialog = onCreateDialogInstance(dialogID, options);
        }

        // Set up dialog id.
        if (dialog != null && dialog instanceof IDialog) {
            // Set dialog id. This id is fired with the dialog callback.
            ((IDialog) dialog).setDialogID(dialogID);
        }
        return dialog;
    }

    /**
     */
    @Override
    public String getDialogTag(int dialogID) {
        String tag = null;

        // Try to obtain tag from the joined factories.
        for (DialogManager.IDialogFactory factory : aJoinedFactories) {
            tag = factory.getDialogTag(dialogID);
            if (tag != null)
                break;
        }
        return (tag != null && tag.length() > 0) ? tag : onGetDialogTag(dialogID);
    }

    /**
     * Getters + Setters ---------------------
     */

    /**
     * Protected -----------------------------
     */

    /**
     * <p>
     * Joins the given dialog factory with this current one. <b>Note</b>, that
     * dialog fragment instances (and their tags) are obtained from these joined
     * libraries in order as they was joined.
     * </p>
     *
     * @param factory Dialog factory to join with.
     */
    protected final void joinFactory(DialogManager.IDialogFactory factory) {
        if (!aJoinedFactories.contains(factory)) {
            aJoinedFactories.add(factory);
        }
    }

    /**
     * <p>
     * Returns array with currently joined dialog factories to this one.
     * </p>
     *
     * @return Set of factories.
     */
    protected final List<DialogManager.IDialogFactory> getJoinedFactories() {
        return aJoinedFactories;
    }

    /**
     * <p>
     * Returns actual application mResources.
     * </p>
     *
     * @return Resources.
     */
    protected final Resources getResources() {
        return mResources;
    }

    /**
     * <p>
     * Returns string from the application mResources.
     * </p>
     *
     * @param stringResID Resource of string to obtain.
     * @return Obtained string from application mResources.
     */
    protected final String getString(int stringResID) {
        return this.mResources.getString(stringResID);
    }

    /**
     * <p>
     * Returns context with which was this factory created.
     * </p>
     *
     * @return Can be {@link Activity} or {@link Context}.
     */
    protected final Context getContext() {
        return mContext;
    }

    /**
     * Resolves the buttons type.
     *
     * @param options     Dialog options.
     * @return Given dialog options with resolved buttons type.
     */
    static <O extends DialogOptions> O resolveButtons(O options) {
        String negative, neutral, positive;

        negative = options.getNegative();
        neutral = options.getNeutral();
        positive = options.getPositive();

        int typeOrdinal = Buttons.DEFAULT.ordinal();
        if (negative == null && neutral == null && positive == null) {
            // There will be no button showed in the dialog.
            typeOrdinal = Buttons.NONE.ordinal();
        } else {
            // Check for text values and resolve type of buttons.
            typeOrdinal = (negative == null || negative.length() == 0) ? typeOrdinal : ++typeOrdinal;
            typeOrdinal = (neutral == null || neutral.length() == 0) ? typeOrdinal : ++typeOrdinal;
            typeOrdinal = (positive == null || positive.length() == 0) ? typeOrdinal : ++typeOrdinal;
        }
        // Set up type.
        options.buttonsType(Buttons.values()[typeOrdinal]);
        return options;
    }

    /**
     * Private -------------------------------
     */

    /**
     * Creates new instance of the dialog depends on the given type.
     * Created instance of dialog will be fully set-upped and ready to show.
     *
     * @param type        Dialog type.
     * @param options Fast dialog options.
     * @param listeners   Set of listeners for requested dialog.
     * @return New instance of {@link Dialog}.
     */
    private static Dialog createDialog(DialogType type, DialogOptions options,
            DialogManager.ListenerOptions listeners) {
        // Prepare options for dialog and create and set-up new instance of dialog.
        final Dialog dialog = Dialog.newInstance(prepareOptions(type, options));
        // Resolve listeners and return.
        return DialogManager.resolveListeners(dialog, listeners);
    }

    /**
     * Resolves buttons type and also resolves default set-up depends on the given dialog type.
     *
     * @param type        Dialog type.
     * @return New instance of dialog options.
     */
    private static <O extends DialogOptions> O prepareOptions(DialogType type, O options) {
        // Resolve buttons depends on the button text values.
        options = resolveButtons(options);
        // Resolve default set-ups and return.
        return resolveDefault(type, options);
    }

    /**
     * Resolves default icon and buttons type depends on the given dialog type.
     *
     * @param type    Dialog type.
     * @param options Dialog options.
     * @return Given dialog options with resolved default data for requested type.
     */
    private static <O extends DialogOptions> O resolveDefault(DialogType type, O options) {
        // There can be already set some custom buttons type or custom icon,
        // so we will override only that which are still at default value.

        // Resolve buttons.
        if (options.getButtonsType() == Buttons.DEFAULT) {
            options.buttonsType(type.defButtons);
        }

        // Resolve icon.
        if (options.getIcon() == -1) {
            options.icon(type.defIcon);
        }
        return options;
    }

    /**
     * Abstract methods ----------------------
     */

    /**
     * <p>
     * Invoked after call of <code>showDialog(int, ...)</code> from the
     * {@link DialogManager} and after iterations trough joined factories.
     * Implemented factory should here return instance of {@link DialogFragment}
     * assigned to requested <var>dialogID</var>. Here passed <var>options</var> can be
     * <code>null</code>, then default should be created and filled in the factory context.
     * </p>
     *
     * @param dialogID Id of dialog which was requested to show from dialog manger.
     * @param options  Dialog options from application context, or <code>null</code> if only
     *                 dialog with id was requested to show.
     * @return New instance of dialog fragment.
     */
    protected abstract DialogFragment onCreateDialogInstance(int dialogID, DialogOptions options);

    /**
     * <p>
     * Invoked to obtain tag for dialog fragment instance associated with the
     * given <var>dialogID</var>. If here provided tag is <code>null</code>,
     * default tag from {@link DialogManager} will be used to show actual dialog
     * </p>
     *
     * @param dialogID Id of dialog which was requested to show from dialog manger.
     * @return Tag for dialog.
     */
    protected abstract String onGetDialogTag(int dialogID);

    /**
     * Inner classes =========================
     */

    /**
     * Interface =============================
     */
}