com.facebook.internal.FacebookDialogBase.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.internal.FacebookDialogBase.java

Source

/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
 * copy, modify, and distribute this software in source code or binary form for use
 * in connection with the web services and APIs provided by Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use of
 * this software is subject to the Facebook Developer Principles and Policies
 * [http://developers.facebook.com/policy/]. This copyright notice shall be
 * included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package com.facebook.internal;

import android.app.Activity;
import android.support.v4.app.Fragment;
import android.util.Log;

import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookDialog;
import com.facebook.FacebookException;
import com.facebook.FacebookSdk;

import java.util.List;

/**
 * com.facebook.internal is solely for the use of other packages within the Facebook SDK for
 * Android. Use of any of the classes in this package is unsupported, and they may be modified or
 * removed without warning at any time.
 */
public abstract class FacebookDialogBase<CONTENT, RESULT> implements FacebookDialog<CONTENT, RESULT> {

    private static final String TAG = "FacebookDialog";

    protected static final Object BASE_AUTOMATIC_MODE = new Object();

    private final Activity activity;
    private final Fragment fragment;
    private List<ModeHandler> modeHandlers;
    private int requestCode;

    protected FacebookDialogBase(final Activity activity, int requestCode) {
        Validate.notNull(activity, "activity");
        this.activity = activity;
        this.fragment = null;
        this.requestCode = requestCode;
    }

    protected FacebookDialogBase(final Fragment fragment, int requestCode) {
        Validate.notNull(fragment, "fragment");
        this.fragment = fragment;
        this.activity = null;
        this.requestCode = requestCode;

        if (fragment.getActivity() == null) {
            throw new IllegalArgumentException("Cannot use a fragment that is not attached to an activity");
        }
    }

    @Override
    public final void registerCallback(final CallbackManager callbackManager,
            final FacebookCallback<RESULT> callback) {
        if (!(callbackManager instanceof CallbackManagerImpl)) {
            throw new FacebookException("Unexpected CallbackManager, " + "please use the provided Factory.");
        }
        registerCallbackImpl((CallbackManagerImpl) callbackManager, callback);
    }

    @Override
    public final void registerCallback(final CallbackManager callbackManager,
            final FacebookCallback<RESULT> callback, final int requestCode) {
        setRequestCode(requestCode);
        registerCallback(callbackManager, callback);
    }

    protected abstract void registerCallbackImpl(final CallbackManagerImpl callbackManager,
            final FacebookCallback<RESULT> callback);

    /**
     * Set the request code for the startActivityForResult call. The requestCode should be
     * outside of the range of those reserved for the Facebook SDK
     * {@link com.facebook.FacebookSdk#isFacebookRequestCode(int)}.
     *
     * @param requestCode the request code to use.
     */
    protected void setRequestCode(int requestCode) {
        if (FacebookSdk.isFacebookRequestCode(requestCode)) {
            throw new IllegalArgumentException(
                    "Request code " + requestCode + " cannot be within the range reserved by the Facebook SDK.");
        }
        this.requestCode = requestCode;
    }

    /**
     * Returns the request code used for this dialog.
     *
     * @return the request code.
     */
    public int getRequestCode() {
        return requestCode;
    }

    @Override
    public boolean canShow(CONTENT content) {
        return canShowImpl(content, BASE_AUTOMATIC_MODE);
    }

    // Pass in BASE_AUTOMATIC_MODE when Automatic mode choice is desired
    protected boolean canShowImpl(CONTENT content, Object mode) {
        boolean anyModeAllowed = (mode == BASE_AUTOMATIC_MODE);

        for (ModeHandler handler : cachedModeHandlers()) {
            if (!anyModeAllowed && !Utility.areObjectsEqual(handler.getMode(), mode)) {
                continue;
            }
            if (handler.canShow(content)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public void show(final CONTENT content) {
        showImpl(content, BASE_AUTOMATIC_MODE);
    }

    // Pass in BASE_AUTOMATIC_MODE when Automatic mode choice is desired
    protected void showImpl(final CONTENT content, final Object mode) {
        AppCall appCall = createAppCallForMode(content, mode);
        if (appCall != null) {
            if (fragment != null) {
                DialogPresenter.present(appCall, fragment);
            } else {
                DialogPresenter.present(appCall, activity);
            }
        } else {
            // If we got a null appCall, then the derived dialog code is doing something wrong
            String errorMessage = "No code path should ever result in a null appCall";
            Log.e(TAG, errorMessage);
            if (FacebookSdk.isDebugEnabled()) {
                throw new IllegalStateException(errorMessage);
            }
        }
    }

    protected Activity getActivityContext() {
        if (activity != null) {
            return activity;
        }

        if (fragment != null) {
            return fragment.getActivity();
        }

        return null;
    }

    private AppCall createAppCallForMode(final CONTENT content, final Object mode) {
        boolean anyModeAllowed = (mode == BASE_AUTOMATIC_MODE);

        AppCall appCall = null;
        for (ModeHandler handler : cachedModeHandlers()) {
            if (!anyModeAllowed && !Utility.areObjectsEqual(handler.getMode(), mode)) {
                continue;
            }
            if (!handler.canShow(content)) {
                continue;
            }

            try {
                appCall = handler.createAppCall(content);
            } catch (FacebookException e) {
                appCall = createBaseAppCall();
                DialogPresenter.setupAppCallForValidationError(appCall, e);
            }
            break;
        }

        if (appCall == null) {
            appCall = createBaseAppCall();
            DialogPresenter.setupAppCallForCannotShowError(appCall);
        }

        return appCall;
    }

    private List<ModeHandler> cachedModeHandlers() {
        if (modeHandlers == null) {
            modeHandlers = getOrderedModeHandlers();
        }

        return modeHandlers;
    }

    protected abstract List<ModeHandler> getOrderedModeHandlers();

    protected abstract AppCall createBaseAppCall();

    protected abstract class ModeHandler {
        /**
         * @return An object to signify a specific dialog-mode.
         */
        public Object getMode() {
            return BASE_AUTOMATIC_MODE;
        }

        public abstract boolean canShow(final CONTENT content);

        public abstract AppCall createAppCall(final CONTENT content);
    }
}