fr.cobaltians.cobalt.Cobalt.java Source code

Java tutorial

Introduction

Here is the source code for fr.cobaltians.cobalt.Cobalt.java

Source

/**
 *
 * Cobalt
 * Cobalt
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Cobaltians
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission 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 fr.cobaltians.cobalt;

import fr.cobaltians.cobalt.activities.CobaltActivity;
import fr.cobaltians.cobalt.fragments.CobaltFragment;
import fr.cobaltians.cobalt.plugin.CobaltAbstractPlugin;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.Log;

import java.io.*;
import java.util.HashMap;
import java.util.Iterator;

import junit.framework.Assert;

import org.json.JSONException;
import org.json.JSONObject;

public class Cobalt {

    // TAG
    public static final String TAG = Cobalt.class.getSimpleName();

    // DEBUG
    public static boolean DEBUG = true;

    // RESOURCES
    private static final String ASSETS_PATH = "file:///android_asset/";

    // INFINITE SCROLL
    public static final int INFINITE_SCROLL_OFFSET_DEFAULT_VALUE = 0;

    /**********************************************************************************************
     * CONFIGURATION FILE
     **********************************************************************************************/

    private final static String CONF_FILE = "cobalt.conf";
    private final static String kControllers = "controllers";
    private final static String kPlugins = "plugins";
    private final static String kAndroid = "android";
    private final static String kDefaultController = "default";
    // TODO: uncomment for Bars
    /*
    public final static String kBars = "bars";
    public final static String kVisible = "visible";
    public final static String kBackgroundColor = "backgroundColor";
    public final static String kIcon = "androidIcon";
    public final static String kTitle = "title";
    public final static String kActions = "actions";
    public final static String kName = "name";
    public final static String kPosition = "androidPosition";
    public final static String kPositionOverflow = "overflow";
    public final static String kPositionTop = "top";
    public final static String kPositionBottom = "bottom";
    */
    public final static String kExtras = "extras";
    public final static String kPage = "page";
    public final static String kActivity = "activity";
    public final static String kPopAsModal = "popAsModal";
    public final static String kPushAsModal = "pushAsModal";
    public final static String kPullToRefresh = "pullToRefresh";
    public final static String kInfiniteScroll = "infiniteScroll";
    public final static String kInfiniteScrollOffset = "infiniteScrollOffset";
    public final static String kSwipe = "swipe";

    /**********************************************************************************************
     * JS KEYWORDS
     **********************************************************************************************/

    // GENERAL
    public final static String kJSAction = "action";
    public final static String kJSCallback = "callback";
    public final static String kJSData = "data";
    public final static String kJSMessage = "message";
    public final static String kJSPage = "page";
    public final static String kJSType = "type";
    public final static String kJSValue = "value";
    public final static String kJSVersion = "version";

    // CALLBACKS
    public final static String JSTypeCallBack = "callback";

    // COBALT IS READY
    public final static String JSTypeCobaltIsReady = "cobaltIsReady";

    // EVENTS
    public final static String JSTypeEvent = "event";
    public final static String kJSEvent = "event";

    // APP EVENTS
    public final static String JSEventOnAppStarted = "onAppStarted";
    public final static String JSEventOnAppBackground = "onAppBackground";
    public final static String JSEventOnAppForeground = "onAppForeground";
    public final static String JSEventOnPageShown = "onPageShown";

    // INTENT
    public final static String JSTypeIntent = "intent";
    public final static String JSActionIntentOpenExternalUrl = "openExternalUrl";
    public final static String kJSUrl = "url";

    // LOG
    public final static String JSTypeLog = "log";

    // NAVIGATION
    public final static String JSTypeNavigation = "navigation";
    public final static String JSActionNavigationPush = "push";
    public final static String JSActionNavigationPop = "pop";
    public final static String JSActionNavigationModal = "modal";
    public final static String JSActionNavigationDismiss = "dismiss";
    public final static String JSActionNavigationReplace = "replace";
    public final static String kJSController = "controller";
    public final static String kJSAnimated = "animated";

    // BACK BUTTON
    public final static String JSEventOnBackButtonPressed = "onBackButtonPressed";
    public final static String JSCallbackOnBackButtonPressed = "onBackButtonPressed";

    // UI
    public final static String JSTypeUI = "ui";
    public final static String kJSUIControl = "control";

    // ALERT
    public final static String JSControlAlert = "alert";
    public final static String kJSAlertTitle = "title";
    public final static String kJSAlertButtons = "buttons";
    public final static String kJSAlertCancelable = "cancelable";
    public final static String kJSAlertButtonIndex = "index";

    // TODO: uncomment for Bars
    // BARS
    /*
    public final static String JSControlBars = "bars";
    public final static String JSActionButtonPressed = "buttonPressed";
    public final static String kJSBarsButton = "button";
    */

    // DATE PICKER
    public static final String JSControlPicker = "picker";
    public static final String JSPickerDate = "date";
    public static final String kJSDate = "date";
    public static final String kJSDay = "day";
    public static final String kJSMonth = "month";
    public static final String kJSYear = "year";
    public static final String kJSTexts = "texts";
    public static final String kJSTitle = "title";
    public static final String kJSCancel = "cancel";
    //public static final String kJSDelete = "delete";
    public static final String kJSClear = "clear";
    public static final String kJSValidate = "validate";

    // TOAST
    public final static String JSControlToast = "toast";

    // WEB LAYER
    public final static String JSTypeWebLayer = "webLayer";
    public final static String JSActionWebLayerShow = "show";
    public final static String JSActionWebLayerDismiss = "dismiss";
    public final static String kJSWebLayerFadeDuration = "fadeDuration";
    public final static String JSEventWebLayerOnDismiss = "onWebLayerDismissed";

    // PULL TO REFRESH
    public final static String JSEventPullToRefresh = "pullToRefresh";
    public final static String JSCallbackPullToRefreshDidRefresh = "pullToRefreshDidRefresh";

    // INFINITE SCROLL
    public final static String JSEventInfiniteScroll = "infiniteScroll";
    public final static String JSCallbackInfiniteScrollDidRefresh = "infiniteScrollDidRefresh";

    //PLUGIN
    public final static String JSTypePlugin = "plugin";
    public final static String kJSPluginName = "name";

    /**********************************************************************************************
     * MEMBERS
     **********************************************************************************************/

    private static Cobalt sInstance;
    private static Context mContext;

    private String mResourcePath = "www/";

    private int mRunningActivities = 0;
    private boolean mFirstActivityStart = true;

    /**********************************************************************************************
     * CONSTRUCTORS
     **********************************************************************************************/

    private Cobalt(Context context) {
        mContext = context.getApplicationContext();
    }

    public static Cobalt getInstance(Context context) {
        if (sInstance == null) {
            Assert.assertNotNull(TAG + " - getInstance: context could not be null", context);
            sInstance = new Cobalt(context);
        }

        return sInstance;
    }

    /**********************************************************************************************
     * GETTERS / SETTERS
     **********************************************************************************************/

    public String getResourcePath() {
        return ASSETS_PATH + mResourcePath;
    }

    public void setResourcePath(String resourcePath) {
        if (resourcePath != null)
            mResourcePath = resourcePath;
        else
            mResourcePath = "";
    }

    public static Context getAppContext() {
        return mContext;
    }

    /**********************************************************************************************
     * APP LIFECYCLE
     **********************************************************************************************/

    public void onActivityStarted(CobaltActivity activity) {
        if (++mRunningActivities == 1) {
            if (mFirstActivityStart) {
                mFirstActivityStart = false;

                activity.onAppStarted();
            } else
                activity.onAppForeground();
        }
    }

    public void onActivityStopped(CobaltActivity activity) {
        if (--mRunningActivities == 0)
            activity.onAppBackground();
    }

    /**********************************************************************************************
     * CONFIGURATION FILE
     **********************************************************************************************/

    public CobaltFragment getFragmentForController(Class<?> CobaltFragmentClass, String controller, String page) {
        CobaltFragment fragment = null;

        try {
            if (CobaltFragment.class.isAssignableFrom(CobaltFragmentClass)) {
                fragment = (CobaltFragment) CobaltFragmentClass.newInstance();
                Bundle configuration = getConfigurationForController(controller);
                configuration.putString(kPage, page);
                fragment.setArguments(configuration);
            } else if (Cobalt.DEBUG)
                Log.e(Cobalt.TAG, TAG + " - getFragmentForController: " + CobaltFragmentClass.getSimpleName()
                        + " does not inherit from CobaltFragment!");
        } catch (java.lang.InstantiationException exception) {
            if (Cobalt.DEBUG)
                Log.e(Cobalt.TAG, TAG + " - getFragmentForController: InstantiationException");
            exception.printStackTrace();
        } catch (IllegalAccessException exception) {
            if (Cobalt.DEBUG)
                Log.e(Cobalt.TAG, TAG + " - getFragmentForController: IllegalAccessException");
            exception.printStackTrace();
        }

        return fragment;
    }

    public Intent getIntentForController(String controller, String page) {
        Intent intent = null;

        Bundle configuration = getConfigurationForController(controller);

        if (!configuration.isEmpty()) {
            String activity = configuration.getString(kActivity);

            // Creates intent
            Class<?> pClass;
            try {
                pClass = Class.forName(activity);
                // Instantiates intent only if class inherits from Activity
                if (Activity.class.isAssignableFrom(pClass)) {
                    configuration.putString(kPage, page);

                    intent = new Intent(mContext, pClass);
                    intent.putExtra(kExtras, configuration);
                } else if (Cobalt.DEBUG)
                    Log.e(Cobalt.TAG,
                            TAG + " - getIntentForController: " + activity + " does not inherit from Activity!");
            } catch (ClassNotFoundException exception) {
                if (Cobalt.DEBUG)
                    Log.e(Cobalt.TAG, TAG + " - getIntentForController: " + activity + " class not found for id "
                            + controller + "!");
                exception.printStackTrace();
            }
        }

        return intent;
    }

    private Bundle getConfigurationForController(String controller) {
        Bundle bundle = new Bundle();

        JSONObject configuration = getConfiguration();

        // Gets configuration
        try {
            JSONObject controllers = configuration.getJSONObject(kControllers);

            String activity;
            // TODO: uncomment for Bars
            //JSONObject actionBar;
            boolean enablePullToRefresh;
            boolean enableInfiniteScroll;
            int infiniteScrollOffset;
            // TODO: add enableGesture

            if (controller != null && controllers.has(controller)) {
                activity = controllers.getJSONObject(controller).getString(kAndroid);
                //actionBar = controllers.getJSONObject(controller).optJSONObject(kBars);
                enablePullToRefresh = controllers.getJSONObject(controller).optBoolean(kPullToRefresh);
                enableInfiniteScroll = controllers.getJSONObject(controller).optBoolean(kInfiniteScroll);
                infiniteScrollOffset = controllers.getJSONObject(controller).optInt(kInfiniteScrollOffset,
                        INFINITE_SCROLL_OFFSET_DEFAULT_VALUE);
            } else {
                activity = controllers.getJSONObject(kDefaultController).getString(kAndroid);
                //actionBar = controllers.getJSONObject(kDefaultController).optJSONObject(kBars);
                enablePullToRefresh = controllers.getJSONObject(kDefaultController).optBoolean(kPullToRefresh);
                enableInfiniteScroll = controllers.getJSONObject(kDefaultController).optBoolean(kInfiniteScroll);
                infiniteScrollOffset = controllers.getJSONObject(kDefaultController).optInt(kInfiniteScrollOffset,
                        INFINITE_SCROLL_OFFSET_DEFAULT_VALUE);
            }

            bundle.putString(kActivity, activity);
            //if (actionBar != null) bundle.putString(kBars, actionBar.toString());
            bundle.putBoolean(kPullToRefresh, enablePullToRefresh);
            bundle.putBoolean(kInfiniteScroll, enableInfiniteScroll);
            bundle.putInt(kInfiniteScrollOffset, infiniteScrollOffset);

            return bundle;
        } catch (JSONException exception) {
            if (Cobalt.DEBUG)
                Log.e(Cobalt.TAG,
                        TAG + " - getConfigurationForController: check cobalt.conf. Known issues: \n "
                                + "\t - controllers field not found or not a JSONObject \n " + "\t - " + controller
                                + " controller not found and no " + kDefaultController + " controller defined \n "
                                + "\t - " + controller + " or " + kDefaultController + "controller found but no "
                                + kAndroid + "defined \n ");
            exception.printStackTrace();
        }

        return bundle;
    }

    /**********************************************************************************************
     * PLUGINS FILE
     **********************************************************************************************/

    public HashMap<String, Class<? extends CobaltAbstractPlugin>> getPlugins() {
        HashMap<String, Class<? extends CobaltAbstractPlugin>> pluginsMap = new HashMap<String, Class<? extends CobaltAbstractPlugin>>();

        try {
            JSONObject configuration = getConfiguration();
            JSONObject plugins = configuration.getJSONObject(kPlugins);
            Iterator<String> pluginsIterator = plugins.keys();

            while (pluginsIterator.hasNext()) {
                String pluginName = pluginsIterator.next();
                try {
                    JSONObject plugin = plugins.getJSONObject(pluginName);
                    String pluginClassName = plugin.getString(kAndroid);

                    try {
                        Class<?> pluginClass = Class.forName(pluginClassName);
                        if (CobaltAbstractPlugin.class.isAssignableFrom(pluginClass)) {
                            pluginsMap.put(pluginName, (Class<? extends CobaltAbstractPlugin>) pluginClass);
                        } else if (Cobalt.DEBUG)
                            Log.e(Cobalt.TAG,
                                    TAG + " - getPlugins: " + pluginClass
                                            + " does not inherit from CobaltAbstractActivity!\n" + pluginName
                                            + " plugin message will not be processed.");
                    } catch (ClassNotFoundException exception) {
                        if (Cobalt.DEBUG) {
                            Log.e(Cobalt.TAG, TAG + " - getPlugins: " + pluginClassName + " class not found!\n"
                                    + pluginName + " plugin message will not be processed.");
                            exception.printStackTrace();
                        }
                    }
                } catch (JSONException exception) {
                    if (Cobalt.DEBUG) {
                        Log.e(Cobalt.TAG, TAG + " - getPlugins: " + pluginName
                                + " field is not a JSONObject or does not contain an android field or is not a String.\n"
                                + pluginName + " plugin message will not be processed.");
                        exception.printStackTrace();
                    }
                }
            }
        } catch (JSONException exception) {
            if (Cobalt.DEBUG) {
                Log.w(Cobalt.TAG,
                        TAG + " - getPlugins: plugins field of cobalt.conf not found or not a JSONObject.");
                exception.printStackTrace();
            }
        }

        return pluginsMap;
    }

    /**********************************************************************************************
     * HELPER METHODS
     **********************************************************************************************/

    private JSONObject getConfiguration() {
        String configuration = readFileFromAssets(mResourcePath + CONF_FILE);

        try {
            return new JSONObject(configuration);
        } catch (JSONException exception) {
            if (Cobalt.DEBUG)
                Log.e(Cobalt.TAG, TAG + " - getConfiguration: check cobalt.conf. File is missing or not at "
                        + ASSETS_PATH + mResourcePath + CONF_FILE);
            exception.printStackTrace();
        }

        return new JSONObject();
    }

    private String readFileFromAssets(String file) {
        try {
            AssetManager assetManager = mContext.getAssets();
            InputStream inputStream = assetManager.open(file);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder fileContent = new StringBuilder();
            int character;

            while ((character = bufferedReader.read()) != -1) {
                fileContent.append((char) character);
            }

            return fileContent.toString();
        } catch (FileNotFoundException exception) {
            if (Cobalt.DEBUG)
                Log.e(Cobalt.TAG, TAG + " - readFileFromAssets: " + file + "not found.");
        } catch (IOException exception) {
            if (Cobalt.DEBUG)
                Log.e(Cobalt.TAG, TAG + " - readFileFromAssets: IOException");
            exception.printStackTrace();
        }

        return "";
    }
}