mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Extracted and tested the database interactions from Contribution.
This commit is contained in:
parent
d45ff218f5
commit
7c80991049
11 changed files with 687 additions and 256 deletions
|
|
@ -21,7 +21,7 @@ import javax.inject.Named;
|
|||
import dagger.android.AndroidInjector;
|
||||
import dagger.android.DaggerApplication;
|
||||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.contributions.ContributionDao;
|
||||
import fr.free.nrw.commons.data.Category;
|
||||
import fr.free.nrw.commons.data.DBOpenHelper;
|
||||
import fr.free.nrw.commons.di.CommonsApplicationComponent;
|
||||
|
|
@ -142,7 +142,7 @@ public class CommonsApplication extends DaggerApplication {
|
|||
|
||||
ModifierSequence.Table.onDelete(db);
|
||||
Category.Table.onDelete(db);
|
||||
Contribution.Table.onDelete(db);
|
||||
ContributionDao.Table.onDelete(db);
|
||||
}
|
||||
|
||||
public interface LogoutListener {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,8 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
|
@ -43,7 +37,6 @@ public class Contribution extends Media {
|
|||
public static final String SOURCE_GALLERY = "gallery";
|
||||
public static final String SOURCE_EXTERNAL = "external";
|
||||
|
||||
private ContentProviderClient client;
|
||||
private Uri contentUri;
|
||||
private String source;
|
||||
private String editSummary;
|
||||
|
|
@ -51,24 +44,42 @@ public class Contribution extends Media {
|
|||
private int state;
|
||||
private long transferred;
|
||||
private String decimalCoords;
|
||||
|
||||
private boolean isMultiple;
|
||||
|
||||
public boolean getMultiple() {
|
||||
return isMultiple;
|
||||
public Contribution(Uri contentUri, String filename, Uri localUri, String imageUrl, Date timestamp,
|
||||
int state, long dataLength, Date dateUploaded, long transferred,
|
||||
String source, String description, String creator, boolean isMultiple,
|
||||
int width, int height, String license) {
|
||||
super(localUri, imageUrl, filename, description, dataLength, timestamp, dateUploaded, creator);
|
||||
this.contentUri = contentUri;
|
||||
this.state = state;
|
||||
this.timestamp = timestamp;
|
||||
this.transferred = transferred;
|
||||
this.source = source;
|
||||
this.isMultiple = isMultiple;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.license = license;
|
||||
}
|
||||
|
||||
public void setMultiple(boolean multiple) {
|
||||
isMultiple = multiple;
|
||||
}
|
||||
|
||||
public Contribution(Uri localUri, String remoteUri, String filename, String description, long dataLength, Date dateCreated, Date dateUploaded, String creator, String editSummary, String decimalCoords) {
|
||||
super(localUri, remoteUri, filename, description, dataLength, dateCreated, dateUploaded, creator);
|
||||
public Contribution(Uri localUri, String imageUrl, String filename, String description, long dataLength,
|
||||
Date dateCreated, Date dateUploaded, String creator, String editSummary, String decimalCoords) {
|
||||
super(localUri, imageUrl, filename, description, dataLength, dateCreated, dateUploaded, creator);
|
||||
this.decimalCoords = decimalCoords;
|
||||
this.editSummary = editSummary;
|
||||
timestamp = new Date(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public Contribution(Parcel in) {
|
||||
super(in);
|
||||
contentUri = in.readParcelable(Uri.class.getClassLoader());
|
||||
source = in.readString();
|
||||
timestamp = (Date) in.readSerializable();
|
||||
state = in.readInt();
|
||||
transferred = in.readLong();
|
||||
isMultiple = in.readInt() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
super.writeToParcel(parcel, flags);
|
||||
|
|
@ -80,14 +91,12 @@ public class Contribution extends Media {
|
|||
parcel.writeInt(isMultiple ? 1 : 0);
|
||||
}
|
||||
|
||||
public Contribution(Parcel in) {
|
||||
super(in);
|
||||
contentUri = in.readParcelable(Uri.class.getClassLoader());
|
||||
source = in.readString();
|
||||
timestamp = (Date) in.readSerializable();
|
||||
state = in.readInt();
|
||||
transferred = in.readLong();
|
||||
isMultiple = in.readInt() == 1;
|
||||
public boolean getMultiple() {
|
||||
return isMultiple;
|
||||
}
|
||||
|
||||
public void setMultiple(boolean multiple) {
|
||||
isMultiple = multiple;
|
||||
}
|
||||
|
||||
public long getTransferred() {
|
||||
|
|
@ -106,10 +115,18 @@ public class Contribution extends Media {
|
|||
return contentUri;
|
||||
}
|
||||
|
||||
public void setContentUri(Uri contentUri) {
|
||||
this.contentUri = contentUri;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(Date timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public int getState() {
|
||||
return state;
|
||||
}
|
||||
|
|
@ -155,62 +172,6 @@ public class Contribution extends Media {
|
|||
return buffer.toString();
|
||||
}
|
||||
|
||||
public void setContentProviderClient(ContentProviderClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try {
|
||||
if (contentUri == null) {
|
||||
contentUri = client.insert(ContributionsContentProvider.BASE_URI, this.toContentValues());
|
||||
} else {
|
||||
client.update(contentUri, toContentValues(), null, null);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
try {
|
||||
if (contentUri == null) {
|
||||
// noooo
|
||||
throw new RuntimeException("tried to delete item with no content URI");
|
||||
} else {
|
||||
client.delete(contentUri, null, null);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ContentValues toContentValues() {
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(Table.COLUMN_FILENAME, getFilename());
|
||||
if (getLocalUri() != null) {
|
||||
cv.put(Table.COLUMN_LOCAL_URI, getLocalUri().toString());
|
||||
}
|
||||
if (getImageUrl() != null) {
|
||||
cv.put(Table.COLUMN_IMAGE_URL, getImageUrl());
|
||||
}
|
||||
if (getDateUploaded() != null) {
|
||||
cv.put(Table.COLUMN_UPLOADED, getDateUploaded().getTime());
|
||||
}
|
||||
cv.put(Table.COLUMN_LENGTH, getDataLength());
|
||||
cv.put(Table.COLUMN_TIMESTAMP, getTimestamp().getTime());
|
||||
cv.put(Table.COLUMN_STATE, getState());
|
||||
cv.put(Table.COLUMN_TRANSFERRED, transferred);
|
||||
cv.put(Table.COLUMN_SOURCE, source);
|
||||
cv.put(Table.COLUMN_DESCRIPTION, description);
|
||||
cv.put(Table.COLUMN_CREATOR, creator);
|
||||
cv.put(Table.COLUMN_MULTIPLE, isMultiple ? 1 : 0);
|
||||
cv.put(Table.COLUMN_WIDTH, width);
|
||||
cv.put(Table.COLUMN_HEIGHT, height);
|
||||
cv.put(Table.COLUMN_LICENSE, license);
|
||||
return cv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
|
|
@ -224,33 +185,6 @@ public class Contribution extends Media {
|
|||
timestamp = new Date(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public static Contribution fromCursor(Cursor cursor) {
|
||||
// Hardcoding column positions!
|
||||
Contribution c = new Contribution();
|
||||
|
||||
//Check that cursor has a value to avoid CursorIndexOutOfBoundsException
|
||||
if (cursor.getCount() > 0) {
|
||||
c.contentUri = ContributionsContentProvider.uriForId(cursor.getInt(0));
|
||||
c.filename = cursor.getString(1);
|
||||
c.localUri = TextUtils.isEmpty(cursor.getString(2)) ? null : Uri.parse(cursor.getString(2));
|
||||
c.imageUrl = cursor.getString(3);
|
||||
c.timestamp = cursor.getLong(4) == 0 ? null : new Date(cursor.getLong(4));
|
||||
c.state = cursor.getInt(5);
|
||||
c.dataLength = cursor.getLong(6);
|
||||
c.dateUploaded = cursor.getLong(7) == 0 ? null : new Date(cursor.getLong(7));
|
||||
c.transferred = cursor.getLong(8);
|
||||
c.source = cursor.getString(9);
|
||||
c.description = cursor.getString(10);
|
||||
c.creator = cursor.getString(11);
|
||||
c.isMultiple = cursor.getInt(12) == 1;
|
||||
c.width = cursor.getInt(13);
|
||||
c.height = cursor.getInt(14);
|
||||
c.license = cursor.getString(15);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
|
@ -263,121 +197,6 @@ public class Contribution extends Media {
|
|||
this.localUri = localUri;
|
||||
}
|
||||
|
||||
public static class Table {
|
||||
public static final String TABLE_NAME = "contributions";
|
||||
|
||||
public static final String COLUMN_ID = "_id";
|
||||
public static final String COLUMN_FILENAME = "filename";
|
||||
public static final String COLUMN_LOCAL_URI = "local_uri";
|
||||
public static final String COLUMN_IMAGE_URL = "image_url";
|
||||
public static final String COLUMN_TIMESTAMP = "timestamp";
|
||||
public static final String COLUMN_STATE = "state";
|
||||
public static final String COLUMN_LENGTH = "length";
|
||||
public static final String COLUMN_UPLOADED = "uploaded";
|
||||
public static final String COLUMN_TRANSFERRED = "transferred"; // Currently transferred number of bytes
|
||||
public static final String COLUMN_SOURCE = "source";
|
||||
public static final String COLUMN_DESCRIPTION = "description";
|
||||
public static final String COLUMN_CREATOR = "creator"; // Initial uploader
|
||||
public static final String COLUMN_MULTIPLE = "multiple";
|
||||
public static final String COLUMN_WIDTH = "width";
|
||||
public static final String COLUMN_HEIGHT = "height";
|
||||
public static final String COLUMN_LICENSE = "license";
|
||||
|
||||
// NOTE! KEEP IN SAME ORDER AS THEY ARE DEFINED UP THERE. HELPS HARD CODE COLUMN INDICES.
|
||||
public static final String[] ALL_FIELDS = {
|
||||
COLUMN_ID,
|
||||
COLUMN_FILENAME,
|
||||
COLUMN_LOCAL_URI,
|
||||
COLUMN_IMAGE_URL,
|
||||
COLUMN_TIMESTAMP,
|
||||
COLUMN_STATE,
|
||||
COLUMN_LENGTH,
|
||||
COLUMN_UPLOADED,
|
||||
COLUMN_TRANSFERRED,
|
||||
COLUMN_SOURCE,
|
||||
COLUMN_DESCRIPTION,
|
||||
COLUMN_CREATOR,
|
||||
COLUMN_MULTIPLE,
|
||||
COLUMN_WIDTH,
|
||||
COLUMN_HEIGHT,
|
||||
COLUMN_LICENSE
|
||||
};
|
||||
|
||||
|
||||
private static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " ("
|
||||
+ "_id INTEGER PRIMARY KEY,"
|
||||
+ "filename STRING,"
|
||||
+ "local_uri STRING,"
|
||||
+ "image_url STRING,"
|
||||
+ "uploaded INTEGER,"
|
||||
+ "timestamp INTEGER,"
|
||||
+ "state INTEGER,"
|
||||
+ "length INTEGER,"
|
||||
+ "transferred INTEGER,"
|
||||
+ "source STRING,"
|
||||
+ "description STRING,"
|
||||
+ "creator STRING,"
|
||||
+ "multiple INTEGER,"
|
||||
+ "width INTEGER,"
|
||||
+ "height INTEGER,"
|
||||
+ "LICENSE STRING"
|
||||
+ ");";
|
||||
|
||||
|
||||
public static void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(CREATE_TABLE_STATEMENT);
|
||||
}
|
||||
|
||||
public static void onDelete(SQLiteDatabase db) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public static void onUpdate(SQLiteDatabase db, int from, int to) {
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
if (from == 1) {
|
||||
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN description STRING;");
|
||||
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN creator STRING;");
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 2) {
|
||||
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN multiple INTEGER;");
|
||||
db.execSQL("UPDATE " + TABLE_NAME + " SET multiple = 0");
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 3) {
|
||||
// Do nothing
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 4) {
|
||||
// Do nothing -- added Category
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 5) {
|
||||
// Added width and height fields
|
||||
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN width INTEGER;");
|
||||
db.execSQL("UPDATE " + TABLE_NAME + " SET width = 0");
|
||||
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN height INTEGER;");
|
||||
db.execSQL("UPDATE " + TABLE_NAME + " SET height = 0");
|
||||
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN license STRING;");
|
||||
db.execSQL("UPDATE " + TABLE_NAME + " SET license='" + Prefs.Licenses.CC_BY_SA_3 + "';");
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String licenseTemplateFor(String license) {
|
||||
switch (license) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,244 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import fr.free.nrw.commons.settings.Prefs;
|
||||
|
||||
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI;
|
||||
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.uriForId;
|
||||
|
||||
public class ContributionDao {
|
||||
private final ContentProviderClient client;
|
||||
|
||||
public ContributionDao(ContentProviderClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public void save(Contribution contribution) {
|
||||
try {
|
||||
if (contribution.getContentUri() == null) {
|
||||
contribution.setContentUri(client.insert(BASE_URI, toContentValues(contribution)));
|
||||
} else {
|
||||
client.update(contribution.getContentUri(), toContentValues(contribution), null, null);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(Contribution contribution) {
|
||||
try {
|
||||
if (contribution.getContentUri() == null) {
|
||||
// noooo
|
||||
throw new RuntimeException("tried to delete item with no content URI");
|
||||
} else {
|
||||
client.delete(contribution.getContentUri(), null, null);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static ContentValues toContentValues(Contribution contribution) {
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(Table.COLUMN_FILENAME, contribution.getFilename());
|
||||
if (contribution.getLocalUri() != null) {
|
||||
cv.put(Table.COLUMN_LOCAL_URI, contribution.getLocalUri().toString());
|
||||
}
|
||||
if (contribution.getImageUrl() != null) {
|
||||
cv.put(Table.COLUMN_IMAGE_URL, contribution.getImageUrl());
|
||||
}
|
||||
if (contribution.getDateUploaded() != null) {
|
||||
cv.put(Table.COLUMN_UPLOADED, contribution.getDateUploaded().getTime());
|
||||
}
|
||||
cv.put(Table.COLUMN_LENGTH, contribution.getDataLength());
|
||||
cv.put(Table.COLUMN_TIMESTAMP, contribution.getTimestamp().getTime());
|
||||
cv.put(Table.COLUMN_STATE, contribution.getState());
|
||||
cv.put(Table.COLUMN_TRANSFERRED, contribution.getTransferred());
|
||||
cv.put(Table.COLUMN_SOURCE, contribution.getSource());
|
||||
cv.put(Table.COLUMN_DESCRIPTION, contribution.getDescription());
|
||||
cv.put(Table.COLUMN_CREATOR, contribution.getCreator());
|
||||
cv.put(Table.COLUMN_MULTIPLE, contribution.getMultiple() ? 1 : 0);
|
||||
cv.put(Table.COLUMN_WIDTH, contribution.getWidth());
|
||||
cv.put(Table.COLUMN_HEIGHT, contribution.getHeight());
|
||||
cv.put(Table.COLUMN_LICENSE, contribution.getLicense());
|
||||
return cv;
|
||||
}
|
||||
|
||||
public static Contribution fromCursor(Cursor cursor) {
|
||||
// Hardcoding column positions!
|
||||
//Check that cursor has a value to avoid CursorIndexOutOfBoundsException
|
||||
if (cursor.getCount() > 0) {
|
||||
return new Contribution(
|
||||
uriForId(cursor.getInt(0)),
|
||||
cursor.getString(1),
|
||||
parseUri(cursor.getString(2)),
|
||||
cursor.getString(3),
|
||||
parseTimestamp(cursor.getLong(4)),
|
||||
cursor.getInt(5),
|
||||
cursor.getLong(6),
|
||||
parseTimestamp(cursor.getLong(7)),
|
||||
cursor.getLong(8),
|
||||
cursor.getString(9),
|
||||
cursor.getString(10),
|
||||
cursor.getString(11),
|
||||
cursor.getInt(12) == 1,
|
||||
cursor.getInt(13),
|
||||
cursor.getInt(14),
|
||||
cursor.getString(15));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Date parseTimestamp(long timestamp) {
|
||||
return timestamp == 0 ? null : new Date(timestamp);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Uri parseUri(String uriString) {
|
||||
return TextUtils.isEmpty(uriString) ? null : Uri.parse(uriString);
|
||||
}
|
||||
|
||||
public static class Table {
|
||||
public static final String TABLE_NAME = "contributions";
|
||||
|
||||
public static final String COLUMN_ID = "_id";
|
||||
public static final String COLUMN_FILENAME = "filename";
|
||||
public static final String COLUMN_LOCAL_URI = "local_uri";
|
||||
public static final String COLUMN_IMAGE_URL = "image_url";
|
||||
public static final String COLUMN_TIMESTAMP = "timestamp";
|
||||
public static final String COLUMN_STATE = "state";
|
||||
public static final String COLUMN_LENGTH = "length";
|
||||
public static final String COLUMN_UPLOADED = "uploaded";
|
||||
public static final String COLUMN_TRANSFERRED = "transferred"; // Currently transferred number of bytes
|
||||
public static final String COLUMN_SOURCE = "source";
|
||||
public static final String COLUMN_DESCRIPTION = "description";
|
||||
public static final String COLUMN_CREATOR = "creator"; // Initial uploader
|
||||
public static final String COLUMN_MULTIPLE = "multiple";
|
||||
public static final String COLUMN_WIDTH = "width";
|
||||
public static final String COLUMN_HEIGHT = "height";
|
||||
public static final String COLUMN_LICENSE = "license";
|
||||
|
||||
// NOTE! KEEP IN SAME ORDER AS THEY ARE DEFINED UP THERE. HELPS HARD CODE COLUMN INDICES.
|
||||
public static final String[] ALL_FIELDS = {
|
||||
COLUMN_ID,
|
||||
COLUMN_FILENAME,
|
||||
COLUMN_LOCAL_URI,
|
||||
COLUMN_IMAGE_URL,
|
||||
COLUMN_TIMESTAMP,
|
||||
COLUMN_STATE,
|
||||
COLUMN_LENGTH,
|
||||
COLUMN_UPLOADED,
|
||||
COLUMN_TRANSFERRED,
|
||||
COLUMN_SOURCE,
|
||||
COLUMN_DESCRIPTION,
|
||||
COLUMN_CREATOR,
|
||||
COLUMN_MULTIPLE,
|
||||
COLUMN_WIDTH,
|
||||
COLUMN_HEIGHT,
|
||||
COLUMN_LICENSE
|
||||
};
|
||||
|
||||
public static final String DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS " + TABLE_NAME;
|
||||
|
||||
public static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " ("
|
||||
+ "_id INTEGER PRIMARY KEY,"
|
||||
+ "filename STRING,"
|
||||
+ "local_uri STRING,"
|
||||
+ "image_url STRING,"
|
||||
+ "uploaded INTEGER,"
|
||||
+ "timestamp INTEGER,"
|
||||
+ "state INTEGER,"
|
||||
+ "length INTEGER,"
|
||||
+ "transferred INTEGER,"
|
||||
+ "source STRING,"
|
||||
+ "description STRING,"
|
||||
+ "creator STRING,"
|
||||
+ "multiple INTEGER,"
|
||||
+ "width INTEGER,"
|
||||
+ "height INTEGER,"
|
||||
+ "LICENSE STRING"
|
||||
+ ");";
|
||||
|
||||
// Upgrade from version 1 ->
|
||||
static final String ADD_CREATOR_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN creator STRING;";
|
||||
static final String ADD_DESCRIPTION_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN description STRING;";
|
||||
|
||||
// Upgrade from version 2 ->
|
||||
static final String ADD_MULTIPLE_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN multiple INTEGER;";
|
||||
static final String SET_DEFAULT_MULTIPLE = "UPDATE " + TABLE_NAME + " SET multiple = 0";
|
||||
|
||||
// Upgrade from version 5 ->
|
||||
static final String ADD_WIDTH_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN width INTEGER;";
|
||||
static final String SET_DEFAULT_WIDTH = "UPDATE " + TABLE_NAME + " SET width = 0";
|
||||
static final String ADD_HEIGHT_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN height INTEGER;";
|
||||
static final String SET_DEFAULT_HEIGHT = "UPDATE " + TABLE_NAME + " SET height = 0";
|
||||
static final String ADD_LICENSE_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN license STRING;";
|
||||
static final String SET_DEFAULT_LICENSE = "UPDATE " + TABLE_NAME + " SET license='" + Prefs.Licenses.CC_BY_SA_3 + "';";
|
||||
|
||||
|
||||
public static void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(CREATE_TABLE_STATEMENT);
|
||||
}
|
||||
|
||||
public static void onDelete(SQLiteDatabase db) {
|
||||
db.execSQL(DROP_TABLE_STATEMENT);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public static void onUpdate(SQLiteDatabase db, int from, int to) {
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
if (from == 1) {
|
||||
db.execSQL(ADD_DESCRIPTION_FIELD);
|
||||
db.execSQL(ADD_CREATOR_FIELD);
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 2) {
|
||||
db.execSQL(ADD_MULTIPLE_FIELD);
|
||||
db.execSQL(SET_DEFAULT_MULTIPLE);
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 3) {
|
||||
// Do nothing
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 4) {
|
||||
// Do nothing -- added Category
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
if (from == 5) {
|
||||
// Added width and height fields
|
||||
db.execSQL(ADD_WIDTH_FIELD);
|
||||
db.execSQL(SET_DEFAULT_WIDTH);
|
||||
db.execSQL(ADD_HEIGHT_FIELD);
|
||||
db.execSQL(SET_DEFAULT_HEIGHT);
|
||||
db.execSQL(ADD_LICENSE_FIELD);
|
||||
db.execSQL(SET_DEFAULT_LICENSE);
|
||||
from++;
|
||||
onUpdate(db, from, to);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ import timber.log.Timber;
|
|||
|
||||
import static android.content.ContentResolver.requestSync;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.STATE_FAILED;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.Table.ALL_FIELDS;
|
||||
import static fr.free.nrw.commons.contributions.ContributionDao.Table.ALL_FIELDS;
|
||||
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.AUTHORITY;
|
||||
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI;
|
||||
import static fr.free.nrw.commons.settings.Prefs.UPLOADS_SHOWING;
|
||||
|
|
@ -76,10 +76,10 @@ public class ContributionsActivity
|
|||
|
||||
This is why Contribution.STATE_COMPLETED is -1.
|
||||
*/
|
||||
private String CONTRIBUTION_SORT = Contribution.Table.COLUMN_STATE + " DESC, "
|
||||
+ Contribution.Table.COLUMN_UPLOADED + " DESC , ("
|
||||
+ Contribution.Table.COLUMN_TIMESTAMP + " * "
|
||||
+ Contribution.Table.COLUMN_STATE + ")";
|
||||
private String CONTRIBUTION_SORT = ContributionDao.Table.COLUMN_STATE + " DESC, "
|
||||
+ ContributionDao.Table.COLUMN_UPLOADED + " DESC , ("
|
||||
+ ContributionDao.Table.COLUMN_TIMESTAMP + " * "
|
||||
+ ContributionDao.Table.COLUMN_STATE + ")";
|
||||
|
||||
private CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
|
|
@ -186,24 +186,23 @@ public class ContributionsActivity
|
|||
|
||||
public void retryUpload(int i) {
|
||||
allContributions.moveToPosition(i);
|
||||
Contribution c = Contribution.fromCursor(allContributions);
|
||||
Contribution c = ContributionDao.fromCursor(allContributions);
|
||||
if (c.getState() == STATE_FAILED) {
|
||||
uploadService.queue(UploadService.ACTION_UPLOAD_FILE, c);
|
||||
Timber.d("Restarting for %s", c.toContentValues());
|
||||
Timber.d("Restarting for %s", c.toString());
|
||||
} else {
|
||||
Timber.d("Skipping re-upload for non-failed %s", c.toContentValues());
|
||||
Timber.d("Skipping re-upload for non-failed %s", c.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteUpload(int i) {
|
||||
allContributions.moveToPosition(i);
|
||||
Contribution c = Contribution.fromCursor(allContributions);
|
||||
Contribution c = ContributionDao.fromCursor(allContributions);
|
||||
if (c.getState() == STATE_FAILED) {
|
||||
Timber.d("Deleting failed contrib %s", c.toContentValues());
|
||||
c.setContentProviderClient(getContentResolver().acquireContentProviderClient(AUTHORITY));
|
||||
c.delete();
|
||||
Timber.d("Deleting failed contrib %s", c.toString());
|
||||
new ContributionDao(getContentResolver().acquireContentProviderClient(AUTHORITY)).delete(c);
|
||||
} else {
|
||||
Timber.d("Skipping deletion for non-failed contrib %s", c.toContentValues());
|
||||
Timber.d("Skipping deletion for non-failed contrib %s", c.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +269,7 @@ public class ContributionsActivity
|
|||
// not yet ready to return data
|
||||
return null;
|
||||
} else {
|
||||
return Contribution.fromCursor((Cursor) contributionsList.getAdapter().getItem(i));
|
||||
return ContributionDao.fromCursor((Cursor) contributionsList.getAdapter().getItem(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ import fr.free.nrw.commons.data.DBOpenHelper;
|
|||
import timber.log.Timber;
|
||||
|
||||
import static android.content.UriMatcher.NO_MATCH;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.Table.ALL_FIELDS;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.Table.TABLE_NAME;
|
||||
import static fr.free.nrw.commons.contributions.ContributionDao.Table.ALL_FIELDS;
|
||||
import static fr.free.nrw.commons.contributions.ContributionDao.Table.TABLE_NAME;
|
||||
|
||||
public class ContributionsContentProvider extends ContentProvider {
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ public class ContributionsContentProvider extends ContentProvider {
|
|||
if (TextUtils.isEmpty(selection)) {
|
||||
rowsUpdated = sqlDB.update(TABLE_NAME,
|
||||
contentValues,
|
||||
Contribution.Table.COLUMN_ID + " = ?",
|
||||
ContributionDao.Table.COLUMN_ID + " = ?",
|
||||
new String[]{String.valueOf(id)});
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class ContributionsListAdapter extends CursorAdapter {
|
|||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ContributionViewHolder views = (ContributionViewHolder)view.getTag();
|
||||
final Contribution contribution = Contribution.fromCursor(cursor);
|
||||
final Contribution contribution = ContributionDao.fromCursor(cursor);
|
||||
|
||||
views.imageView.setMedia(contribution);
|
||||
views.titleView.setText(contribution.getDisplayTitle());
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
|||
import timber.log.Timber;
|
||||
|
||||
import static fr.free.nrw.commons.contributions.Contribution.STATE_COMPLETED;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.Table.COLUMN_FILENAME;
|
||||
import static fr.free.nrw.commons.contributions.ContributionDao.Table.COLUMN_FILENAME;
|
||||
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
|
|
@ -121,7 +121,7 @@ public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
"", -1, dateUpdated, dateUpdated, user,
|
||||
"", "");
|
||||
contrib.setState(STATE_COMPLETED);
|
||||
imageValues.add(contrib.toContentValues());
|
||||
imageValues.add(ContributionDao.toContentValues(contrib));
|
||||
|
||||
if (imageValues.size() % COMMIT_THRESHOLD == 0) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import android.content.Context;
|
|||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.contributions.ContributionDao;
|
||||
import fr.free.nrw.commons.modifications.ModifierSequence;
|
||||
|
||||
public class DBOpenHelper extends SQLiteOpenHelper {
|
||||
|
|
@ -21,14 +21,14 @@ public class DBOpenHelper extends SQLiteOpenHelper {
|
|||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase sqLiteDatabase) {
|
||||
Contribution.Table.onCreate(sqLiteDatabase);
|
||||
ContributionDao.Table.onCreate(sqLiteDatabase);
|
||||
ModifierSequence.Table.onCreate(sqLiteDatabase);
|
||||
Category.Table.onCreate(sqLiteDatabase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int from, int to) {
|
||||
Contribution.Table.onUpdate(sqLiteDatabase, from, to);
|
||||
ContributionDao.Table.onUpdate(sqLiteDatabase, from, to);
|
||||
ModifierSequence.Table.onUpdate(sqLiteDatabase, from, to);
|
||||
Category.Table.onUpdate(sqLiteDatabase, from, to);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import javax.inject.Inject;
|
|||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.contributions.ContributionDao;
|
||||
import fr.free.nrw.commons.contributions.ContributionsContentProvider;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import timber.log.Timber;
|
||||
|
|
@ -93,7 +94,7 @@ public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
contributionCursor.moveToFirst();
|
||||
contrib = Contribution.fromCursor(contributionCursor);
|
||||
contrib = ContributionDao.fromCursor(contributionCursor);
|
||||
|
||||
if (contrib.getState() == Contribution.STATE_COMPLETED) {
|
||||
String pageContent;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import fr.free.nrw.commons.R;
|
|||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.contributions.ContributionDao;
|
||||
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
||||
import fr.free.nrw.commons.contributions.ContributionsContentProvider;
|
||||
import fr.free.nrw.commons.modifications.ModificationsContentProvider;
|
||||
|
|
@ -66,6 +67,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
public static final int NOTIFICATION_UPLOAD_IN_PROGRESS = 1;
|
||||
public static final int NOTIFICATION_UPLOAD_COMPLETE = 2;
|
||||
public static final int NOTIFICATION_UPLOAD_FAILED = 3;
|
||||
private ContributionDao dao;
|
||||
|
||||
public UploadService() {
|
||||
super("UploadService");
|
||||
|
|
@ -105,7 +107,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
startForeground(NOTIFICATION_UPLOAD_IN_PROGRESS, curProgressNotification.build());
|
||||
|
||||
contribution.setTransferred(transferred);
|
||||
contribution.save();
|
||||
dao.save(contribution);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -123,6 +125,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
|
||||
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
contributionsProviderClient = this.getContentResolver().acquireContentProviderClient(ContributionsContentProvider.AUTHORITY);
|
||||
dao = new ContributionDao(contributionsProviderClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -144,9 +147,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
|
||||
contribution.setState(Contribution.STATE_QUEUED);
|
||||
contribution.setTransferred(0);
|
||||
contribution.setContentProviderClient(contributionsProviderClient);
|
||||
|
||||
contribution.save();
|
||||
dao.save(contribution);
|
||||
toUpload++;
|
||||
if (curProgressNotification != null && toUpload != 1) {
|
||||
curProgressNotification.setContentText(getResources().getQuantityString(R.plurals.uploads_pending_notification_indicator, toUpload, toUpload));
|
||||
|
|
@ -167,11 +168,11 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (intent.getAction().equals(ACTION_START_SERVICE) && freshStart) {
|
||||
ContentValues failedValues = new ContentValues();
|
||||
failedValues.put(Contribution.Table.COLUMN_STATE, Contribution.STATE_FAILED);
|
||||
failedValues.put(ContributionDao.Table.COLUMN_STATE, Contribution.STATE_FAILED);
|
||||
|
||||
int updated = getContentResolver().update(ContributionsContentProvider.BASE_URI,
|
||||
failedValues,
|
||||
Contribution.Table.COLUMN_STATE + " = ? OR " + Contribution.Table.COLUMN_STATE + " = ?",
|
||||
ContributionDao.Table.COLUMN_STATE + " = ? OR " + ContributionDao.Table.COLUMN_STATE + " = ?",
|
||||
new String[]{ String.valueOf(Contribution.STATE_QUEUED), String.valueOf(Contribution.STATE_IN_PROGRESS) }
|
||||
);
|
||||
Timber.d("Set %d uploads to failed", updated);
|
||||
|
|
@ -261,7 +262,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
contribution.setImageUrl(uploadResult.getImageUrl());
|
||||
contribution.setState(Contribution.STATE_COMPLETED);
|
||||
contribution.setDateUploaded(uploadResult.getDateUploaded());
|
||||
contribution.save();
|
||||
dao.save(contribution);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Timber.d("I have a network fuckup");
|
||||
|
|
@ -292,7 +293,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
notificationManager.notify(NOTIFICATION_UPLOAD_FAILED, failureNotification);
|
||||
|
||||
contribution.setState(Contribution.STATE_FAILED);
|
||||
contribution.save();
|
||||
dao.save(contribution);
|
||||
}
|
||||
|
||||
private String findUniqueFilename(String fileName) throws IOException {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,367 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.ContentValues;
|
||||
import android.database.MatrixCursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.TestCommonsApplication;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
|
||||
import static fr.free.nrw.commons.contributions.Contribution.SOURCE_CAMERA;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.SOURCE_GALLERY;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.STATE_COMPLETED;
|
||||
import static fr.free.nrw.commons.contributions.Contribution.STATE_QUEUED;
|
||||
import static fr.free.nrw.commons.contributions.ContributionDao.*;
|
||||
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI;
|
||||
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.uriForId;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.isA;
|
||||
import static org.mockito.Matchers.isNull;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(constants = BuildConfig.class, sdk = 21, application = TestCommonsApplication.class)
|
||||
public class ContributionDaoTest {
|
||||
|
||||
private static final String LOCAL_URI = "http://example.com/";
|
||||
@Mock
|
||||
ContentProviderClient client;
|
||||
@Mock
|
||||
SQLiteDatabase database;
|
||||
@Captor
|
||||
ArgumentCaptor<ContentValues> captor;
|
||||
|
||||
private Uri contentUri;
|
||||
private ContributionDao testObject;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
contentUri = uriForId(111);
|
||||
|
||||
testObject = new ContributionDao(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createTable() {
|
||||
Table.onCreate(database);
|
||||
verify(database).execSQL(Table.CREATE_TABLE_STATEMENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteTable() {
|
||||
Table.onDelete(database);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(database);
|
||||
inOrder.verify(database).execSQL(Table.DROP_TABLE_STATEMENT);
|
||||
inOrder.verify(database).execSQL(Table.CREATE_TABLE_STATEMENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upgradeDatabase_v1_to_v2() {
|
||||
Table.onUpdate(database, 1, 2);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(database);
|
||||
inOrder.verify(database).execSQL(Table.ADD_DESCRIPTION_FIELD);
|
||||
inOrder.verify(database).execSQL(Table.ADD_CREATOR_FIELD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upgradeDatabase_v2_to_v3() {
|
||||
Table.onUpdate(database, 2, 3);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(database);
|
||||
inOrder.verify(database).execSQL(Table.ADD_MULTIPLE_FIELD);
|
||||
inOrder.verify(database).execSQL(Table.SET_DEFAULT_MULTIPLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upgradeDatabase_v3_to_v4() {
|
||||
Table.onUpdate(database, 3, 4);
|
||||
|
||||
// No changes
|
||||
verifyZeroInteractions(database);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upgradeDatabase_v4_to_v5() {
|
||||
Table.onUpdate(database, 4, 5);
|
||||
|
||||
// No changes
|
||||
verifyZeroInteractions(database);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upgradeDatabase_v5_to_v6() {
|
||||
Table.onUpdate(database, 5, 6);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(database);
|
||||
inOrder.verify(database).execSQL(Table.ADD_WIDTH_FIELD);
|
||||
inOrder.verify(database).execSQL(Table.SET_DEFAULT_WIDTH);
|
||||
inOrder.verify(database).execSQL(Table.ADD_HEIGHT_FIELD);
|
||||
inOrder.verify(database).execSQL(Table.SET_DEFAULT_HEIGHT);
|
||||
inOrder.verify(database).execSQL(Table.ADD_LICENSE_FIELD);
|
||||
inOrder.verify(database).execSQL(Table.SET_DEFAULT_LICENSE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveNewContribution_nonNullFields() throws Exception {
|
||||
when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri);
|
||||
Contribution contribution = createContribution(true, null, null, null, null);
|
||||
|
||||
testObject.save(contribution);
|
||||
|
||||
assertEquals(contentUri, contribution.getContentUri());
|
||||
verify(client).insert(eq(BASE_URI), captor.capture());
|
||||
ContentValues cv = captor.getValue();
|
||||
|
||||
// Long fields
|
||||
assertEquals(222L, cv.getAsLong(Table.COLUMN_LENGTH).longValue());
|
||||
assertEquals(321L, cv.getAsLong(Table.COLUMN_TIMESTAMP).longValue());
|
||||
assertEquals(333L, cv.getAsLong(Table.COLUMN_TRANSFERRED).longValue());
|
||||
|
||||
// Integer fields
|
||||
assertEquals(STATE_COMPLETED, cv.getAsInteger(Table.COLUMN_STATE).intValue());
|
||||
assertEquals(640, cv.getAsInteger(Table.COLUMN_WIDTH).intValue());
|
||||
assertEquals(480, cv.getAsInteger(Table.COLUMN_HEIGHT).intValue());
|
||||
|
||||
// String fields
|
||||
assertEquals(SOURCE_CAMERA, cv.getAsString(Table.COLUMN_SOURCE));
|
||||
assertEquals("desc", cv.getAsString(Table.COLUMN_DESCRIPTION));
|
||||
assertEquals("create", cv.getAsString(Table.COLUMN_CREATOR));
|
||||
assertEquals("007", cv.getAsString(Table.COLUMN_LICENSE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveNewContribution_nullableFieldsAreNull() throws Exception {
|
||||
when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri);
|
||||
Contribution contribution = createContribution(true, null, null, null, null);
|
||||
|
||||
testObject.save(contribution);
|
||||
|
||||
assertEquals(contentUri, contribution.getContentUri());
|
||||
verify(client).insert(eq(BASE_URI), captor.capture());
|
||||
ContentValues cv = captor.getValue();
|
||||
|
||||
// Nullable fields are absent if null
|
||||
assertFalse(cv.containsKey(Table.COLUMN_LOCAL_URI));
|
||||
assertFalse(cv.containsKey(Table.COLUMN_IMAGE_URL));
|
||||
assertFalse(cv.containsKey(Table.COLUMN_UPLOADED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveNewContribution_nullableImageUrlUsesFileAsBackup() throws Exception {
|
||||
when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri);
|
||||
Contribution contribution = createContribution(true, null, null, null, "file");
|
||||
|
||||
testObject.save(contribution);
|
||||
|
||||
assertEquals(contentUri, contribution.getContentUri());
|
||||
verify(client).insert(eq(BASE_URI), captor.capture());
|
||||
ContentValues cv = captor.getValue();
|
||||
|
||||
// Nullable fields are absent if null
|
||||
assertFalse(cv.containsKey(Table.COLUMN_LOCAL_URI));
|
||||
assertFalse(cv.containsKey(Table.COLUMN_UPLOADED));
|
||||
|
||||
assertEquals(Utils.makeThumbBaseUrl("file"), cv.getAsString(Table.COLUMN_IMAGE_URL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveNewContribution_nullableFieldsAreNonNull() throws Exception {
|
||||
when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri);
|
||||
Contribution contribution = createContribution(true, Uri.parse(LOCAL_URI),
|
||||
"image", new Date(456L), null);
|
||||
|
||||
testObject.save(contribution);
|
||||
|
||||
assertEquals(contentUri, contribution.getContentUri());
|
||||
verify(client).insert(eq(BASE_URI), captor.capture());
|
||||
ContentValues cv = captor.getValue();
|
||||
|
||||
assertEquals(LOCAL_URI, cv.getAsString(Table.COLUMN_LOCAL_URI));
|
||||
assertEquals("image", cv.getAsString(Table.COLUMN_IMAGE_URL));
|
||||
assertEquals(456L, cv.getAsLong(Table.COLUMN_UPLOADED).longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveNewContribution_booleanEncodesTrue() throws Exception {
|
||||
when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri);
|
||||
Contribution contribution = createContribution(true, null, null, null, null);
|
||||
|
||||
testObject.save(contribution);
|
||||
|
||||
assertEquals(contentUri, contribution.getContentUri());
|
||||
verify(client).insert(eq(BASE_URI), captor.capture());
|
||||
ContentValues cv = captor.getValue();
|
||||
|
||||
// Boolean true --> 1 for ths encoding scheme
|
||||
assertEquals("Boolean true should be encoded as 1", 1,
|
||||
cv.getAsInteger(Table.COLUMN_MULTIPLE).intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveNewContribution_booleanEncodesFalse() throws Exception {
|
||||
when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri);
|
||||
Contribution contribution = createContribution(false, null, null, null, null);
|
||||
|
||||
testObject.save(contribution);
|
||||
|
||||
assertEquals(contentUri, contribution.getContentUri());
|
||||
verify(client).insert(eq(BASE_URI), captor.capture());
|
||||
ContentValues cv = captor.getValue();
|
||||
|
||||
// Boolean true --> 1 for ths encoding scheme
|
||||
assertEquals("Boolean false should be encoded as 0", 0,
|
||||
cv.getAsInteger(Table.COLUMN_MULTIPLE).intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveExistingContribution() throws Exception {
|
||||
Contribution contribution = createContribution(false, null, null, null, null);
|
||||
contribution.setContentUri(contentUri);
|
||||
|
||||
testObject.save(contribution);
|
||||
|
||||
verify(client).update(eq(contentUri), isA(ContentValues.class), isNull(String.class), isNull(String[].class));
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void saveTranslatesExceptions() throws Exception {
|
||||
when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenThrow(new RemoteException(""));
|
||||
|
||||
testObject.save(createContribution(false, null, null, null, null));
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void deleteTranslatesExceptions() throws Exception {
|
||||
when(client.delete(isA(Uri.class), any(), any())).thenThrow(new RemoteException(""));
|
||||
|
||||
Contribution contribution = createContribution(false, null, null, null, null);
|
||||
contribution.setContentUri(contentUri);
|
||||
testObject.delete(contribution);
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void exceptionThrownWhenAttemptingToDeleteUnsavedContribution() {
|
||||
testObject.delete(createContribution(false, null, null, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteExistingContribution() throws Exception {
|
||||
Contribution contribution = createContribution(false, null, null, null, null);
|
||||
contribution.setContentUri(contentUri);
|
||||
|
||||
testObject.delete(contribution);
|
||||
|
||||
verify(client).delete(eq(contentUri), isNull(String.class), isNull(String[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createFromCursor() {
|
||||
long created = 321L;
|
||||
long uploaded = 456L;
|
||||
MatrixCursor mc = createCursor(created, uploaded, false, LOCAL_URI);
|
||||
|
||||
Contribution c = ContributionDao.fromCursor(mc);
|
||||
|
||||
assertEquals(uriForId(111), c.getContentUri());
|
||||
assertEquals("file", c.getFilename());
|
||||
assertEquals(LOCAL_URI, c.getLocalUri().toString());
|
||||
assertEquals("image", c.getImageUrl());
|
||||
assertEquals(created, c.getTimestamp().getTime());
|
||||
assertEquals(created, c.getDateCreated().getTime());
|
||||
assertEquals(STATE_QUEUED, c.getState());
|
||||
assertEquals(222L, c.getDataLength());
|
||||
assertEquals(uploaded, c.getDateUploaded().getTime());
|
||||
assertEquals(88L, c.getTransferred());
|
||||
assertEquals(SOURCE_GALLERY, c.getSource());
|
||||
assertEquals("desc", c.getDescription());
|
||||
assertEquals("create", c.getCreator());
|
||||
assertEquals(640, c.getWidth());
|
||||
assertEquals(480, c.getHeight());
|
||||
assertEquals("007", c.getLicense());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createFromCursor_nullableTimestamps() {
|
||||
MatrixCursor mc = createCursor(0L, 0L, false, LOCAL_URI);
|
||||
|
||||
Contribution c = ContributionDao.fromCursor(mc);
|
||||
|
||||
assertNull(c.getTimestamp());
|
||||
assertNull(c.getDateCreated());
|
||||
assertNull(c.getDateUploaded());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createFromCursor_nullableLocalUri() {
|
||||
MatrixCursor mc = createCursor(0L, 0L, false, "");
|
||||
|
||||
Contribution c = ContributionDao.fromCursor(mc);
|
||||
|
||||
assertNull(c.getLocalUri());
|
||||
assertNull(c.getDateCreated());
|
||||
assertNull(c.getDateUploaded());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createFromCursor_booleanEncoding() {
|
||||
MatrixCursor mcFalse = createCursor(0L, 0L, false, LOCAL_URI);
|
||||
assertFalse(ContributionDao.fromCursor(mcFalse).getMultiple());
|
||||
|
||||
MatrixCursor mcHammer = createCursor(0L, 0L, true, LOCAL_URI);
|
||||
assertTrue(ContributionDao.fromCursor(mcHammer).getMultiple());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private MatrixCursor createCursor(long created, long uploaded, boolean multiple, String localUri) {
|
||||
MatrixCursor mc = new MatrixCursor(Table.ALL_FIELDS, 1);
|
||||
mc.addRow(Arrays.asList("111", "file", localUri, "image",
|
||||
created, STATE_QUEUED, 222L, uploaded, 88L, SOURCE_GALLERY, "desc",
|
||||
"create", multiple ? 1 : 0, 640, 480, "007"));
|
||||
mc.moveToFirst();
|
||||
return mc;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Contribution createContribution(boolean multiple, Uri localUri,
|
||||
String imageUrl, Date dateUploaded, String filename) {
|
||||
Contribution contribution = new Contribution(localUri, imageUrl, filename, "desc", 222L,
|
||||
new Date(321L), dateUploaded, "create", "edit", "coords");
|
||||
contribution.setState(STATE_COMPLETED);
|
||||
contribution.setTransferred(333L);
|
||||
contribution.setSource(SOURCE_CAMERA);
|
||||
contribution.setLicense("007");
|
||||
contribution.setMultiple(multiple);
|
||||
contribution.setTimestamp(new Date(321L));
|
||||
contribution.setWidth(640);
|
||||
contribution.setHeight(480); // VGA should be enough for anyone, right?
|
||||
return contribution;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue