package org.dodgybits.shuffle.android.core.model.persistence; import static org.dodgybits.shuffle.android.core.util.Constants.cFlurryCountParam; import static org.dodgybits.shuffle.android.core.util.Constants.cFlurryCreateEntityEvent; import static org.dodgybits.shuffle.android.core.util.Constants.cFlurryDeleteEntityEvent; import static org.dodgybits.shuffle.android.core.util.Constants.cFlurryEntityTypeParam; import static org.dodgybits.shuffle.android.core.util.Constants.cFlurryUpdateEntityEvent; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.dodgybits.shuffle.android.core.activity.flurry.Analytics; import org.dodgybits.shuffle.android.core.model.Entity; import org.dodgybits.shuffle.android.core.model.Id; import org.dodgybits.shuffle.android.persistence.provider.AbstractCollectionProvider.ShuffleTable; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.provider.BaseColumns; public abstract class AbstractEntityPersister<E extends Entity> implements EntityPersister<E> { protected Analytics mAnalytics; protected ContentResolver mResolver; protected Map<String, String> mFlurryParams; public AbstractEntityPersister(ContentResolver resolver, Analytics analytics) { mResolver = resolver; mAnalytics = analytics; Map<String, String> params = new HashMap<String,String>(); params.put(cFlurryEntityTypeParam, getEntityName()); mFlurryParams = Collections.unmodifiableMap(params); } @Override public E findById(Id localId) { E entity = null; if (localId.isInitialised()) { Cursor cursor = mResolver.query( getContentUri(), getFullProjection(), BaseColumns._ID + " = ?", new String[] {localId.toString()}, null); if (cursor.moveToFirst()) { entity = read(cursor); } cursor.close(); } return entity; } @Override public Uri insert(E e) { validate(e); Uri uri = mResolver.insert(getContentUri(), null); update(uri, e); mAnalytics.onEvent(cFlurryCreateEntityEvent, mFlurryParams); return uri; } @Override public void bulkInsert(Collection<E> entities) { int numEntities = entities.size(); if (numEntities > 0) { ContentValues[] valuesArray = new ContentValues[numEntities]; int i = 0; for(E entity : entities) { validate(entity); ContentValues values = new ContentValues(); writeContentValues(values, entity); valuesArray[i++] = values; } int rowsCreated = mResolver.bulkInsert(getContentUri(), valuesArray); Map<String, String> params = new HashMap<String, String>(mFlurryParams); params.put(cFlurryCountParam, String.valueOf(rowsCreated)); mAnalytics.onEvent(cFlurryCreateEntityEvent, params); } } @Override public void update(E e) { validate(e); Uri uri = getUri(e); update(uri, e); mAnalytics.onEvent(cFlurryUpdateEntityEvent, mFlurryParams); } @Override public boolean moveToTrash(Id id) { ContentValues values = new ContentValues(); values.put(ShuffleTable.DELETED, true); values.put(ShuffleTable.MODIFIED_DATE, System.currentTimeMillis()); return (mResolver.update(getUri(id), values, null, null) == 1); } @Override public int moveToTrash(String selection, String[] selectionArgs) { ContentValues values = new ContentValues(); values.put(ShuffleTable.DELETED, true); values.put(ShuffleTable.MODIFIED_DATE, System.currentTimeMillis()); return mResolver.update(getContentUri(), values, selection, selectionArgs); } public boolean putBack(Id id) { ContentValues values = new ContentValues(); values.put(ShuffleTable.DELETED, false); values.put(ShuffleTable.MODIFIED_DATE, System.currentTimeMillis()); return (mResolver.update(getUri(id), values, null, null) == 1); } @Override public int emptyTrash() { int rowsDeleted = mResolver.delete(getContentUri(), "deleted = 1", null); Map<String, String> params = new HashMap<String, String>(mFlurryParams); params.put(cFlurryCountParam, String.valueOf(rowsDeleted)); mAnalytics.onEvent(cFlurryDeleteEntityEvent, params); return rowsDeleted; } @Override public boolean deletePermanently(Id id) { Uri uri = getUri(id); boolean success = (mResolver.delete(uri, null, null) == 1); if (success) { mAnalytics.onEvent(cFlurryDeleteEntityEvent, mFlurryParams); } return success; } abstract public Uri getContentUri(); abstract protected void writeContentValues(ContentValues values, E e); abstract protected String getEntityName(); private void validate(E e) { if (e == null || !e.isValid()) { throw new IllegalArgumentException("Cannot persist uninitialised entity " + e); } } private Uri getUri(E e) { return getUri(e.getLocalId()); } private Uri getUri(Id localId) { return ContentUris.appendId( getContentUri().buildUpon(), localId.getId()).build(); } private void update(Uri uri, E e) { ContentValues values = new ContentValues(); writeContentValues(values, e); mResolver.update(uri, values, null, null); } protected static Id readId(Cursor cursor, int index) { Id result = Id.NONE; if (!cursor.isNull(index)) { result = Id.create(cursor.getLong(index)); } return result; } protected static String readString(Cursor cursor, int index) { return (cursor.isNull(index) ? null : cursor.getString(index)); } protected static long readLong(Cursor cursor, int index) { return readLong(cursor, index, 0L); } protected static long readLong(Cursor cursor, int index, long defaultValue) { long result = defaultValue; if (!cursor.isNull(index)) { result = cursor.getLong(index); } return result; } protected static Boolean readBoolean(Cursor cursor, int index) { return (cursor.getInt(index) == 1); } protected static void writeId(ContentValues values, String key, Id id) { if (id.isInitialised()) { values.put(key, id.getId()); } else { values.putNull(key); } } protected static void writeBoolean(ContentValues values, String key, boolean value) { values.put(key, value ? 1 : 0); } protected static void writeString(ContentValues values, String key, String value) { if (value == null) { values.putNull(key); } else { values.put(key, value); } } }