Refactored transitory preservation to be structured better

pull/14/head
Sam Bosley 13 years ago
parent ea42bb828c
commit c44b884f3a

@ -11,8 +11,6 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import android.content.ContentValues;
@ -319,7 +317,6 @@ public abstract class AbstractModel implements Parcelable, Cloneable {
public synchronized <TYPE> void mergeWith(ContentValues other) {
if (setValues == null)
setValues = new ContentValues();
restoreTransitories(other);
setValues.putAll(other);
}
@ -378,76 +375,12 @@ public abstract class AbstractModel implements Parcelable, Cloneable {
return transitoryData.remove(key);
}
/**
* Move transitory values (those that can be saved) to setValues,
* to be restored later. This is useful for the api daos that go
* through the content provider
*/
public synchronized void retainTransitories() {
if (transitoryData == null)
return;
if (setValues == null)
setValues = new ContentValues();
Set<String> keys = transitoryData.keySet();
for (String key : keys) {
String newKey = RETAIN_TRANSITORY_PREFIX + key;
Object value = transitoryData.get(key);
putObjectInContentValues(newKey, value, setValues);
}
}
/**
* Read keys from ContentValues. Remove those that match the
* RETAIN_TRANSITORY_PREFIX pattern and set those values
* on transitory data
* @param cv
*/
private void restoreTransitories(ContentValues cv) {
public Set<String> getAllTransitoryKeys() {
if (transitoryData == null)
transitoryData = new HashMap<String, Object>();
Set<Entry<String, Object>> entries = cv.valueSet();
Set<String> keysToRemove = new HashSet<String>();
for (Entry<String, Object> entry: entries) {
String key = entry.getKey();
if (key.startsWith(RETAIN_TRANSITORY_PREFIX)) {
String newKey = key.substring(RETAIN_TRANSITORY_PREFIX.length());
Object value = cv.get(key);
transitoryData.put(newKey, value);
keysToRemove.add(key);
}
}
for (String key : keysToRemove) {
cv.remove(key);
}
}
/**
* If value is of a type that is puttable in ContentValues, cast and put it
* @param key
* @param value
* @param cv
*/
private void putObjectInContentValues(String key, Object value, ContentValues cv) {
if (value instanceof Boolean)
cv.put(key, (Boolean) value);
if (value instanceof Byte)
cv.put(key, (Byte) value);
if (value instanceof Double)
cv.put(key, (Double) value);
if (value instanceof Float)
cv.put(key, (Float) value);
if (value instanceof Integer)
cv.put(key, (Integer) value);
if (value instanceof Long)
cv.put(key, (Long) value);
if (value instanceof Short)
cv.put(key, (Short) value);
if (value instanceof String)
cv.put(key, (String) value);
return null;
return transitoryData.keySet();
}
// --- Convenience wrappers for using transitories as flags
public boolean checkTransitory(String flag) {
Object trans = getTransitory(flag);

@ -2,8 +2,10 @@ package com.todoroo.andlib.data;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Set;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
@ -13,6 +15,7 @@ import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.AndroidUtilities;
/**
@ -95,13 +98,13 @@ public class ContentResolverDao<TYPE extends AbstractModel> {
if(model.isSaved()) {
if(model.getSetValues() == null)
return false;
model.retainTransitories();
writeTransitoriesToModelContentValues(model);
retainedTransitories = true;
if(cr.update(uriWithId(model.getId()), model.getSetValues(), null, null) != 0)
return true;
}
if (!retainedTransitories)
model.retainTransitories();
writeTransitoriesToModelContentValues(model);
Uri uri = cr.insert(baseUri, model.getMergedValues());
long id = Long.parseLong(uri.getLastPathSegment());
model.setId(id);
@ -109,6 +112,19 @@ public class ContentResolverDao<TYPE extends AbstractModel> {
return true;
}
private void writeTransitoriesToModelContentValues(AbstractModel model) {
Set<String> keys = model.getAllTransitoryKeys();
if (keys != null) {
ContentValues transitories = new ContentValues();
for (String key : keys) {
String newKey = AbstractModel.RETAIN_TRANSITORY_PREFIX + key;
Object value = model.getTransitory(key);
AndroidUtilities.putInto(transitories, newKey, value, false);
}
model.mergeWith(transitories);
}
}
/**
* Returns object corresponding to the given identifier
*

@ -150,16 +150,24 @@ public class AndroidUtilities {
* @param key
* @param value
*/
public static void putInto(ContentValues target, String key, Object value) {
if(value instanceof String)
target.put(key, (String) value);
else if(value instanceof Long)
target.put(key, (Long) value);
else if(value instanceof Integer)
target.put(key, (Integer) value);
else if(value instanceof Double)
public static void putInto(ContentValues target, String key, Object value, boolean errorOnFail) {
if (value instanceof Boolean)
target.put(key, (Boolean) value);
else if (value instanceof Byte)
target.put(key, (Byte) value);
else if (value instanceof Double)
target.put(key, (Double) value);
else
else if (value instanceof Float)
target.put(key, (Float) value);
else if (value instanceof Integer)
target.put(key, (Integer) value);
else if (value instanceof Long)
target.put(key, (Long) value);
else if (value instanceof Short)
target.put(key, (Short) value);
else if (value instanceof String)
target.put(key, (String) value);
else if (errorOnFail)
throw new UnsupportedOperationException("Could not handle type " + //$NON-NLS-1$
value.getClass());
}

@ -3,6 +3,10 @@
*/
package com.todoroo.astrid.provider;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
@ -266,6 +270,7 @@ public class Astrid3ContentProvider extends ContentProvider {
case URI_DIR: {
helper.model.mergeWith(values);
readTransitoriesFromModelContentValues(helper.model);
if(!helper.create())
throw new SQLException("Could not insert row into database (constraint failed?)");
@ -321,6 +326,7 @@ public class Astrid3ContentProvider extends ContentProvider {
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
long id = cursor.getLong(0);
helper.model.mergeWith(values);
readTransitoriesFromModelContentValues(helper.model);
helper.model.setId(id);
helper.update();
helper.model.clear();
@ -333,6 +339,27 @@ public class Astrid3ContentProvider extends ContentProvider {
}
}
private void readTransitoriesFromModelContentValues(AbstractModel model) {
ContentValues setValues = model.getSetValues();
if (setValues != null) {
Set<Entry<String, Object>> entries = setValues.valueSet();
Set<String> keysToRemove = new HashSet<String>();
for (Entry<String, Object> entry: entries) {
String key = entry.getKey();
if (key.startsWith(AbstractModel.RETAIN_TRANSITORY_PREFIX)) {
String newKey = key.substring(AbstractModel.RETAIN_TRANSITORY_PREFIX.length());
Object value = setValues.get(key);
model.putTransitory(newKey, value);
keysToRemove.add(key);
}
}
for (String key : keysToRemove) {
setValues.remove(key);
}
}
}
/* ======================================================================
* ============================================================ query ===
* ====================================================================== */

@ -437,11 +437,11 @@ public class TaskService {
for (Property<?> property : Metadata.PROPERTIES)
if (property.name.equals(key)) {
AndroidUtilities.putInto(forMetadata, key, value);
AndroidUtilities.putInto(forMetadata, key, value, true);
continue outer;
}
AndroidUtilities.putInto(forTask, key, value);
AndroidUtilities.putInto(forTask, key, value, true);
}
task.mergeWith(forTask);
}

Loading…
Cancel
Save