/** ** Copyright (c) 2010 Ushahidi Inc ** All rights reserved ** Contact: team@ushahidi.com ** Website: http://www.ushahidi.com ** ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: http://www.gnu.org/licenses/lgpl.html. ** ** ** If you have questions regarding the use of this file, please contact ** Ushahidi developers at team@ushahidi.com. ** **/ package com.ushahidi.android.app.database; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.text.TextUtils; import android.util.Log; public class Database { private static final String TAG = "UshahidiDatabase"; private DatabaseHelper mDbHelper; private SQLiteDatabase mDb; public static final String DATABASE_NAME = "ushahidi_db"; private static final int DATABASE_VERSION = 19; private final Context mContext; public static ReportDao mReportDao; // Report table public static CategoryDao mCategoryDao; // Category table public static MapDao mMapDao; // Map aka deployment table public static ReportCategoryDao mReportCategoryDao; // ReportCategory table public static MediaDao mMediaDao; // Media table public static OfflineReportDao mOfflineReport; // Offline reports public static CheckinDao mCheckin; // checkins public static UserDao mUserDao; // user public static CommentDao mCommentDao; // comment public static OpenGeoSmsDao mOpenGeoSmsDao; private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(IReportSchema.INCIDENTS_TABLE_CREATE); db.execSQL(ICategorySchema.CATEGORIES_TABLE_CREATE); if (!doesVirtualTableExists(db, IMapSchema.TABLE)) { // create map aka deployment table db.execSQL(IMapSchema.MAP_TABLE_CREATE); } // create default map // TODO:: check if default map is set. db.execSQL(IMapSchema.DEFAULT_MAP_CREATE); db.execSQL(IReportCategorySchema.REPORT_CATEGORY_TABLE_CREATE); db.execSQL(IMediaSchema.MEDIA_TABLE_CREATE); db.execSQL(IUserSchema.USER_TABLE_CREATE); db.execSQL(ICheckinSchema.CHECKINS_TABLE_CREATE); db.execSQL(IOfflineReportSchema.OFFLINE_REPORT_TABLE_CREATE); db.execSQL(ICommentSchema.COMMENT_TABLE_CREATE); db.execSQL(IOpenGeoSmsSchema.OPENGEOSMS_TABLE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + " which destroys all old data"); List<String> reportCategoryColumns; try { // upgrade report category db.execSQL(IReportCategorySchema.REPORT_CATEGORY_TABLE_CREATE); reportCategoryColumns = Database.getColumns(db, IReportCategorySchema.TABLE); db.execSQL("ALTER TABLE " + IReportCategorySchema.TABLE + " RENAME TO temp_" + IReportCategorySchema.TABLE); db.execSQL(IReportCategorySchema.REPORT_CATEGORY_TABLE_CREATE); reportCategoryColumns.retainAll(Database.getColumns(db, IReportCategorySchema.TABLE)); String reportsCategoryCols = Database.join( reportCategoryColumns, ","); db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s FROM temp_%s", IReportCategorySchema.TABLE, reportsCategoryCols, reportsCategoryCols, IReportCategorySchema.TABLE)); db.execSQL("DROP TABLE IF EXISTS temp_" + IReportCategorySchema.TABLE); onCreate(db); } catch (SQLException e) { e.printStackTrace(); } } } /** * Credits http://goo.gl/7kOpU * * @param db * @param tableName * @return */ public static List<String> getColumns(SQLiteDatabase db, String tableName) { List<String> ar = null; Cursor c = null; try { c = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 1", null); if (c != null) { ar = new ArrayList<String>(Arrays.asList(c.getColumnNames())); } } catch (Exception e) { Log.v(tableName, e.getMessage(), e); e.printStackTrace(); } finally { if (c != null) c.close(); } return ar; } public static String join(List<String> list, String delim) { StringBuilder buf = new StringBuilder(); int num = list.size(); for (int i = 0; i < num; i++) { if (i != 0) buf.append(delim); buf.append((String) list.get(i)); } return buf.toString(); } public Database(Context context) { this.mContext = context; } public static List<String> getTableColumns(SQLiteDatabase db, String tableName) { ArrayList<String> columns = new ArrayList<String>(); String cmd = "pragma table_info(" + tableName + ");"; Cursor cur = db.rawQuery(cmd, null); while (cur.moveToNext()) { columns.add(cur.getString(cur.getColumnIndex("name"))); } cur.close(); return columns; } // Credits: // http://udinic.wordpress.com/2012/05/09/sqlite-drop-column-support/ private static void dropColumn(SQLiteDatabase db, String createTableCmd, String tableName, String[] colsToRemove) { List<String> updatedTableColumns = getTableColumns(db, tableName); // Remove the columns we don't want anymore from the table's list of // columns updatedTableColumns.removeAll(Arrays.asList(colsToRemove)); String columnsSeperated = TextUtils.join(",", updatedTableColumns); db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;"); // Creating the table on its new format (no redundant columns) db.execSQL(createTableCmd); // Populating the table with the data db.execSQL("INSERT INTO " + tableName + "(" + columnsSeperated + ") SELECT " + columnsSeperated + " FROM " + tableName + "_old;"); db.execSQL("DROP TABLE " + tableName + "_old;"); } public static boolean doesVirtualTableExists(SQLiteDatabase db, String tableName) { Cursor cursor = db .rawQuery( String.format( "SELECT DISTINCT tbl_name from sqlite_master where tbl_name ='%s'", tableName), null); if (cursor.getCount() > 0) { cursor.close(); return true; } cursor.close(); return false; } public Database open() throws SQLException { mDbHelper = new DatabaseHelper(mContext); mDb = mDbHelper.getWritableDatabase(); mReportDao = new ReportDao(mDb); mCategoryDao = new CategoryDao(mDb); mMapDao = new MapDao(mDb); mMediaDao = new MediaDao(mDb); mReportCategoryDao = new ReportCategoryDao(mDb); mOfflineReport = new OfflineReportDao(mDb); mCheckin = new CheckinDao(mDb); mUserDao = new UserDao(mDb); mCommentDao = new CommentDao(mDb); mOpenGeoSmsDao = new OpenGeoSmsDao(mDb); return this; } public void close() { mDbHelper.close(); } }