aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/persistance/db/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/persistance/db/access')
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/persistance/db/access/AbstractDatabaseAccess.java21
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/persistance/db/access/CursorHelper.java203
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/persistance/db/access/MessageDatabaseAccess.java181
3 files changed, 405 insertions, 0 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/persistance/db/access/AbstractDatabaseAccess.java b/src/main/java/de/thedevstack/conversationsplus/persistance/db/access/AbstractDatabaseAccess.java
new file mode 100644
index 00000000..407859c7
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/persistance/db/access/AbstractDatabaseAccess.java
@@ -0,0 +1,21 @@
+package de.thedevstack.conversationsplus.persistance.db.access;
+
+import android.database.sqlite.SQLiteDatabase;
+
+/**
+ * Created by steckbrief on 24.08.2016.
+ */
+public abstract class AbstractDatabaseAccess {
+ static void executeAlterStatements(SQLiteDatabase db, String... alterStatements) {
+ for (String alterStatement : alterStatements) {
+ db.execSQL(alterStatement);
+ }
+ }
+
+ static void addNewColumns(SQLiteDatabase db, String tableName, String... columnDefinitions) {
+ for (String columnDefinition : columnDefinitions) {
+ String alterStatement = "ALTER TABLE " + tableName + " ADD COLUMN " + columnDefinition;
+ db.execSQL(alterStatement);
+ }
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/persistance/db/access/CursorHelper.java b/src/main/java/de/thedevstack/conversationsplus/persistance/db/access/CursorHelper.java
new file mode 100644
index 00000000..122e5160
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/persistance/db/access/CursorHelper.java
@@ -0,0 +1,203 @@
+package de.thedevstack.conversationsplus.persistance.db.access;
+
+import android.database.Cursor;
+
+/**
+ * Created by steckbrief on 15.04.2016.
+ */
+public abstract class CursorHelper {
+
+ public 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);
+ }
+
+ public 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);
+ }
+
+ public 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);
+ }
+
+ public 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);
+ }
+
+ public 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);
+ }
+
+ public 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);
+ }
+
+ public 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)
+ */
+ public 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.
+ */
+ public 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.
+ */
+ public 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.
+ */
+ public 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.
+ */
+ public 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.
+ */
+ public 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.
+ */
+ public 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.
+ */
+ public static double getDouble(Cursor cursor, int columnIndex) {
+ return cursor.getDouble(columnIndex);
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/persistance/db/access/MessageDatabaseAccess.java b/src/main/java/de/thedevstack/conversationsplus/persistance/db/access/MessageDatabaseAccess.java
new file mode 100644
index 00000000..139dc419
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/persistance/db/access/MessageDatabaseAccess.java
@@ -0,0 +1,181 @@
+package de.thedevstack.conversationsplus.persistance.db.access;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import de.thedevstack.android.logcat.Logging;
+import de.thedevstack.conversationsplus.entities.FileParams;
+import de.thedevstack.conversationsplus.enums.FileStatus;
+import de.thedevstack.conversationsplus.persistance.db.migrations.FileParamsBodyToDatabaseFieldsMigration;
+
+import eu.siacs.conversations.entities.Message;
+
+/**
+ *
+ */
+public class MessageDatabaseAccess extends AbstractDatabaseAccess {
+ // since cplus db version 1
+ public static final String TABLE_NAME_ADDITIONAL_PARAMETERS = "message_parameters";
+ private static final String COLUMN_NAME_MSG_PARAMS_HTTPUPLOAD = "httpupload";
+ private static final String COLUMN_NAME_MSG_PARAMS_MSGUUID = "message_uuid";
+ private static final String COLUMN_NAME_MSG_PARAMS_TREATASDOWNLOADABLE_DECISION = "treatasdownloadable_decision";
+ // since cplus db version 3
+ private static final String COLUMN_NAME_MSG_PARAMS_FILE_SIZE = "file_size";
+ private static final String COLUMN_NAME_MSG_PARAMS_FILE_TYPE = "file_type";
+ private static final String COLUMN_NAME_MSG_PARAMS_FILE_WIDTH = "file_width";
+ private static final String COLUMN_NAME_MSG_PARAMS_FILE_HEIGHT = "file_height";
+ private static final String COLUMN_NAME_MSG_PARAMS_FILE_STATUS = "file_status";
+ private static final String COLUMN_NAME_MSG_PARAMS_FILE_NAME = "file_name";
+ private static final String COLUMN_NAME_MSG_PARAMS_FILE_PATH = "file_path";
+ private static final String COLUMN_NAME_MSG_PARAMS_FILE_URL = "file_url";
+
+ private static final String TABLE_ADDITIONAL_PARAMETERS_CREATE_V1 = "CREATE TABLE " + MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS + " ("
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + " TEXT, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_HTTPUPLOAD + " INTEGER DEFAULT 0, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_TREATASDOWNLOADABLE_DECISION + " TEXT DEFAULT 'NOT_DECIDED', "
+ + "FOREIGN KEY(" + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + ") REFERENCES " + Message.TABLENAME + "(" + Message.UUID + ") ON DELETE CASCADE)";
+
+ private static final String TABLE_ADDITIONAL_PARAMETERS_CREATE = "CREATE TABLE " + MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS + " ("
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + " TEXT, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_HTTPUPLOAD + " INTEGER DEFAULT 0, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_TREATASDOWNLOADABLE_DECISION + " TEXT DEFAULT 'NOT_DECIDED', "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_TYPE + " TEXT DEFAULT NULL, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_SIZE + " INTEGER DEFAULT 0, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_HEIGHT + " INTEGER DEFAULT 0, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_WIDTH + " INTEGER DEFAULT 0, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_STATUS + " TEXT DEFAULT 'UNDEFINED', "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_NAME + " TEXT DEFAULT NULL, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_PATH + " TEXT DEFAULT NULL, "
+ + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_URL + " TEXT DEFAULT NULL, "
+ + "FOREIGN KEY(" + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + ") REFERENCES " + Message.TABLENAME + "(" + Message.UUID + ") ON DELETE CASCADE)";
+
+ public static void updateMessageParameters(SQLiteDatabase db, Message message, String uuid) {
+ String[] args = {uuid};
+ db.update(MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS, MessageDatabaseAccess.getAdditionalParametersContentValues(message), MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + "=?", args);
+ }
+
+ public 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);
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_TREATASDOWNLOADABLE_DECISION, message.treatAsDownloadable().name());
+ if (null != message.getFileParams()) {
+ FileParams fileParams = message.getFileParams();
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_TYPE, fileParams.getMimeType());
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_SIZE, fileParams.getSize());
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_HEIGHT, fileParams.getHeight());
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_WIDTH, fileParams.getWidth());
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_PATH, fileParams.getPath());
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_URL, fileParams.getUrl());
+ if (null != fileParams.getFileStatus()) {
+ additionalParameters.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_STATUS, fileParams.getFileStatus().name());
+ }
+ }
+
+ return additionalParameters;
+ }
+
+ private static void populateMessageParametersFromCursor(Cursor cursor, Message message) {
+ boolean isHttpUploaded = CursorHelper.getInt(cursor, COLUMN_NAME_MSG_PARAMS_HTTPUPLOAD) == 1;
+ message.setHttpUploaded(isHttpUploaded);
+ String downloadable = CursorHelper.getString(cursor, COLUMN_NAME_MSG_PARAMS_TREATASDOWNLOADABLE_DECISION);
+ Message.Decision treatAsDownloadable = Message.Decision.NOT_DECIDED;
+ try {
+ treatAsDownloadable = Message.Decision.valueOf(downloadable);
+ } catch (IllegalArgumentException e) {
+ // Should only happen if the database is corrupted, but to be on the save side catch it here
+ Logging.e("db.msg", "Unknown Decision for treatAsDownloadable found: '" + downloadable + "'");
+ }
+
+ message.setTreatAsDownloadable(treatAsDownloadable);
+
+ if (message.hasFileAttached()) {
+ FileParams fileParams = new FileParams(message.getBody());
+ String fileType = CursorHelper.getString(cursor, COLUMN_NAME_MSG_PARAMS_FILE_TYPE);
+ fileParams.setMimeType(fileType);
+ String name = CursorHelper.getString(cursor, COLUMN_NAME_MSG_PARAMS_FILE_NAME);
+ fileParams.setName(name);
+ String path = CursorHelper.getString(cursor, COLUMN_NAME_MSG_PARAMS_FILE_PATH);
+ fileParams.setPath(path);
+ String url = CursorHelper.getString(cursor, COLUMN_NAME_MSG_PARAMS_FILE_URL);
+ fileParams.setUrl(url);
+ long fileSize = CursorHelper.getLong(cursor, COLUMN_NAME_MSG_PARAMS_FILE_SIZE);
+ fileParams.setSize(fileSize);
+ int imageHeight = CursorHelper.getInt(cursor, COLUMN_NAME_MSG_PARAMS_FILE_HEIGHT);
+ fileParams.setHeight(imageHeight);
+ int imageWidth = CursorHelper.getInt(cursor, COLUMN_NAME_MSG_PARAMS_FILE_WIDTH);
+ fileParams.setWidth(imageWidth);
+ String status = CursorHelper.getString(cursor, COLUMN_NAME_MSG_PARAMS_FILE_STATUS);
+ if (null != status && !status.isEmpty()) {
+ FileStatus fileStatus = FileStatus.UNDEFINED;
+ try {
+ fileStatus = FileStatus.valueOf(status);
+ } catch (IllegalArgumentException e) {
+ // Should only happen if the database is corrupted, but to be on the save side catch it here
+ Logging.e("db.msg", "Unknown FileStatus for fileParams.fileStatus found: '" + status + "'");
+ }
+ fileParams.setFileStatus(fileStatus);
+ }
+ message.setFileParams(fileParams);
+ }
+ }
+
+ public 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();
+ }
+
+ public static void upgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion < 1 && newVersion >= 1) {
+ Logging.d("db.upgrade.cplus", "Creating additional parameters table for messages.");
+ db.execSQL(MessageDatabaseAccess.TABLE_ADDITIONAL_PARAMETERS_CREATE_V1);
+ db.execSQL("INSERT INTO " + MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS + "(" + MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + ") "
+ + " SELECT " + Message.UUID + " FROM " + Message.TABLENAME);
+ }
+ if (oldVersion < 3 && newVersion >= 3) {
+ Logging.d("db.upgrade.cplus", "Upgrade " + MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS);
+ String[] columnDefinitions = {
+ MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_TYPE + " TEXT DEFAULT NULL",
+ MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_SIZE + " INTEGER DEFAULT 0",
+ MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_HEIGHT + " INTEGER DEFAULT 0",
+ MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_WIDTH + " INTEGER DEFAULT 0",
+ MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_STATUS + " TEXT DEFAULT 'UNDEFINED'",
+ MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_NAME + " TEXT DEFAULT NULL",
+ MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_PATH + " TEXT DEFAULT NULL",
+ };
+
+ addNewColumns(db, MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS, columnDefinitions);
+
+ Logging.d("db.upgrade.cplus", "Migrate file params from message body to database fields");
+ Cursor cursor = db.rawQuery("SELECT " + Message.UUID + ", " + Message.BODY + " FROM " + Message.TABLENAME + " WHERE " + Message.TYPE + "=? OR " + Message.TYPE + "=?", new String[] {String.valueOf(Message.TYPE_FILE), String.valueOf(Message.TYPE_IMAGE)});
+ while (cursor.moveToNext()) {
+ String uuid = CursorHelper.getString(cursor, Message.UUID);
+ String body = CursorHelper.getString(cursor, Message.BODY);
+ FileParams fileParams = FileParamsBodyToDatabaseFieldsMigration.getFileParams(body);
+ String newBody = fileParams.getUrl();
+ ContentValues values = new ContentValues();
+ values.put(Message.BODY, newBody);
+ db.update(Message.TABLENAME, values, Message.UUID + "=?", new String[] {uuid});
+
+ ContentValues parameterValues = new ContentValues();
+ parameterValues.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_SIZE, fileParams.getSize());
+ parameterValues.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_HEIGHT, fileParams.getHeight());
+ parameterValues.put(MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_FILE_WIDTH, fileParams.getWidth());
+
+ db.update(MessageDatabaseAccess.TABLE_NAME_ADDITIONAL_PARAMETERS, parameterValues, MessageDatabaseAccess.COLUMN_NAME_MSG_PARAMS_MSGUUID + "=?", new String[] {uuid});
+ }
+ cursor.close();
+ }
+ }
+
+ public static void create(SQLiteDatabase db) {
+ // Create Conversations+ related tables
+ db.execSQL(MessageDatabaseAccess.TABLE_ADDITIONAL_PARAMETERS_CREATE);
+ }
+}