package org.commcare.models.legacy;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.preference.PreferenceManager;
import org.commcare.android.javarosa.AndroidLogEntry;
import org.commcare.logging.AndroidLogger;
import org.commcare.android.javarosa.DeviceReportRecord;
import org.commcare.android.database.user.models.FormRecord;
import org.commcare.android.database.user.models.GeocodeCacheModel;
import org.commcare.android.database.user.models.SessionStateDescriptor;
import org.commcare.resources.model.Resource;
import org.javarosa.core.services.Logger;
/**
* This class exists in order to handle all of the logic associated with upgrading from one version
* of CommCare ODK to another. It is going to get big and annoying.
*
* @author ctsims
*/
public class LegacyCommCareUpgrader {
private final Context context;
public LegacyCommCareUpgrader(Context c) {
this.context = c;
}
public boolean doUpgrade(SQLiteDatabase database, int from, int to) {
Logger.log(AndroidLogger.TYPE_MAINTENANCE, String.format("App DB Upgrade needed! Starting upgrade from %d to %d", from, to));
if (from == 1) {
if (upgradeOneTwo(database)) {
from = 2;
} else {
return false;
}
}
if (from == 26) {
if (upgradeTwoSixtoTwoSeven(database)) {
from = 27;
} else {
return false;
}
}
if (from == 27) {
if (upgradeTwoSeventoTwoEight(database)) {
from = 28;
} else {
return false;
}
}
if (from == 28) {
if (upgradeTwoEighttoTwoNine(database)) {
from = 29;
} else {
return false;
}
}
if (from == 29) {
if (upgradeTwoNineToThreeOh(database)) {
from = 30;
} else {
return false;
}
}
Logger.log(AndroidLogger.TYPE_MAINTENANCE, String.format("Upgrade %s", from == to ? "succesful" : "unsuccesful"));
return from == to;
}
private boolean upgradeTwoNineToThreeOh(SQLiteDatabase database) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putBoolean("isValidated", true).commit();
return true;
}
private boolean upgradeOneTwo(SQLiteDatabase database) {
database.beginTransaction();
LegacyTableBuilder builder = new LegacyTableBuilder("UPGRADE_RESOURCE_TABLE");
builder.addData(new Resource());
database.execSQL(builder.getTableCreateString());
database.setVersion(2);
database.setTransactionSuccessful();
database.endTransaction();
return true;
}
/**
* Previous FormRecord entries were lacking, we're going to
* wipe them out.
*/
private boolean upgradeTwoSixtoTwoSeven(SQLiteDatabase database) {
database.beginTransaction();
//wipe out old Form Record table
database.execSQL("drop table FORMRECORDS");
//Build us a new one with the new structure
LegacyTableBuilder builder = new LegacyTableBuilder("FORMRECORDS");
builder.addData(new FormRecord());
database.execSQL(builder.getTableCreateString());
database.setTransactionSuccessful();
database.endTransaction();
return true;
}
private boolean upgradeTwoSeventoTwoEight(SQLiteDatabase database) {
database.beginTransaction();
LegacyTableBuilder builder = new LegacyTableBuilder(GeocodeCacheModel.STORAGE_KEY);
builder.addData(new GeocodeCacheModel());
database.execSQL(builder.getTableCreateString());
database.setTransactionSuccessful();
database.endTransaction();
return true;
}
private boolean upgradeTwoEighttoTwoNine(SQLiteDatabase database) {
String ssdTable = LegacyTableBuilder.scrubName("android_cc_session");
String tempssdTable = LegacyTableBuilder.scrubName("android_cc_session" + "temp");
int oldRows = countRows(database, ssdTable);
try {
database.beginTransaction();
LegacyTableBuilder builder = new LegacyTableBuilder(AndroidLogEntry.STORAGE_KEY);
builder.addData(new AndroidLogEntry());
database.execSQL(builder.getTableCreateString());
builder = new LegacyTableBuilder("log_records");
builder.addData(new DeviceReportRecord());
database.execSQL(builder.getTableCreateString());
//SQLite can't add column constraints. You've gotta make a new table, copy everything over, and
//wipe the old one
database.execSQL(String.format("ALTER TABLE %s RENAME TO %s;", ssdTable, tempssdTable));
builder = new LegacyTableBuilder("android_cc_session");
builder.setUnique(SessionStateDescriptor.META_FORM_RECORD_ID);
builder.addData(new SessionStateDescriptor());
database.execSQL(builder.getTableCreateString());
String cols = builder.getColumns();
database.execSQL(String.format("INSERT OR REPLACE INTO %s (%s) " +
"SELECT %s " +
"FROM %s;", ssdTable, cols, cols, tempssdTable));
database.execSQL(String.format("DROP TABLE %s;", tempssdTable));
database.setTransactionSuccessful();
int newRows = countRows(database, ssdTable);
if (oldRows != newRows) {
Logger.log(AndroidLogger.TYPE_MAINTENANCE, String.format("Removed %s duplicate SessionStateDescriptor rows during DB Upgrade", String.valueOf(oldRows - newRows)));
}
return true;
} finally {
database.endTransaction();
}
}
private int countRows(SQLiteDatabase database, String table) {
Cursor c = null;
try {
c = database.rawQuery(String.format("SELECT COUNT(*) AS total FROM %s", table), new String[0]);
c.moveToFirst();
return c.getInt(0);
} catch (Exception e) {
return -1;
} finally {
if (c != null) {
c.close();
}
}
}
}