com.jogden.spunkycharts.MainApplication.java Source code

Java tutorial

Introduction

Here is the source code for com.jogden.spunkycharts.MainApplication.java

Source

package com.jogden.spunkycharts;

/* 
Copyright (C) 2014 Jonathon Ogden     < jeog.dev@gmail.com >
    
This program 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 3 of the License, or
(at your option) any later version.
    
This program 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 this program.  If not, see http://www.gnu.org/licenses.
*/
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import com.jogden.spunkycharts.ApplicationPreferences.ChartPreferencesSetup;
import com.jogden.spunkycharts.animations.BaseSelectAnimationA;
import com.jogden.spunkycharts.data.DataContentService;
import com.jogden.spunkycharts.data.DataContentService.DataClientInterface;
import com.jogden.spunkycharts.misc.Pair;

import android.app.Activity;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.view.View;

public class MainApplication extends Application {
    static { /* our native lib */
        System.loadLibrary("SpunkyCharts");
    }

    /* a wrapper to interface popular findViewById method */
    public interface ViewFindable {
        public View findViewById(int id);
    }

    /* PRICE AXIS SCALE/INCREMENTS NATIVE SUB-ROUTINE: 
     * determines what increment values fit 'best. (see SpunkyCharts.cpp) */
    public static native float[] IncrementRegressNative(float adjRangeDiff, int maxNodes);

    @SuppressWarnings("serial")
    public static class AppNotReadyForDataException extends IllegalStateException {
        public AppNotReadyForDataException(String msg) {
            super(msg);
        }
    }

    @SuppressWarnings("serial")
    static public class InvalidChartManifestException extends XmlPullParserException {
        public InvalidChartManifestException(String msg) {
            super(msg);
        }
    }

    @SuppressWarnings("serial")
    public static final List<Class<?>> availablePanels = new ArrayList<Class<?>>() {
        {
            add(DockingPanelActivity.L2.class);
            add(DockingPanelActivity.L1.class);
            add(DockingPanelActivity.class);
            add(DockingPanelActivity.R1.class);
            add(DockingPanelActivity.R2.class);
        }
    };

    public static final int TMOVE_THRSHLD = 10;
    public static final int WIRELESS_SETTINGS_REQ = 101;
    public static final int UPDATE_PREFS_REQ = 102;

    private static MainApplication thisApp = null;
    private static LocalBroadcastManager ourBroadcastMngr = null;
    private static DataContentService ourDataService = null;
    private static ServiceConnection ourDataServiceConnection = null;

    public static volatile boolean readyForData = false;

    public static final Object currentDockingPanelMonitor = new Object();

    /* docking panel currently 'active' (onStart, onStop) */
    public static volatile Activity currentDockingPanel = null;
    public static Class<? extends DockingPanelActivity> currentDockingPanelActivity = null;

    /* all panels, active or in back stack */
    public static final List<DockingPanelActivity> dockingPanels = new ArrayList<DockingPanelActivity>();

    /* available chart type names and Fragment objects */
    public static final Map<String, Class<? extends BaseChartFragmentA>> metaChartTypes = new LinkedHashMap<String, Class<? extends BaseChartFragmentA>>();

    /* available chart selection animation names and Animation objects */
    public static final Map<String, Class<? extends BaseSelectAnimationA>> metaSelectAnimTypes = new LinkedHashMap<String, Class<? extends BaseSelectAnimationA>>();

    /* available data client names and implementations
     * currently we're just using the last added to this mapping  */
    public static final Map<String, Class<? extends DataClientInterface>> metaDataClients = new LinkedHashMap<String, Class<? extends DataClientInterface>>();

    public static LocalBroadcastManager getLocalBroadcastManager() {
        return ourBroadcastMngr;
    }

    public static MainApplication getInstance() {
        return thisApp;
    }

    public static DataContentService getDataService() {
        return ourDataService;
    }

