package net.bradmont.openmpd; import net.bradmont.openmpd.models.*; import net.bradmont.supergreen.*; import net.bradmont.supergreen.models.*; import android.content.Context; import android.database.sqlite.*; import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; public class MPDDBHelper extends DBHelper{ private static MPDDBHelper instance = null; private static int DATABASE_VERSION = 21; @Override protected void registerModels(){ instance = this; registerModel(new Contact()); registerModel(new Address()); registerModel(new EmailAddress()); registerModel(new PhoneNumber()); registerModel(new Gift()); registerModel(new ContactStatus()); registerModel(new TntService()); registerModel(new ServiceAccount()); registerModel(new Notification()); registerModel(new LogItem()); registerModel(new QuickMessage()); } public MPDDBHelper(Context c) { super(c, DATABASE_VERSION); if (instance == null){ instance = this; } } // get the instance without instantiating public static MPDDBHelper rawGet(){ return instance; } public static MPDDBHelper get(){ // Thread-safety is a pain; if we aren't instantiated, we'll use // the main app activity as context. This means outside threads // will have to be careful to take care of this themselves. if (instance == null){ instance = new MPDDBHelper(OpenMPD.get()); } return instance; } public static ModelList filter(String table_name, String field_name, int value){ return get() .getReferenceModel(table_name) .filter(field_name, value); } public static ModelList filter(String table_name, String field_name, float value){ return get() .getReferenceModel(table_name) .filter(field_name, value); } public static ModelList filter(String table_name, String field_name, String value){ return get() .getReferenceModel(table_name) .filter(field_name, value); } public static DBModel getModelByField(String table_name, String field_name, String value){ return getReferenceModel(table_name).getByField(field_name, value); } public static DBModel getModelByField(String table_name, String field_name, int value){ return getReferenceModel(table_name).getByField(field_name, value); } @Override public void onCreate(SQLiteDatabase db){ super.onCreate(db); String file = ""; try { file = context.getResources().getResourceName(R.raw.views); executeSqlScript(context, db, R.raw.views); } catch (IOException e){ // TODO we should die gracefully here... Log.i("net.bradmont.openmpd", "FAILURE: could not open " + file ); } } /** * The following methods are taken from Markus Junginger's GreenDAO * (https://github.com/greenrobot/greenDAO/), licensed under the APL 2.0 */ /** * Calls {@link #executeSqlScript(Context, SQLiteDatabase, String, boolean)} with transactional set to true. * * @return number of statements executed. */ public static int executeSqlScript(Context context, SQLiteDatabase db, int file_id ) throws IOException { return executeSqlScript(context, db, file_id, true); } /** * Executes the given SQL asset in the given database (SQL file should be UTF-8). The database file may contain * multiple SQL statements. Statements are split using a simple regular expression (something like * "semicolon before a line break"), not by analyzing the SQL syntax. This will work for many SQL files, but check * yours. * * @return number of statements executed. */ public static int executeSqlScript(Context context, SQLiteDatabase db, int file_id, boolean transactional) throws IOException { byte[] bytes = readAsset(context, file_id); String sql = new String(bytes, "UTF-8"); String[] lines = sql.split(";(\\s)*[\n\r]"); int count; if (transactional) { count = executeSqlStatementsInTx(db, lines); } else { count = executeSqlStatements(db, lines); } return count; } public static int executeSqlStatementsInTx(SQLiteDatabase db, String[] statements) { db.beginTransaction(); try { int count = executeSqlStatements(db, statements); db.setTransactionSuccessful(); return count; } finally { db.endTransaction(); } } public static int executeSqlStatements(SQLiteDatabase db, String[] statements) { int count = 0; for (String line : statements) { line = line.trim(); if (line.length() > 0) { db.execSQL(line); count++; } } return count; } public static int copyAllBytes(InputStream in, OutputStream out) throws IOException { int byteCount = 0; byte[] buffer = new byte[4096]; while (true) { int read = in.read(buffer); if (read == -1) { break; } out.write(buffer, 0, read); byteCount += read; } return byteCount; } public static byte[] readAllBytes(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); copyAllBytes(in, out); return out.toByteArray(); } public static byte[] readAsset(Context context, int file_id) throws IOException { InputStream in = context.getResources().openRawResource(file_id); try { return readAllBytes(in); } finally { in.close(); } } @Override public synchronized void close(){ super.close(); instance = null; } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){ super.onUpgrade(db, oldVersion, newVersion); if (oldVersion < 10){ db.execSQL("drop view monthly_base_giving;"); db.execSQL( "create view monthly_base_giving as select month, sum(base_total) base_giving from (select * from _monthly_base_giving union select * from _monthly_base_giving_in_special_month) group by month;"); } if (oldVersion < 14){ db.execSQL("update contact_status set notes=NULL;"); } if (oldVersion < 17){ db.execSQL("update contact_status set partner_type=partner_type*10;"); db.execSQL("drop table if exists giving_summary_cache;"); String file = ""; try { file = context.getResources().getResourceName(R.raw.views); executeSqlScript(context, db, R.raw.views); } catch (IOException e){ // TODO we should die gracefully here... Log.i("net.bradmont.openmpd", "FAILURE: could not open " + file ); } } if (oldVersion < 18){ db.execSQL("drop view _monthly_base_giving;"); db.execSQL( "create view if not exists _monthly_base_giving as select month, sum(total_gifts) as base_total from partner_giving_status join partner_giving_by_month on partner_giving_status.tnt_people_id = partner_giving_by_month.tnt_people_id where total_gifts<=giving_amount and partner_type=60 group by month order by month; "); db.execSQL("drop table if exists giving_summary_cache;"); } if (oldVersion < 19){ db.execSQL("alter table tnt_service add query_ini_url string;"); db.execSQL("update tnt_service set query_ini_url='http://tntmpd.powertochange.org/tntmpd/Query.ini', name = 'Power to Change - Canada' where name_short='P2C'"); db.execSQL("update tnt_service set query_ini_url='https://staffweb.cru.org/ss/tntmpd/query.ini', name = 'Cru - USA' where name_short='CCC'"); db.execSQL("update tnt_service set query_ini_url='https://rews.cco.ca/dataserver/CCO/dataquery/TntQuery.aspx', name = 'CCO Canada' where name_short='CCO'"); } if (oldVersion < 20){ db.execSQL("alter table tnt_service add untested_service int default 0;"); } if (oldVersion < 21){ db.execSQL("alter table log add timestamp string;"); } } }