/*
* Copyright (C) 2007-2011 OpenIntents.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openintents.shopping.library.util;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import java.util.LinkedList;
import java.util.List;
import org.openintents.shopping.library.provider.ShoppingContract;
import org.openintents.shopping.library.provider.ShoppingContract.*;
public class ShoppingUtils {
/**
* TAG for logging.
*/
private static final String TAG = "ShoppingUtils";
private static final boolean debug = false;
/**
* Obtain item id by name.
*
* @param context
* @param name
* @return Item ID or -1 if item does not exist.
*/
public static long getItemId(Context context, String name) {
long id = -1;
Cursor existingItems = context.getContentResolver().query(
Items.CONTENT_URI, new String[]{Items._ID},
"upper(name) = upper(?)", new String[]{name}, null);
if (existingItems.getCount() > 0) {
existingItems.moveToFirst();
id = existingItems.getLong(0);
}
existingItems.close();
return id;
}
public static long getItemIdForList(Context context, String name, String list_id) {
long id = -1;
Cursor existingItems = context.getContentResolver().query(
ContainsFull.CONTENT_URI, new String[]{Contains.ITEM_ID},
"list_id = ? and upper(items.name) = upper(?)", new String[]{list_id, name}, null);
if (existingItems.getCount() > 0) {
existingItems.moveToFirst();
id = existingItems.getLong(0);
}
existingItems.close();
return id;
}
public static String getItemName(Context context, long itemId) {
String name = "";
Cursor existingItems = context.getContentResolver().query(
ShoppingContract.Items.CONTENT_URI,
new String[]{ShoppingContract.Items.NAME}, "_id = ?",
new String[]{String.valueOf(itemId)}, null);
if (existingItems.getCount() > 0) {
existingItems.moveToFirst();
name = existingItems.getString(0);
}
existingItems.close();
return name;
}
/**
* Gets or creates a new item and returns its id. If the item exists
* already, the existing id is returned. Otherwise a new item is created.
*
* @param name New name of the item.
* @param price
* @param barcode
* @return id of the new or existing item.
*/
public static long updateOrCreateItem(Context context, String name,
String tags, String price, String barcode, String list_id) {
long id;
if (list_id == null) {
id = getItemId(context, name);
} else {
id = getItemIdForList(context, name, list_id);
}
if (id >= 0) {
// Update existing item
// (pass 'null' for name: Existing item: no need to change name.)
ContentValues values = getContentValues(name, tags, price, barcode);
try {
Uri uri = Uri.withAppendedPath(
ShoppingContract.Items.CONTENT_URI, String.valueOf(id));
context.getContentResolver().update(uri, values, null, null);
if (debug) {
Log.d(TAG, "updated item: " + uri);
}
} catch (Exception e) {
Log.e(TAG, "Update item failed", e);
}
}
if (id == -1) {
// Add new item to list.
ContentValues values = getContentValues(name, tags, price, barcode);
try {
Uri uri = context.getContentResolver().insert(
ShoppingContract.Items.CONTENT_URI, values);
if (debug) {
Log.d(TAG, "Insert new item: " + uri);
}
id = Long.parseLong(uri.getPathSegments().get(1));
} catch (Exception e) {
Log.e(TAG, "Insert item failed", e);
// return -1
}
}
return id;
}
private static ContentValues getContentValues(String name, String tags,
String price, String barcode) {
ContentValues values = new ContentValues(4);
if (name != null) {
values.put(ShoppingContract.Items.NAME, name);
}
if (tags != null) {
values.put(ShoppingContract.Items.TAGS, tags);
}
if (price != null) {
Long priceLong = PriceConverter.getCentPriceFromString(price);
values.put(ShoppingContract.Items.PRICE, priceLong);
}
if (barcode != null) {
values.put(ShoppingContract.Items.BARCODE, barcode);
}
return values;
}
/**
* Gets or creates a new item and returns its id. If the item exists
* already, the existing id is returned. Otherwise a new item is created.
*
* @param name New name of the item.
* @return id of the new or existing item.
*/
public static long getItem(Context context, String name, String tags,
String price, String units, String note, Boolean duplicate,
Boolean update) {
long id = -1;
if (!duplicate) {
if (id == -1) {
id = getItemId(context, name);
}
if (id != -1 && !update) {
return id;
}
}
return getItem(context, id, name, tags, price, units, note);
}
/**
* Gets or creates a new item and returns its id. If the item exists
* already, the existing id is returned. Otherwise a new item is created.
*
* @param id id of the item to update, or -1 to create a new item.
* @param name New name of the item.
* @return id of the new or existing item.
*/
public static long getItem(Context context, long id, String name,
String tags, String price, String units, String note) {
// now we are either updating or adding.
// either way we need some content values.
// Add item to list:
ContentValues values = new ContentValues(1);
if (id == -1) {
values.put(Items.NAME, name);
}
values.put(Items.TAGS, tags);
if (!TextUtils.isEmpty(note)) {
values.put(Items.NOTE, note);
}
if (price != null) {
values.put(Items.PRICE, price);
}
if (!TextUtils.isEmpty(units)) {
// in the items table we store the string directly,
// but we register the units in the units table for use in
// completion.
long unit_id = getUnits(context, units);
values.put(Items.UNITS, units);
}
try {
if (id == -1) {
Uri uri = context.getContentResolver().insert(
Items.CONTENT_URI, values);
if (debug) {
Log.d(TAG, "Insert new item: " + uri);
}
id = Long.parseLong(uri.getPathSegments().get(1));
} else {
context.getContentResolver().update(
Uri.withAppendedPath(Items.CONTENT_URI,
String.valueOf(id)), values, null, null
);
}
} catch (Exception e) {
Log.e(TAG, "Insert item failed", e);
// return -1
}
return id;
}
public static long getUnits(Context context, String units) {
long id = -1;
Cursor existingUnits = context.getContentResolver().query(
Units.CONTENT_URI, new String[]{Units._ID},
"upper(name) = upper(?)", new String[]{units}, null);
if (existingUnits.getCount() > 0) {
existingUnits.moveToFirst();
id = existingUnits.getLong(0);
existingUnits.close();
} else {
existingUnits.close();
// Add item to list:
ContentValues values = new ContentValues(1);
values.put(Units.NAME, units);
try {
Uri uri = context.getContentResolver().insert(
Units.CONTENT_URI, values);
if (debug) {
Log.d(TAG, "Insert new units: " + uri);
}
id = Long.parseLong(uri.getPathSegments().get(1));
} catch (Exception e) {
Log.e(TAG, "Insert units failed", e);
// return -1
}
}
return id;
}
/**
* Gets or creates a new shopping list and returns its id. If the list
* exists already, the existing id is returned. Otherwise a new list is
* created.
*
* @param context
* @param name New name of the list.
* @return id of the new or existing list.
*/
public static long getList(Context context, final String name) {
long id = -1;
Cursor existingItems = context.getContentResolver().query(
Lists.CONTENT_URI, new String[]{Items._ID},
"upper(name) = upper(?)", new String[]{name}, null);
if (existingItems.getCount() > 0) {
existingItems.moveToFirst();
id = existingItems.getLong(0);
existingItems.close();
} else {
// Add list to list:
ContentValues values = new ContentValues(1);
values.put(Lists.NAME, name);
try {
Uri uri = context.getContentResolver().insert(
Lists.CONTENT_URI, values);
if (debug) {
Log.d(TAG, "Insert new list: " + uri);
}
id = Long.parseLong(uri.getPathSegments().get(1));
} catch (Exception e) {
Log.e(TAG, "insert list failed", e);
return -1;
}
}
return id;
}
/**
* Gets or creates a new store and returns its id. If the store exists
* already, the existing id is returned. Otherwise a new store is created.
*
* @param context
* @param name New name of the list.
* @return id of the new or existing list.
*/
public static long getStore(Context context, final String name,
final long listId) {
long id = -1;
Cursor existingItems = context.getContentResolver().query(
Stores.CONTENT_URI, new String[]{Stores._ID},
"upper(name) = upper(?) AND list_id = ?",
new String[]{name, String.valueOf(listId)}, null);
if (existingItems.getCount() > 0) {
existingItems.moveToFirst();
id = existingItems.getLong(0);
existingItems.close();
} else {
// Add list to list:
ContentValues values = new ContentValues(1);
values.put(Stores.NAME, name);
values.put(Stores.LIST_ID, listId);
try {
Uri uri = context.getContentResolver().insert(
Stores.CONTENT_URI, values);
if (debug) {
Log.d(TAG, "Insert new store: " + uri);
}
id = Long.parseLong(uri.getPathSegments().get(1));
} catch (Exception e) {
Log.e(TAG, "insert store failed", e);
return -1;
}
}
return id;
}
/**
* Adds a new item to a specific list and returns its id. If the item exists
* already, the existing id is returned.
*
* @param itemId The id of the new item.
* @param listId The id of the shopping list the item is added.
* @param status The status of the new item
* @param priority The priority of the new item
* @param quantity The quantity of the new item
* @param togglestatus If true, then status is toggled between WANT_TO_BUY and BOUGHT
* @return id of the "contains" table entry, or -1 if insert failed.
*/
public static long addItemToList(Context context, final long itemId,
final long listId, final long status, String priority,
String quantity, final boolean togglestatus,
final boolean known_new, final boolean resetQuantity) {
long id = -1;
Cursor existingItems = null;
if (!known_new) {
existingItems = context.getContentResolver()
.query(Contains.CONTENT_URI,
new String[]{Contains._ID, Contains.STATUS},
"list_id = ? AND item_id = ?",
new String[]{String.valueOf(listId),
String.valueOf(itemId)}, null
);
}
if (existingItems != null && existingItems.getCount() > 0) {
existingItems.moveToFirst();
id = existingItems.getLong(0);
long oldstatus = existingItems.getLong(1);
existingItems.close();
long newstatus = Status.WANT_TO_BUY;
// Toggle status:
if (oldstatus == Status.WANT_TO_BUY) {
newstatus = Status.BOUGHT;
}
// set status to want_to_buy:
ContentValues values = new ContentValues(3);
if (togglestatus) {
values.put(Contains.STATUS, newstatus);
} else {
values.put(Contains.STATUS, status);
}
if (quantity != null) {
// Only change quantity if an explicit value has been passed.
// (see issue 286)
values.put(ShoppingContract.Contains.QUANTITY, quantity);
} else {
if (resetQuantity) {
values.put(ShoppingContract.Contains.QUANTITY, "");
}
}
if (priority != null) {
values.put(ShoppingContract.Contains.PRIORITY, priority);
}
Uri uri = Uri.withAppendedPath(Contains.CONTENT_URI,
String.valueOf(id));
try {
context.getContentResolver().update(uri, values, null, null);
if (debug) {
Log.d(TAG, "updated item: " + uri);
}
} catch (Exception e) {
try {
// Maybe old version of OI Shopping List is installed:
values.remove(Contains.PRIORITY);
context.getContentResolver()
.update(uri, values, null, null);
if (debug) {
Log.d(TAG, "updated item: " + uri);
}
} catch (Exception e2) {
Log.e(TAG, "insert into table 'contains' failed", e2);
id = -1;
}
}
} else {
if (existingItems != null) {
existingItems.close();
}
// Add item to list:
ContentValues values = new ContentValues(2);
values.put(Contains.ITEM_ID, itemId);
values.put(Contains.LIST_ID, listId);
if (togglestatus) {
values.put(Contains.STATUS, Status.WANT_TO_BUY);
} else {
values.put(Contains.STATUS, status);
}
if (quantity != null) {
values.put(Contains.QUANTITY, quantity);
}
if (priority != null) {
values.put(Contains.PRIORITY, priority);
}
try {
Uri uri = context.getContentResolver().insert(
Contains.CONTENT_URI, values);
if (debug) {
Log.d(TAG, "Insert new entry in 'contains': " + uri);
}
id = Long.parseLong(uri.getPathSegments().get(1));
} catch (Exception e) {
try {
// Maybe old version of OI Shopping List is installed:
values.remove(Contains.PRIORITY);
Uri uri = context.getContentResolver().insert(
Contains.CONTENT_URI, values);
if (debug) {
Log.d(TAG, "Insert new entry in 'contains': " + uri);
}
id = Long.parseLong(uri.getPathSegments().get(1));
} catch (Exception e2) {
Log.e(TAG, "insert into table 'contains' failed", e2);
id = -1;
}
}
}
return id;
}
/**
* Adds an item to a specific store and returns its id. If the item exists
* already, the existing id is returned.
*
* @param itemId The id of the new item.
* @param storeId The id of the shopping list the item is added.
* @param stocksItem The type of the new item
* @return id of the "contains" table entry, or -1 if insert failed.
*/
public static long addItemToStore(Context context, final long itemId,
final long storeId, final boolean stocksItem, final String aisle,
final String price, boolean known_new) {
long id = -1;
Cursor existingItems = null;
if (!known_new) {
existingItems = context.getContentResolver()
.query(ItemStores.CONTENT_URI,
new String[]{ItemStores._ID},
"store_id = ? AND item_id = ?",
new String[]{String.valueOf(storeId),
String.valueOf(itemId)}, null
);
}
if (existingItems != null && existingItems.getCount() > 0) {
existingItems.moveToFirst();
id = existingItems.getLong(0);
existingItems.close();
// update aisle and price:
ContentValues values = new ContentValues(3);
if (!TextUtils.isEmpty(price))
values.put(ItemStores.PRICE, price);
if (!TextUtils.isEmpty(aisle))
values.put(ItemStores.AISLE, aisle);
values.put(ItemStores.STOCKS_ITEM, stocksItem);
try {
Uri uri = Uri.withAppendedPath(ItemStores.CONTENT_URI,
String.valueOf(id));
context.getContentResolver().update(uri, values, null, null);
if (debug) {
Log.d(TAG, "updated itemstore: " + uri);
}
} catch (Exception e) {
Log.e(TAG, "Update itemstore failed", e);
}
} else {
if (existingItems != null) {
existingItems.close();
}
// Add item to list:
ContentValues values = new ContentValues(5);
values.put(ItemStores.ITEM_ID, itemId);
values.put(ItemStores.STORE_ID, storeId);
values.put(ItemStores.PRICE, price);
values.put(ItemStores.AISLE, aisle);
values.put(ItemStores.STOCKS_ITEM, stocksItem);
try {
Uri uri = context.getContentResolver().insert(
ItemStores.CONTENT_URI, values);
if (debug) {
Log.d(TAG, "Insert new entry in 'itemstores': " + uri);
}
id = Long.parseLong(uri.getPathSegments().get(1));
} catch (Exception e) {
Log.e(TAG, "insert into table 'itemstores' failed", e);
id = -1;
}
}
return id;
}
/**
* Adds an item to a specific store and returns its id. If the item exists
* already, the existing id is returned.
*
* @param itemId The id of the new item.
* @param storeId The id of the store to which the item is added.
* @param aisle The aisle in which the item can be found at this store.
* Can be null.
* @param price The price of the item at this store.
* Can be null.
* @param known_new true if the caller knows the item is not yet in the table for this store.
* @return id of the "contains" table entry, or -1 if insert failed.
*/
public static long addItemToStore(Context context, final long itemId,
final long storeId, final String aisle, final String price, boolean known_new) {
return addItemToStore(context, itemId, storeId, true, aisle, price, known_new);
}
/**
* Returns the id of the default shopping list. Currently this is always 1.
*
* @return The id of the default shopping list.
*/
public static long getDefaultList(Context context) {
long id = 1;
try {
Cursor c = context.getContentResolver().query(
ActiveList.CONTENT_URI, ActiveList.PROJECTION, null, null,
null);
if (c.getCount() > 0) {
c.moveToFirst();
id = c.getLong(0);
c.close();
}
} catch (IllegalArgumentException e) {
// The URI has not been defined.
// The URI requires OI Shopping List 1.3.0 or higher.
// Most probably we want to access OI Shopping List 1.2.6 or
// earlier.
Log.e(TAG, "ActiveList URI not supported", e);
}
return id;
}
public static Uri getListForItem(Context context, String itemId) {
Cursor cursor = context.getContentResolver().query(
Contains.CONTENT_URI, new String[]{Contains.LIST_ID},
Contains.ITEM_ID + " = ?", new String[]{itemId},
Contains.DEFAULT_SORT_ORDER);
if (cursor != null) {
Uri uri;
if (cursor.moveToFirst()) {
uri = Uri.withAppendedPath(ShoppingContract.Lists.CONTENT_URI,
cursor.getString(0));
} else {
uri = null;
}
cursor.close();
return uri;
} else {
return null;
}
}
public static void addTagToItem(Context context, long itemId, String newTag) {
String allTags = "";
Cursor existingTags = context.getContentResolver().query(
Items.CONTENT_URI, new String[]{Items.TAGS}, "_id = ?",
new String[]{String.valueOf(itemId)}, null);
if (existingTags.getCount() > 0) {
existingTags.moveToFirst();
allTags = existingTags.getString(0);
existingTags.close();
}
if (!TextUtils.isEmpty(allTags)) {
if (allTags.equals(newTag))
return;
if (allTags.startsWith(newTag + ","))
return;
if (allTags.contains(", " + newTag))
return;
allTags = allTags + ", " + newTag;
} else {
allTags = newTag;
}
ContentValues values = new ContentValues(1);
values.put(Items.TAGS, allTags);
context.getContentResolver()
.update(Uri.withAppendedPath(Items.CONTENT_URI,
String.valueOf(itemId)), values, null, null);
}
/**
* Cleanly deletes an item from a list (from the Contains table), but the
* item itself remains. Afterwards, either the item should be moved to
* another list, or the item should be deleted. Deletion includes itemstores
* and contains.
*
* @param context
* @param itemId
* @return 1 if the item got deleted, 0 otherwise.
*/
public static int deleteItemFromList(Context context, String itemId,
String listId) {
// First delete all itemstores for item
List<String> itemStoreIds = getItemStoreIdsForList(context, itemId,
listId);
for (String itemStoreId : itemStoreIds) {
context.getContentResolver().delete(ItemStores.CONTENT_URI,
"itemstores._id = " + itemStoreId, null);
}
// Delete item from currentList by deleting contains row
return context.getContentResolver().delete(
Contains.CONTENT_URI, "item_id = ? and list_id = ?",
new String[]{itemId, listId});
}
/**
* Cleanly deletes an item from a particular list if it does not exist on
* any other list. Deletion includes itemstores and the item itself.
*
* @param context
* @param itemId
* @return 1 if the item got deleted, 0 otherwise.
*/
public static int deleteItem(Context context, String itemId, String listId) {
deleteItemFromList(context, itemId, listId);
int itemsDeleted = 0;
if (!isItemContainedInOtherExistingList(context, itemId)) {
// Delete the item itself if it is not contained in an existing list
// anymore
itemsDeleted = context.getContentResolver().delete(
Items.CONTENT_URI, "_id = ?", new String[]{itemId});
}
return itemsDeleted;
}
/**
* Returns true if the item is contained in an existing list. Extra care is
* taken because old contains could be left over from lists that do not
* exist anymore.
*
* @param context
* @param itemId
* @return
*/
private static boolean isItemContainedInOtherExistingList(Context context,
String itemId) {
Cursor c = context.getContentResolver().query(Contains.CONTENT_URI,
new String[]{Contains.LIST_ID}, Contains.ITEM_ID + " = ?",
new String[]{itemId}, null);
if (c != null) {
while (c.moveToNext()) {
// Item is contained in some list...
String listId = c.getString(0);
Cursor c2 = context.getContentResolver().query(
Lists.CONTENT_URI, new String[]{Lists._ID},
Lists._ID + " = ?", new String[]{listId}, null);
if (c2 != null) {
if (c2.moveToNext()) {
// ... and that list exists
c2.close();
c.close();
return true;
}
c2.close();
}
}
c.close();
}
return false;
}
/**
* Cleanly deletes a store. Deletion includes itemstores and the store
* itself.
*
* @param context
* @param storeId
* @return 1 if the store got deleted, 0 otherwise.
*/
public static int deleteStore(Context context, String storeId) {
// First delete all items for store
context.getContentResolver().delete(ItemStores.CONTENT_URI,
"store_id = " + storeId, null);
// Then delete currently selected store
return context.getContentResolver().delete(
Stores.CONTENT_URI, "_id = " + storeId, null);
}
/**
* Cleanly deletes a list. Deletion includes stores, itemstores, items, and
* the list itself.
*
* @param context
* @param listId
* @return 1 if the list got deleted, 0 otherwise.
*/
public static int deleteList(Context context, String listId) {
// Delete all items
List<String> itemIds = getItemIdsForList(context, listId);
for (String itemId : itemIds) {
deleteItem(context, itemId, listId);
}
// Delete all stores
List<String> storeIds = getStoreIdsForList(context, listId);
for (String storeId : storeIds) {
deleteStore(context, storeId);
}
// Then delete currently selected list
return context.getContentResolver().delete(
Lists.CONTENT_URI, "_id = " + listId, null);
}
private static List<String> getItemStoreIdsForList(Context context,
String itemId, String listId) {
// Get a cursor for all stores
Cursor c = context.getContentResolver().query(
ItemStores.CONTENT_URI.buildUpon().appendPath("item")
.appendPath(itemId).appendPath(listId).build(),
new String[]{"itemstores._id"}, null, null, null
);
return getStringListAndCloseCursor(c, 0);
}
private static List<String> getItemIdsForList(Context context, String listId) {
Cursor c = context.getContentResolver().query(Contains.CONTENT_URI,
new String[]{Contains.ITEM_ID}, Contains.LIST_ID + " = ?",
new String[]{listId}, null);
return getStringListAndCloseCursor(c, 0);
}
private static List<String> getStoreIdsForList(Context context,
String listId) {
Cursor c = context.getContentResolver().query(Stores.CONTENT_URI,
new String[]{Stores._ID}, Stores.LIST_ID + " = ?",
new String[]{listId}, null);
return getStringListAndCloseCursor(c, 0);
}
private static List<String> getStringListAndCloseCursor(Cursor c, int index) {
List<String> items = new LinkedList<String>();
if (c != null) {
while (c.moveToNext()) {
String item = c.getString(index);
items.add(item);
}
c.close();
}
return items;
}
private static String getListFilterStoreId(Context context, Uri list_uri) {
String store_id = null;
Cursor c = context.getContentResolver().query(list_uri,
new String[]{Lists.STORE_FILTER}, null, null, null);
if (c.getCount() > 0) {
c.moveToFirst();
store_id = c.getString(0);
c.deactivate();
c.close();
}
return store_id;
}
public static String getListFilterStoreName(Context context, Uri list_uri) {
String filter = null;
String store_id = getListFilterStoreId(context, list_uri);
if (store_id != null && store_id.length() > 0) {
Cursor c = context.getContentResolver().query(Stores.CONTENT_URI,
new String[]{Stores.NAME}, "_id = ?", new String[]{store_id}, null);
if (c != null) {
if (c.getCount() > 0) {
c.moveToFirst();
filter = c.getString(0);
}
c.deactivate();
c.close();
}
}
return filter;
}
public static String getListTagsFilter(Context context, Uri list_uri) {
String filter = null;
Cursor c = context.getContentResolver().query(list_uri,
new String[]{Lists.TAGS_FILTER}, null, null, null);
if (c.getCount() > 0) {
c.moveToFirst();
filter = c.getString(0);
c.deactivate();
c.close();
if (filter != null && filter.length() == 0) {
filter = null;
}
}
return filter;
}
public static void addDefaultsToAddedItem(Context context, long list_id, long item_id) {
Uri list_uri = Uri.withAppendedPath(ShoppingContract.Lists.CONTENT_URI,
Long.toString(list_id));
String tagsFilter = getListTagsFilter(context, list_uri);
String storeId = getListFilterStoreId(context, list_uri);
boolean hasTagsFilter = !TextUtils.isEmpty(tagsFilter);
boolean hasStoreIdFilter = !TextUtils.isEmpty(storeId);
if (hasStoreIdFilter) {
addItemToStore(context, item_id, Long.parseLong(storeId), true, null, null, false);
}
if (hasTagsFilter) {
addTagToItem(context, item_id, tagsFilter);
}
}
public static String getListSortOrder(Context context, long list_id) {
String sort = null;
Uri list_uri = Uri.withAppendedPath(ShoppingContract.Lists.CONTENT_URI,
Long.toString(list_id));
Cursor c = context.getContentResolver().query(list_uri,
new String[]{Lists.ITEMS_SORT}, null, null, null);
if (c.getCount() > 0) {
c.moveToFirst();
sort = c.getString(0);
c.deactivate();
c.close();
if (sort != null && sort.length() == 0) {
sort = null;
}
}
return sort;
}
}