aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/persistance
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/persistance')
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/persistance/CursorHelper.java203
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java61
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/persistance/MessageDatabaseAccess.java46
3 files changed, 309 insertions, 1 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/persistance/CursorHelper.java b/src/main/java/de/thedevstack/conversationsplus/persistance/CursorHelper.java
new file mode 100644
index 00000000..7e3fdab0
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/persistance/CursorHelper.java
@@ -0,0 +1,203 @@
+package de.thedevstack.conversationsplus.persistance;
+
+import android.database.Cursor;
+
+/**
+ * Created by steckbrief on 15.04.2016.
+ */
+public abstract class CursorHelper {
+
+ static double getDouble(Cursor cursor, String columnName) {
+ if (null == cursor) {
+ return Double.MIN_VALUE;
+ }
+ int columnIndex = getColumnIndex(cursor, columnName);
+ if (columnIndex < 0) {
+ return Double.MIN_VALUE;
+ }
+ return getDouble(cursor, columnIndex);
+ }
+
+ static String getString(Cursor cursor, String columnName) {
+ if (null == cursor) {
+ return null;
+ }
+ int columnIndex = getColumnIndex(cursor, columnName);
+ if (columnIndex < 0) {
+ return null;
+ }
+ return getString(cursor, columnIndex);
+ }
+
+ static float getFloat(Cursor cursor, String columnName) {
+ if (null == cursor) {
+ return Float.MIN_VALUE;
+ }
+ int columnIndex = getColumnIndex(cursor, columnName);
+ if (columnIndex < 0) {
+ return Float.MIN_VALUE;
+ }
+ return getFloat(cursor, columnIndex);
+ }
+
+ static int getInt(Cursor cursor, String columnName) {
+ if (null == cursor) {
+ return Integer.MIN_VALUE;
+ }
+ int columnIndex = getColumnIndex(cursor, columnName);
+ if (columnIndex < 0) {
+ return Integer.MIN_VALUE;
+ }
+ return getInt(cursor, columnIndex);
+ }
+
+ static long getLong(Cursor cursor, String columnName) {
+ if (null == cursor) {
+ return Long.MIN_VALUE;
+ }
+ int columnIndex = getColumnIndex(cursor, columnName);
+ if (columnIndex < 0) {
+ return Long.MIN_VALUE;
+ }
+ return getLong(cursor, columnIndex);
+ }
+
+ static int getShort(Cursor cursor, String columnName) {
+ if (null == cursor) {
+ return Short.MIN_VALUE;
+ }
+ int columnIndex = getColumnIndex(cursor, columnName);
+ if (columnIndex < 0) {
+ return Short.MIN_VALUE;
+ }
+ return getShort(cursor, columnIndex);
+ }
+
+ static byte[] getBlob(Cursor cursor, String columnName) {
+ if (null == cursor) {
+ return null;
+ }
+ int columnIndex = getColumnIndex(cursor, columnName);
+ if (columnIndex < 0) {
+ return null;
+ }
+ return getBlob(cursor, columnIndex);
+ }
+
+ /**
+ * Returns the zero-based index for the given column name, or -1 if the column doesn't exist.
+ * If you expect the column to exist use {@link Cursor#getColumnIndexOrThrow(String)} instead, which
+ * will make the error more clear.
+ *
+ * @param columnName the name of the target column.
+ * @return the zero-based column index for the given column name, or -1 if
+ * the column name does not exist.
+ * @see Cursor#getColumnIndexOrThrow(String)
+ */
+ static int getColumnIndex(Cursor cursor, String columnName) {
+ return cursor.getColumnIndex(columnName);
+ }
+
+ /**
+ * Returns the value of the requested column as a byte array.
+ *
+ * <p>The result and whether this method throws an exception when the
+ * column value is null or the column type is not a blob type is
+ * implementation-defined.
+ *
+ * @param columnIndex the zero-based index of the target column.
+ * @return the value of that column as a byte array.
+ */
+ static byte[] getBlob(Cursor cursor, int columnIndex) {
+ return cursor.getBlob(columnIndex);
+ }
+
+ /**
+ * Returns the value of the requested column as a String.
+ *
+ * <p>The result and whether this method throws an exception when the
+ * column value is null or the column type is not a string type is
+ * implementation-defined.
+ *
+ * @param columnIndex the zero-based index of the target column.
+ * @return the value of that column as a String.
+ */
+ static String getString(Cursor cursor, int columnIndex) {
+ return cursor.getString(columnIndex);
+ }
+
+ /**
+ * Returns the value of the requested column as a short.
+ *
+ * <p>The result and whether this method throws an exception when the
+ * column value is null, the column type is not an integral type, or the
+ * integer value is outside the range [<code>Short.MIN_VALUE</code>,
+ * <code>Short.MAX_VALUE</code>] is implementation-defined.
+ *
+ * @param columnIndex the zero-based index of the target column.
+ * @return the value of that column as a short.
+ */
+ static short getShort(Cursor cursor, int columnIndex) {
+ return cursor.getShort(columnIndex);
+ }
+
+ /**
+ * Returns the value of the requested column as an int.
+ *
+ * <p>The result and whether this method throws an exception when the
+ * column value is null, the column type is not an integral type, or the
+ * integer value is outside the range [<code>Integer.MIN_VALUE</code>,
+ * <code>Integer.MAX_VALUE</code>] is implementation-defined.
+ *
+ * @param columnIndex the zero-based index of the target column.
+ * @return the value of that column as an int.
+ */
+ static int getInt(Cursor cursor, int columnIndex) {
+ return cursor.getInt(columnIndex);
+ }
+
+ /**
+ * Returns the value of the requested column as a long.
+ *
+ * <p>The result and whether this method throws an exception when the
+ * column value is null, the column type is not an integral type, or the
+ * integer value is outside the range [<code>Long.MIN_VALUE</code>,
+ * <code>Long.MAX_VALUE</code>] is implementation-defined.
+ *
+ * @param columnIndex the zero-based index of the target column.
+ * @return the value of that column as a long.
+ */
+ static long getLong(Cursor cursor, int columnIndex) {
+ return cursor.getLong(columnIndex);
+ }
+
+ /**
+ * Returns the value of the requested column as a float.
+ *
+ * <p>The result and whether this method throws an exception when the
+ * column value is null, the column type is not a floating-point type, or the
+ * floating-point value is not representable as a <code>float</code> value is
+ * implementation-defined.
+ *
+ * @param columnIndex the zero-based index of the target column.
+ * @return the value of that column as a float.
+ */
+ static float getFloat(Cursor cursor, int columnIndex) {
+ return cursor.getFloat(columnIndex);
+ }
+
+ /**
+ * Returns the value of the requested column as a double.
+ *
+ * <p>The result and whether this method throws an exception when the
+ * column value is null, the column type is not a floating-point type, or the
+ * floating-point value is not representable as a <code>double</code> value is
+ * implementation-defined.
+ *
+ * @param columnIndex the zero-based index of the target column.
+ * @return the value of that column as a double.
+ */
+ static double getDouble(Cursor cursor, int columnIndex) {
+ return cursor.getDouble(columnIndex);
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java b/src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java
index 4157d6f8..768f16c5 100644
--- a/src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java
+++ b/src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java
@@ -34,6 +34,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import org.json.JSONException;
import de.thedevstack.android.logcat.Logging;
+import de.thedevstack.conversationsplus.BuildConfig;
import de.thedevstack.conversationsplus.Config;
import de.thedevstack.conversationsplus.crypto.axolotl.AxolotlServiceImpl;
import de.thedevstack.conversationsplus.crypto.axolotl.SQLiteAxolotlStore;
@@ -53,6 +54,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "history";
private static final int DATABASE_VERSION = 25;
+ private static final int C_TO_CPLUS_VERSION_OFFSET = 1000;
+ private static final int CPLUS_DATABASE_VERSION = 2;
+ private static final int CPLUS_DATABASE_VERSION_MULTIPLIER = 100;
+ private static final int PHYSICAL_DATABASE_VERSION = DATABASE_VERSION + C_TO_CPLUS_VERSION_OFFSET + (CPLUS_DATABASE_VERSION * CPLUS_DATABASE_VERSION_MULTIPLIER);
private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -129,8 +134,17 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ ") ON CONFLICT IGNORE"
+ ");";
+ private static int calculateCDatabaseVersion(int physicalDatabaseVersion) {
+ return physicalDatabaseVersion % CPLUS_DATABASE_VERSION_MULTIPLIER;
+ }
+
+ private static int calculateCPLusDatabaseVersion(int physicalDatabaseVersion) {
+ int cPlusDatabaseVersion = (physicalDatabaseVersion - C_TO_CPLUS_VERSION_OFFSET) / CPLUS_DATABASE_VERSION_MULTIPLIER;
+ return cPlusDatabaseVersion < 0 ? 0 : cPlusDatabaseVersion;
+ }
+
private DatabaseBackend(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ super(context, DATABASE_NAME, null, PHYSICAL_DATABASE_VERSION);
}
@Override
@@ -176,10 +190,34 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL(CREATE_PREKEYS_STATEMENT);
db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT);
db.execSQL(CREATE_IDENTITIES_STATEMENT);
+
+ // Create Conversations+ related tables
+ db.execSQL(MessageDatabaseAccess.TABLE_ADDITIONAL_PARAMETERS_CREATE_V0);
}
+ protected void onUpgradeCPlusDatabase(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Logging.d("db.upgrade.cplus", "Updating Conversations+ database from version '" + oldVersion + "' to '" + newVersion + "'");
+ if (oldVersion != newVersion) {
+ if ((oldVersion == 0 || oldVersion == 1) && newVersion == 2) {
+ Logging.d("db.upgrade.cplus", "Creating additional parameters table for messages.");
+ db.execSQL(MessageDatabaseAccess.TABLE_ADDITIONAL_PARAMETERS_CREATE_V0);
+ db.execSQL("INSERT INTO " + MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS + "(" + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + ") "
+ + " SELECT " + Message.UUID + " FROM " + Message.TABLENAME);
+ }
+ }
+ }
+
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ onUpgradeConversationsDatabase(db, calculateCDatabaseVersion(oldVersion), calculateCDatabaseVersion(newVersion));
+ onUpgradeCPlusDatabase(db, calculateCPLusDatabaseVersion(oldVersion), calculateCPLusDatabaseVersion(newVersion));
+ }
+
+ protected void onUpgradeConversationsDatabase(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Logging.d("db.upgrade.conversations", "Updating Conversations database from version '" + oldVersion + "' to '" + newVersion + "'");
+ if (oldVersion == newVersion) {
+ return;
+ }
if (oldVersion < 2 && newVersion >= 2) {
db.execSQL("update " + Account.TABLENAME + " set "
+ Account.OPTIONS + " = " + Account.OPTIONS + " | 8");
@@ -396,8 +434,14 @@ public class DatabaseBackend extends SQLiteOpenHelper {
}
public void createMessage(Message message) {
+ Logging.d("db.msg.insert", "Inserting new message with uuid '" + message.getUuid() + "', isRead: " + message.isRead());
+
SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransaction();
db.insert(Message.TABLENAME, null, message.getContentValues());
+ db.insert(MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS, null, MessageDatabaseAccess.getAdditionalParametersContentValues(message));
+ db.setTransactionSuccessful();
+ db.endTransaction();
}
public void createAccount(Account account) {
@@ -471,6 +515,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
cursor.moveToLast();
do {
Message message = Message.fromCursor(cursor);
+ MessageDatabaseAccess.populateMessageParameters(db, message);
message.setConversation(conversation);
list.add(message);
} while (cursor.moveToPrevious());
@@ -502,6 +547,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
@Override
public Message next() {
Message message = Message.fromCursor(cursor);
+ MessageDatabaseAccess.populateMessageParameters(db, message);
cursor.moveToNext();
return message;
}
@@ -598,17 +644,28 @@ public class DatabaseBackend extends SQLiteOpenHelper {
}
public void updateMessage(Message message) {
+ Logging.d("db.msg.update", "Updating message with uuid '" + message.getUuid() + "', isRead: " + message.isRead());
SQLiteDatabase db = this.getWritableDatabase();
String[] args = {message.getUuid()};
+ db.beginTransaction();
db.update(Message.TABLENAME, message.getContentValues(), Message.UUID
+ "=?", args);
+ db.update(MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS, MessageDatabaseAccess.getAdditionalParametersContentValues(message), MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + "=?", args);
+ db.setTransactionSuccessful();
+ db.endTransaction();
}
public void updateMessage(Message message, String uuid) {
+ Logging.d("db.msg.update", "Updating message with uuid '" + uuid + "', isRead: " + message.isRead());
+
SQLiteDatabase db = this.getWritableDatabase();
String[] args = {uuid};
+ db.beginTransaction();
db.update(Message.TABLENAME, message.getContentValues(), Message.UUID
+ "=?", args);
+ db.update(MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS, MessageDatabaseAccess.getAdditionalParametersContentValues(message), MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + "=?", args);
+ db.setTransactionSuccessful();
+ db.endTransaction();
}
public void readRoster(Roster roster) {
@@ -642,6 +699,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
}
public void deleteMessagesInConversation(Conversation conversation) {
+ Logging.d("db.msg.delete", "Deleting messages in conversation with uuid '" + conversation.getUuid());
+
SQLiteDatabase db = this.getWritableDatabase();
String[] args = {conversation.getUuid()};
db.delete(Message.TABLENAME, Message.CONVERSATION + "=?", args);
diff --git a/src/main/java/de/thedevstack/conversationsplus/persistance/MessageDatabaseAccess.java b/src/main/java/de/thedevstack/conversationsplus/persistance/MessageDatabaseAccess.java
new file mode 100644
index 00000000..737c16ff
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/persistance/MessageDatabaseAccess.java
@@ -0,0 +1,46 @@
+package de.thedevstack.conversationsplus.persistance;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import de.thedevstack.conversationsplus.entities.Message;
+import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException;
+import de.thedevstack.conversationsplus.xmpp.jid.Jid;
+
+/**
+ * Created by steckbrief on 15.04.2016.
+ */
+public class MessageDatabaseAccess {
+ static final String TABLE_NAME_ADDITIONAL_PARAMETERS = "message_parameters";
+ static final String COLUMN_NAME_MSG_PARAMS_HTTPUPLOAD = "httpupload";
+ static final String COLUMN_NAME_MSG_PARAMS_MSGUUID = "message_uuid";
+
+ static final String TABLE_ADDITIONAL_PARAMETERS_CREATE_V0 = "CREATE TABLE " + MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS + " ("
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + " TEXT, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_HTTPUPLOAD + " INTEGER DEFAULT 0, "
+ + "FOREIGN KEY(" + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + ") REFERENCES " + Message.TABLENAME + "(" + Message.UUID + ") ON DELETE CASCADE)";
+
+ static ContentValues getAdditionalParametersContentValues(Message message) {
+ ContentValues additionalParameters = new ContentValues();
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID, message.getUuid());
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_HTTPUPLOAD, message.isHttpUploaded() ? 1 : 0);
+
+ return additionalParameters;
+ }
+
+ static void populateMessageParametersFromCursor(Cursor cursor, Message message) {
+ boolean isHttpUploaded = CursorHelper.getInt(cursor, COLUMN_NAME_MSG_PARAMS_HTTPUPLOAD) == 1;
+ message.setHttpUploaded(isHttpUploaded);
+ }
+
+ static void populateMessageParameters(SQLiteDatabase db, Message message) {
+ Cursor paramsCursor = db.query(MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS,
+ null, MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + "=?",
+ new String[] {message.getUuid()},
+ null, null, null, null);
+ paramsCursor.moveToNext();
+ MessageDatabaseAccess.populateMessageParametersFromCursor(paramsCursor, message);
+ paramsCursor.close();
+ }
+}