    public static void setDataService(DataContentService service) {
        ourDataService = service;
    }

    public static boolean isDataServiceRunning() {
        return ourDataService != null;
    }

    public static void connectToDataService() {
        thisApp.bindService(new Intent(thisApp, DataContentService.class),
                ourDataServiceConnection = new ServiceConnection() {
                    public void onServiceConnected(ComponentName name, IBinder binder) {
                        ourDataService = ((DataContentService.OurBinder) binder).getService();
                        DataContentService.connect();
                    }

                    public void onServiceDisconnected(ComponentName name) {
                        ourDataService = null;
                    }
                }, Context.BIND_AUTO_CREATE);
        thisApp.startService(new Intent(thisApp, DataContentService.class));
    }

    public static void disconnectFromDataService() {
        if (ourDataService != null) {
            if (ourDataServiceConnection != null)
                thisApp.unbindService(ourDataServiceConnection);
            else
                throw new IllegalStateException(
                        "Failed to disconnect from data service, " + "ourDataServiceConnection is null.");
        }
    }

    @Override
    public final void onCreate() {
        super.onCreate();
        thisApp = this;
        /* DO NOT REFERENCE ApplicationPreferences BEFORE HERE- */
        ourBroadcastMngr = LocalBroadcastManager.getInstance(this);
        try { /* check chart manifest */
            _loadSpunkyManifest();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /* sub for extracting from chart_manifest.xml */
    @SuppressWarnings("unchecked")
    private final void _loadSpunkyManifest() throws XmlPullParserException, ClassNotFoundException,
            InstantiationException, IllegalAccessException, IOException {
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        XmlPullParser parser = factory.newPullParser();
        InputStream manifestStrm = getResources().openRawResource(R.raw.spunky_manifest);
        parser.setInput(manifestStrm, null);
        String name = null;
        String layName = null;
        String fragName = null;
        String prefsName = null;
        String className = null;
        Class<BaseChartFragmentA> fragCls = null;
        Class<ChartPreferencesSetup> prefCls = null;
        Class<BaseSelectAnimationA> animCls = null;
        Class<DataClientInterface> dataCls = null;
        Integer layId = 0;
        boolean validInner = false;
        int eType = parser.getEventType();
        while (eType != XmlPullParser.END_DOCUMENT) {
            if (eType == XmlPullParser.START_TAG) {
                if (parser.getName().equals("SpunkyManifest"))
                    validInner = true;
                name = null;
                fragName = null;
                prefsName = null;
                className = null;
                fragCls = null;
                prefCls = null;
                animCls = null;
                dataCls = null;
                layId = 0;
                if (validInner && parser.getName().equals("ChartType")) {
                    if ((name = parser.getAttributeValue(null, "name")) == null)
                        throw new InvalidChartManifestException("ChartType does not have a 'chartName' attr");
                    if ((fragName = parser.getAttributeValue(null, "fragName")) == null)
                        throw new InvalidChartManifestException(
                                "ChartType [" + name + "] does not have a 'fragName' attr");
                    else {
                        try {
                            fragCls = (Class<BaseChartFragmentA>) Class.forName(fragName);
                        } catch (Exception e) {
                            throw new InvalidChartManifestException(
                                    "fragName attr [ " + fragName + " ] is not a valid fully "
                                            + "qualifed name or derived class of BaseChartFragmentA");
                        }
                    }
                    if ((prefsName = parser.getAttributeValue(null, "prefsName")) == null)
                        throw new InvalidChartManifestException(
                                "ChartType [" + name + "] does not have a 'prefsName' attr ");
                    else {
                        try {
                            prefCls = (Class<ChartPreferencesSetup>) Class.forName(prefsName);
                        } catch (Exception e) {
                            throw new InvalidChartManifestException("prefsName attr [ " + prefsName
                                    + " ] is not a valid " + "fully qualifed name or implementation of "
                                    + "ApplicationPreferences.ChartPreferencesSetup");
                        }
                    }
                    if ((layName = parser.getAttributeValue(null, "layout")) == null)
                        throw new InvalidChartManifestException(
                                "ChartType [ " + name + " ] does not have a 'layout' attr ");
                    else {
                        try {
                            layId = getResources().getIdentifier(
                                    this.getPackageName() + ":" + layName.replace("@", ""), null, null);
                            if (layId == 0)
                                throw new Exception();
                        } catch (Exception e) {
                            throw new InvalidChartManifestException(
                                    "layout attr [" + layName + "] is not a valid layout " + "resource in the "
                                            + this.getPackageName() + " package");
                        }
                    }
                } else if (validInner && parser.getName().equals("DataClient")) {
                    if ((name = parser.getAttributeValue(null, "name")) == null)
                        throw new InvalidChartManifestException("DataClient does not have a 'name' attr");
                    if ((className = parser.getAttributeValue(null, "className")) == null)
                        throw new InvalidChartManifestException(
                                "DataClient [" + name + "] " + "does not have a 'className' attr ");
                    else {
                        try {
                            dataCls = (Class<DataClientInterface>) Class.forName(className);
                        } catch (Exception e) {
                            throw new InvalidChartManifestException(
                                    "className attr [" + className + "] is not a valid fully "
                                            + "qualifed name or implementation of DataClientInterface");
                        }
                    }
                } else if (validInner && parser.getName().equals("ChartSelectAnimation")) {
                    if ((name = parser.getAttributeValue(null, "name")) == null)
                        throw new InvalidChartManifestException("ChartSelectAnimation does not have a 'name' attr");
                    if ((className = parser.getAttributeValue(null, "className")) == null)
                        throw new InvalidChartManifestException(
                                "ChartSelectAnimation [" + name + "] " + "does not have a 'className' attr ");
                    else {
                        try {
                            animCls = (Class<BaseSelectAnimationA>) Class.forName(className);
                        } catch (Exception e) {
                            throw new InvalidChartManifestException(
                                    "className attr [" + className + "] is not a valid fully "
                                            + "qualifed name or derived class of BaseSelectAnimationA");
                        }
                    }
                }
            } else if (eType == XmlPullParser.END_TAG) {
                if (parser.getName().equals("SpunkyManifest"))
                    validInner = false;
                if (validInner && parser.getName().equals("ChartType")) {
                    metaChartTypes.put(name, fragCls);
                    ApplicationPreferences.metaChartPrefs.put(name,
                            new Pair<ChartPreferencesSetup, Integer>(prefCls.newInstance(), layId));
                } else if (validInner && parser.getName().equals("ChartSelectAnimation")) {
                    metaSelectAnimTypes.put(name, animCls);
                    //
                    //
                } else if (validInner && parser.getName().equals("DataClient")) {
                    metaDataClients.put(name, dataCls);
                    /* use the last provided (for now) */
                    DataContentService.setDataClientInterface(dataCls.newInstance());
                    //
                    //
                } else if (!validInner) {
                    int metaFrags = metaChartTypes.size();
                    int metaPrefs = ApplicationPreferences.metaChartPrefs.size();
                    int metaPrefLayIds = ApplicationPreferences.metaChartPrefs.size();
                    if (metaFrags != metaPrefs)
                        throw new InvalidChartManifestException(
                                "inconsistent fragment and preference entries (count)");
                    else if (metaPrefs != metaPrefLayIds)
                        throw new InvalidChartManifestException(
                                "inconsistent preference and preference " + "layout entries (count)");
                    else if (metaFrags == 0)
                        throw new InvalidChartManifestException("Spunky Charts requires at least one chart type.");
                    if (metaSelectAnimTypes.size() < 1)
                        throw new InvalidChartManifestException(
                                "Spunky Charts requires at least one Select Animation.");
                }
            }
            eType = parser.next();
        }
    }

}