net.naonedbus.provider.CustomContentProvider.java Source code

Java tutorial

Introduction

Here is the source code for net.naonedbus.provider.CustomContentProvider.java

Source

/**
 * Copyright (C) 2013 Romain Guefveneu.
 *   
 *  This file is part of naonedbus.
 *   
 *  Naonedbus 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.
 *  
 *  Naonedbus 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/>.
 */
package net.naonedbus.provider;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import net.naonedbus.BuildConfig;
import net.naonedbus.R;
import net.naonedbus.helper.BulkLoaderHelper.BulkQuery;
import net.naonedbus.helper.CompressedQueriesHelper;
import net.naonedbus.utils.TimeLogUtils;

import org.apache.commons.io.IOUtils;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.net.Uri;
import android.util.Log;

import com.bugsense.trace.BugSenseHandler;

public abstract class CustomContentProvider extends ContentProvider {

    private static CoreDatabase database;
    private static DatabaseActionObserver databaseActionListener;

    @Override
    public boolean onCreate() {
        synchronized (this) {
            if (database == null) {
                database = new CoreDatabase(getContext());
            }
        }
        return true;
    }

    @Override
    public abstract int delete(Uri uri, String selection, String[] selectionArgs);

    @Override
    public abstract String getType(Uri uri);

    @Override
    public abstract Uri insert(Uri uri, ContentValues values);

    @Override
    public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder);

    protected SQLiteDatabase getReadableDatabase() {
        return database.getReadableDatabase();
    }

    protected SQLiteDatabase getWritableDatabase() {
        return database.getWritableDatabase();
    }

    public static synchronized void setDatabaseActionListener(final DatabaseActionObserver listener) {
        CustomContentProvider.databaseActionListener = listener;
    }

    @Override
    public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs);

    protected static class CoreDatabase extends SQLiteOpenHelper {
        private static final String LOG_TAG = "CoreDatabase";
        private static final boolean DBG = BuildConfig.DEBUG;

        private static final int DB_VERSION = DatabaseVersions.CURRENT;
        private static final String DB_NAME = "data.db";

        private final Context mContext;
        private final CompressedQueriesHelper mCompressedQueriesHelper;

        private boolean mSuccess = true;

        public CoreDatabase(final Context context) {
            super(context, DB_NAME, null, DB_VERSION);
            mContext = context;
            mCompressedQueriesHelper = new CompressedQueriesHelper(context);
            mCompressedQueriesHelper.setNewVersion(DB_VERSION);
        }

        @Override
        public void onOpen(final SQLiteDatabase db) {
            super.onOpen(db);
            if (!db.isReadOnly()) {
                // Enable foreign key constraints
                db.execSQL("PRAGMA foreign_keys=ON;");
            }
        }

        @Override
        public void onCreate(final SQLiteDatabase db) {
            if (DBG)
                Log.d(LOG_TAG, "Cration de la base de donnes.");

            TimeLogUtils timeLogUtils;

            if (CustomContentProvider.databaseActionListener != null) {
                CustomContentProvider.databaseActionListener.dispatchCreate();
            }

            if (DBG) {
                timeLogUtils = new TimeLogUtils(LOG_TAG);
                timeLogUtils.start();
            }

            createDatabase(db);

            if (CustomContentProvider.databaseActionListener != null) {
                CustomContentProvider.databaseActionListener.dispatchUpgradeDone(mSuccess);
            }

            if (DBG) {
                timeLogUtils.step("Fin d'installation");
            }
        }

        private void createDatabase(final SQLiteDatabase db) {
            try {

                execute(db, R.raw.sql_create);
                executeBulk(db, R.raw.sql_data);

            } catch (final Exception e) {
                BugSenseHandler.sendExceptionMessage("Erreur lors de cration de la base.", "", e);
                Log.e(LOG_TAG, "Erreur lors de cration de la base.", e);
            }
        }

        @Override
        public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
            if (DBG)
                Log.d(LOG_TAG, "Mise  jour de la base de donnes.");

            mCompressedQueriesHelper.setOldVersion(oldVersion);

            TimeLogUtils timeLogUtils;

            if (CustomContentProvider.databaseActionListener != null) {
                CustomContentProvider.databaseActionListener.dispatchUpgrade(oldVersion);
            }

            if (DBG) {
                timeLogUtils = new TimeLogUtils(LOG_TAG);
                timeLogUtils.start();
            }

            try {

                execute(db, R.raw.sql_before_update, R.raw.sql_create);
                executeBulk(db, R.raw.sql_data);
                execute(db, R.raw.sql_after_update);

            } catch (final Exception e) {
                BugSenseHandler.sendExceptionMessage("Erreur lors de la mise  jour de la base.", "", e);
                Log.e(LOG_TAG, "Erreur lors de la mise  jour de la base.", e);
                handleUpgradeException();
            } finally {
                if (DBG)
                    timeLogUtils.step("Fin de la mise  jour");
            }

        }

        private void handleUpgradeException() {
            if (DBG)
                Log.i(LOG_TAG, "Recration de la base de donne.");

            mSuccess = false;

            final File dbFile = mContext.getDatabasePath(DB_NAME);
            dbFile.delete();

            final SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile.getAbsolutePath(), null);
            db.beginTransaction();
            createDatabase(db);
            db.setTransactionSuccessful();
            db.endTransaction();
        }

        /**
         * Executer des fichiers SQL sur la base de donnes.
         * 
         * @param db
         *            La base de donnes.
         * @param resIds
         *            Les ids des scripts  excuter, dans l'ordre.
         * @throws IOException
         */
        private void execute(final SQLiteDatabase db, final int... resIds) throws IOException {
            for (final int resId : resIds) {
                if (resId == 0)
                    continue;

                if (DBG)
                    Log.i(LOG_TAG, "Execution du script " + mContext.getResources().getResourceName(resId));

                final List<String> queries = mCompressedQueriesHelper.getQueries(resId);

                for (final String query : queries) {
                    if (DBG)
                        Log.d(LOG_TAG, "\t" + query);

                    if (query.trim().length() > 0) {
                        db.execSQL(query);
                    }
                }

            }
        }

        /**
         * Executer des fichiers SQL sur la base de donnes, en mode Bulk.
         * 
         * @param db
         *            La base de donnes.
         * @param resIds
         *            Les ids des scripts  excuter, dans l'ordre.
         * @throws IOException
         */
        private void executeBulk(final SQLiteDatabase db, final int... resIds) throws IOException {
            SQLiteStatement statement;
            List<BulkQuery> bulkQueries;

            for (final int resId : resIds) {
                if (DBG)
                    Log.i(LOG_TAG, "Execution du script " + mContext.getResources().getResourceName(resId));

                bulkQueries = mCompressedQueriesHelper.getBulkQueries(resId);

                for (final BulkQuery bulkQuery : bulkQueries) {
                    final List<String[]> statementValues = bulkQuery.getValues();
                    statement = db.compileStatement(bulkQuery.getPattern());
                    for (final String[] values : statementValues) {
                        for (int i = 0; i < values.length; i++) {
                            statement.bindString(i + 1, values[i]);
                        }
                        statement.execute();
                    }
                }
            }

        }

    }

}