Example usage for android.net Uri getPathSegments

List of usage examples for android.net Uri getPathSegments

Introduction

In this page you can find the example usage for android.net Uri getPathSegments.

Prototype

public abstract List<String> getPathSegments();

Source Link

Document

Gets the decoded path segments.

Usage

From source file:io.n7.calendar.caldav.CalDAVService.java

private long createCalendar(Account acc) {
    String name = acc.getName(), account = acc.getEmail(), collection = acc.getCollection(), url = acc.getUrl();
    // Create a Calendar object
    ContentValues cv = new ContentValues();
    cv.put(Calendars.NAME, name);//from www .  j  a v  a2  s  . c o m
    cv.put(Calendars.DISPLAY_NAME, name);
    cv.put(Calendars.URL, url);
    cv.put(Calendars._SYNC_ACCOUNT, account);
    cv.put(Calendars._SYNC_ACCOUNT_TYPE, CALDAV_ACC_TYPE);
    cv.put(Calendars._SYNC_ID, collection);
    cv.put(Calendars.SYNC_EVENTS, 1);
    cv.put(Calendars.SELECTED, 0);
    cv.put(Calendars.HIDDEN, 0);
    cv.put(Calendars.COLOR, 0xFF9d50a4);
    cv.put(Calendars.SELECTED, 1);
    // Don't show attendee status if we're the organizer
    cv.put(Calendars.ORGANIZER_CAN_RESPOND, 0);

    cv.put(Calendars.TIMEZONE, Time.getCurrentTimezone());
    cv.put(Calendars.ACCESS_LEVEL, Calendars.OWNER_ACCESS);
    cv.put(Calendars.OWNER_ACCOUNT, account);

    Uri uri = mCR.insert(Calendars.CONTENT_URI, cv);
    if (uri != null) {
        String stringId = uri.getPathSegments().get(1);
        return Long.parseLong(stringId);
    }
    return -1;
}

From source file:org.mozilla.labs.Soup.provider.AppsProvider.java

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

    qb.setTables(APPS_TABLE_NAME);//from  w ww .  ja  va  2s  .  c o  m

    switch (sUriMatcher.match(uri)) {
    case APPS:
        qb.setProjectionMap(sAppsProjectionMap);
        break;

    case APP_ID:
        qb.setProjectionMap(sAppsProjectionMap);
        qb.appendWhere(Apps._ID + "=" + uri.getPathSegments().get(1));
        break;

    case LIVE_FOLDER_APPS:
        qb.setProjectionMap(sLiveFolderProjectionMap);
        break;

    default:
        throw new IllegalArgumentException("Unknown URI " + uri);
    }

    // If no sort order is specified use the default
    String orderBy;
    if (TextUtils.isEmpty(sortOrder)) {
        orderBy = AppsContract.Apps.DEFAULT_SORT_ORDER;
    } else {
        orderBy = sortOrder;
    }

    // Get the database and run the query
    SQLiteDatabase db = mOpenHelper.getReadableDatabase();
    Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);

    // Tell the cursor what uri to watch, so it knows when its source data
    // changes
    c.setNotificationUri(getContext().getContentResolver(), uri);
    return c;
}

From source file:org.opendatakit.common.android.provider.impl.FormsProviderImpl.java

@Override
public String getType(Uri uri) {
    List<String> segments = uri.getPathSegments();

    if (segments.size() < 1 || segments.size() > 2) {
        throw new IllegalArgumentException("Unknown URI (incorrect number of segments!) " + uri);
    }/*from  w  w  w  . jav a2s .  co m*/
    String uriFormId = ((segments.size() == 2) ? segments.get(1) : null);

    if (uriFormId == null) {
        return FormsColumns.CONTENT_TYPE;
    } else {
        return FormsColumns.CONTENT_ITEM_TYPE;
    }
}

From source file:org.rapidandroid.tests.ContentBootstrapTests.java

private void insertFormsIntoDb(Vector<Form> forms) {
    // ok, now, let's create all the content types and such one by one.
    ModelTranslator.ClearFormTables();//from w  w w. j a v  a2 s. c o m

    Log.d("dimagi", "** inserting forms into db");
    for (int i = 0; i < forms.size(); i++) {
        Form f = forms.get(i);
        Field[] fields = f.getFields();
        Log.d("dimagi", "**** inserting form " + f.getFormName());

        // insert the form first
        Uri formUri = Uri.parse(RapidSmsDBConstants.Form.CONTENT_URI_STRING + f.getFormId());
        Cursor crform = getContext().getContentResolver().query(formUri, null, null, null, null);
        if (crform.getCount() == 0) {
            ContentValues typecv = new ContentValues();

            typecv.put(RapidSmsDBConstants.Form._ID, f.getFormId());
            typecv.put(RapidSmsDBConstants.Form.FORMNAME, f.getFormName());
            // typecv.put(RapidSmsDBConstants.Form.PARSEMETHOD,
            // f.getParser().getName());
            typecv.put(RapidSmsDBConstants.Form.PARSEMETHOD, "simpleregex");
            typecv.put(RapidSmsDBConstants.Form.PREFIX, f.getPrefix());
            typecv.put(RapidSmsDBConstants.Form.DESCRIPTION, f.getDescription());

            Uri insertedFormUri = getContext().getContentResolver().insert(RapidSmsDBConstants.Form.CONTENT_URI,
                    typecv);
            Log.d("dimagi", "****** Inserted form into db: " + insertedFormUri);
            assertEquals(insertedFormUri.getPathSegments().get(1), f.getFormId() + "");
        }
        crform.close();

        Log.d("dimagi", "****** Begin fields loop: " + fields.length);
        for (int j = 0; j < fields.length; j++) {
            Field thefield = fields[j];
            SimpleFieldType thetype = (SimpleFieldType) thefield.getFieldType();
            // make the URI and insert for the Fieldtype
            Log.d("dimagi", "******** Iterating through fields: " + thefield.getName() + " id: "
                    + thefield.getFieldId());

            Uri fieldtypeUri = Uri.parse(RapidSmsDBConstants.FieldType.CONTENT_URI_STRING + thetype.getId());
            Cursor typeCursor = getContext().getContentResolver().query(fieldtypeUri, null, null, null, null);
            if (typeCursor.getCount() == 0) {
                ContentValues typecv = new ContentValues();

                typecv.put(RapidSmsDBConstants.FieldType._ID, thetype.getId());
                typecv.put(RapidSmsDBConstants.FieldType.DATATYPE, thetype.getDataType());
                typecv.put(RapidSmsDBConstants.FieldType.NAME, thetype.getReadableName());
                typecv.put(RapidSmsDBConstants.FieldType.REGEX, thetype.getRegex());

                Log.d("dimagi", "InsertFieldType: " + thetype.getId());
                Log.d("dimagi", "InsertFieldType: " + thetype.getDataType());
                Log.d("dimagi", "InsertFieldType: " + thetype.getReadableName());
                Log.d("dimagi", "InsertFieldType: " + thetype.getRegex());

                Uri insertedTypeUri = getContext().getContentResolver()
                        .insert(RapidSmsDBConstants.FieldType.CONTENT_URI, typecv);
                Log.d("dimagi", "********** Inserted SimpleFieldType into db: " + insertedTypeUri);
                assertEquals(insertedTypeUri.getPathSegments().get(1), thetype.getId() + "");
            }
            typeCursor.close();

            Uri fieldUri = Uri.parse(RapidSmsDBConstants.Field.CONTENT_URI_STRING + thefield.getFieldId());
            Cursor crfield = getContext().getContentResolver().query(fieldUri, null, null, null, null);
            if (crfield.getCount() == 0) {
                ContentValues typecv = new ContentValues();

                typecv.put(RapidSmsDBConstants.Field._ID, thefield.getFieldId());
                typecv.put(RapidSmsDBConstants.Field.NAME, thefield.getName());
                typecv.put(RapidSmsDBConstants.Field.FORM, f.getFormId());
                typecv.put(RapidSmsDBConstants.Field.PROMPT, thefield.getDescription());
                typecv.put(RapidSmsDBConstants.Field.SEQUENCE, thefield.getSequenceId());

                typecv.put(RapidSmsDBConstants.Field.FIELDTYPE,
                        ((SimpleFieldType) (thefield.getFieldType())).getId());
                // typecv.put(RapidSmsDBConstants.Field.FIELDTYPE,
                // thefield.getFieldType().getId());

                // Log.d("dimagi", "_ID: " + thefield.getFieldId());
                // Log.d("dimagi", "NAME: " + thefield.getName());
                // Log.d("dimagi", "FORM: " + f.getFormId());
                // Log.d("dimagi", "PROMPT: " + thefield.getPrompt());
                // Log.d("dimagi", "SEQUENCE: " + thefield.getSequenceId());
                // Log.d("dimagi", "FIELDTYPE: " +
                // thefield.getFieldType().getId());

                Uri insertedFieldUri = getContext().getContentResolver()
                        .insert(RapidSmsDBConstants.Field.CONTENT_URI, typecv);
                Log.d("dimagi", "********** Inserted Field into db: " + insertedFieldUri);
                assertEquals(insertedFieldUri.getPathSegments().get(1), thefield.getFieldId() + "");
            }
            crfield.close();
            // next, make the uri and insert for the field.
        }
    }
    assertEquals(2, forms.size());
    Log.d("dimagi", "Test form insert success");

}

From source file:com.hivewallet.androidclient.wallet.AddressBookProvider.java

@Override
public Cursor query(final Uri uri, final String[] projection, final String originalSelection,
        final String[] originalSelectionArgs, final String sortOrder) {
    final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setTables(DATABASE_TABLE);//from   w  w  w.  ja  v a  2s .c  o m

    final List<String> pathSegments = uri.getPathSegments();
    if (pathSegments.size() > 1)
        throw new IllegalArgumentException(uri.toString());

    String selection = null;
    String[] selectionArgs = null;

    if (pathSegments.size() == 1) {
        final String address = uri.getLastPathSegment();

        qb.appendWhere(KEY_ADDRESS + "=");
        qb.appendWhereEscapeString(address);
    } else if (SELECTION_IN.equals(originalSelection)) {
        final String[] addresses = originalSelectionArgs[0].trim().split(",");

        qb.appendWhere(KEY_ADDRESS + " IN (");
        appendAddresses(qb, addresses);
        qb.appendWhere(")");
    } else if (SELECTION_NOTIN.equals(originalSelection)) {
        final String[] addresses = originalSelectionArgs[0].trim().split(",");

        qb.appendWhere(KEY_ADDRESS + " NOT IN (");
        appendAddresses(qb, addresses);
        qb.appendWhere(")");
    } else if (SELECTION_QUERY.equals(originalSelection)) {
        final String query = '%' + originalSelectionArgs[0].trim() + '%';
        selection = KEY_ADDRESS + " LIKE ? OR " + KEY_LABEL + " LIKE ?";
        selectionArgs = new String[] { query, query };
    }

    final Cursor cursor = qb.query(helper.getReadableDatabase(), projection, selection, selectionArgs, null,
            null, sortOrder);

    cursor.setNotificationUri(getContext().getContentResolver(), uri);

    return cursor;
}

From source file:org.opendatakit.services.forms.provider.FormsProvider.java

@Override
public String getType(@NonNull Uri uri) {
    List<String> segments = uri.getPathSegments();

    PatchedFilter pf = extractUriFeatures(uri, segments, null, null);

    if (pf.isNumericFormId || segments.size() == 3) {
        return FormsColumns.CONTENT_ITEM_TYPE;
    } else {/*from w  w w .j a  v a2 s.  c o m*/
        return FormsColumns.CONTENT_TYPE;
    }
}

From source file:org.opensilk.music.library.provider.LibraryProvider.java

@Override
public final Bundle call(String method, String arg, Bundle extras) {

    final Bundle ok = new Bundle();
    ok.putBoolean(Extras.OK, true);//ww  w.  j  a v a  2s . co  m

    if (method == null)
        method = "";
    switch (method) {
    case LibraryMethods.QUERY: {
        extras.setClassLoader(getClass().getClassLoader());

        final IBinder binder = getBinderCallbackFromBundle(extras);
        if (binder == null || !binder.isBinderAlive()) {
            //this is mostly for the null, if the binder is dead then
            //sending them a reason is moot. but we check the binder here
            //so we dont have to do it 50 times below and we can be pretty
            //sure the linkToDeath will succeed
            ok.putBoolean(Extras.OK, false);
            writeCause(ok, new LibraryException(BAD_BINDER, null));
            return ok;
        }

        final Uri uri = extras.getParcelable(Extras.URI);
        final List<String> pathSegments = uri.getPathSegments();
        if (pathSegments.size() < 3 || pathSegments.size() > 5) {
            Log.e(TAG, "Wrong number of path segments: uri=" + uri);
            ok.putBoolean(Extras.OK, false);
            writeCause(ok, new LibraryException(ILLEGAL_URI, new IllegalArgumentException(uri.toString())));
            return ok;
        }

        final String library = pathSegments.get(0);
        final String identity;
        if (pathSegments.size() > 3) {
            identity = pathSegments.get(3);
        } else {
            identity = null;
        }

        final Bundle args = new Bundle();
        args.putParcelable(Extras.URI, uri);
        String sortOrder = extras.getString(Extras.SORTORDER);
        args.putString(Extras.SORTORDER, sortOrder != null ? sortOrder : BundleableSortOrder.A_Z);

        switch (mMatcher.match(uri)) {
        case M_ALBUMS: {
            final BundleableSubscriber<Album> subscriber = new BundleableSubscriber<>(binder);
            queryAlbumsInternal(library, subscriber, args);
            break;
        }
        case M_ALBUM: {
            final BundleableSubscriber<Album> subscriber = new BundleableSubscriber<>(binder);
            getAlbumInternal(library, identity, subscriber, args);
            break;
        }
        case M_ALBUM_TRACKS: {
            final BundleableSubscriber<Track> subscriber = new BundleableSubscriber<>(binder);
            getAlbumTracksInternal(library, identity, subscriber, args);
            break;
        }
        case M_ARTISTS: {
            final BundleableSubscriber<Artist> subscriber = new BundleableSubscriber<>(binder);
            queryArtistsInternal(library, subscriber, args);
            break;
        }
        case M_ARTIST: {
            final BundleableSubscriber<Artist> subscriber = new BundleableSubscriber<>(binder);
            getArtistInternal(library, identity, subscriber, args);
            break;
        }
        case M_ARTIST_ALBUMS: {
            final BundleableSubscriber<Album> subscriber = new BundleableSubscriber<>(binder);
            getArtistAlbumsInternal(library, identity, subscriber, args);
            break;
        }
        case M_ARTIST_TRACKS: {
            final BundleableSubscriber<Track> subscriber = new BundleableSubscriber<>(binder);
            getArtistTracksInternal(library, identity, subscriber, args);
            break;
        }
        case M_FOLDERS:
        case M_FOLDER: {
            final BundleableSubscriber<Bundleable> subscriber = new BundleableSubscriber<>(binder);
            browseFoldersInternal(library, identity, subscriber, args);
            break;
        }
        case M_GENRES: {
            final BundleableSubscriber<Genre> subscriber = new BundleableSubscriber<>(binder);
            queryGenresInternal(library, subscriber, args);
            break;
        }
        case M_GENRE: {
            final BundleableSubscriber<Genre> subscriber = new BundleableSubscriber<>(binder);
            getGenreInternal(library, identity, subscriber, args);
            break;
        }
        case M_GENRE_ALBUMS: {
            final BundleableSubscriber<Album> subscriber = new BundleableSubscriber<>(binder);
            getGenreAlbumsInternal(library, identity, subscriber, args);
            break;
        }
        case M_GENRE_TRACKS: {
            final BundleableSubscriber<Track> subscriber = new BundleableSubscriber<>(binder);
            getGenreTracksInternal(library, identity, subscriber, args);
            break;
        }
        case M_PLAYLISTS: {
            final BundleableSubscriber<Playlist> subscriber = new BundleableSubscriber<>(binder);
            queryPlaylistsInternal(library, subscriber, args);
            break;
        }
        case M_PLAYLIST: {
            final BundleableSubscriber<Playlist> subscriber = new BundleableSubscriber<>(binder);
            getPlaylistInternal(library, identity, subscriber, args);
            break;
        }
        case M_PLAYLIST_TRACKS: {
            final BundleableSubscriber<Track> subscriber = new BundleableSubscriber<>(binder);
            getPlaylistTracksInternal(library, identity, subscriber, args);
            break;
        }
        case M_TRACKS: {
            final BundleableSubscriber<Track> subscriber = new BundleableSubscriber<>(binder);
            queryTracksInternal(library, subscriber, args);
            break;
        }
        case M_TRACK: {
            final BundleableSubscriber<Track> subscriber = new BundleableSubscriber<>(binder);
            getTrackInternal(library, identity, subscriber, args);
            break;
        }
        default: {
            ok.putBoolean(Extras.OK, false);
            writeCause(ok, new LibraryException(ILLEGAL_URI, new IllegalArgumentException(uri.toString())));
        }
        }
        return ok;
    }
    case LibraryMethods.LIBRARYCONF:
        return getLibraryConfig().dematerialize();
    default:
        Log.e(TAG, "Unknown method " + method);
        ok.putBoolean(Extras.OK, false);
        writeCause(ok, new LibraryException(METHOD_NOT_IMPLEMENTED, new UnsupportedOperationException(method)));
        return ok;
    }
}

From source file:cn.edu.wyu.documentviewer.RecentsProvider.java

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    final SQLiteDatabase db = mHelper.getReadableDatabase();
    switch (sMatcher.match(uri)) {
    case URI_RECENT:
        final long cutoff = System.currentTimeMillis() - MAX_HISTORY_IN_MILLIS;
        return db.query(TABLE_RECENT, projection, RecentColumns.TIMESTAMP + ">" + cutoff, null, null, null,
                sortOrder);//  ww  w .j  av a2s .co m
    case URI_STATE:
        final String authority = uri.getPathSegments().get(1);
        final String rootId = uri.getPathSegments().get(2);
        final String documentId = uri.getPathSegments().get(3);
        return db.query(
                TABLE_STATE, projection, StateColumns.AUTHORITY + "=? AND " + StateColumns.ROOT_ID + "=? AND "
                        + StateColumns.DOCUMENT_ID + "=?",
                new String[] { authority, rootId, documentId }, null, null, sortOrder);
    case URI_RESUME:
        final String packageName = uri.getPathSegments().get(1);
        return db.query(TABLE_RESUME, projection, ResumeColumns.PACKAGE_NAME + "=?",
                new String[] { packageName }, null, null, sortOrder);
    default:
        throw new UnsupportedOperationException("Unsupported Uri " + uri);
    }
}

From source file:org.thialfihar.android.apg.provider.ProviderHelper.java

/**
 * Find the master key id related to a given query. The id will either be extracted from the
 * query, which should work for all specific /key_rings/ queries, or will be queried if it can't.
 *///w  ww .ja va2s . co  m
public long extractOrGetMasterKeyId(Uri queryUri) throws NotFoundException {
    // try extracting from the uri first
    String firstSegment = queryUri.getPathSegments().get(1);
    if (!firstSegment.equals("find"))
        try {
            return Long.parseLong(firstSegment);
        } catch (NumberFormatException e) {
            // didn't work? oh well.
            Log.d(Constants.TAG, "Couldn't get masterKeyId from URI, querying...");
        }
    return getMasterKeyId(queryUri);
}

From source file:org.opendatakit.common.android.provider.impl.InstanceProviderImpl.java

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    List<String> segments = uri.getPathSegments();

    if (segments.size() < 2 || segments.size() > 3) {
        throw new SQLException("Unknown URI (too many segments!) " + uri);
    }/*from  w  w w. j a  v a 2  s  .c  om*/

    String appName = segments.get(0);
    ODKFileUtils.verifyExternalStorageAvailability();
    ODKFileUtils.assertDirectoryStructure(appName);
    String tableId = segments.get(1);
    String instanceName = null;
    // _ID in UPLOADS_TABLE_NAME
    String instanceId = (segments.size() == 3 ? segments.get(2) : null);

    SQLiteDatabase db = null;
    String fullQuery;
    String filterArgs[];
    Cursor c = null;

    String dbTableName;
    List<ColumnDefinition> orderedDefns;

    StringBuilder b = new StringBuilder();

    try {
        db = DatabaseFactory.get().getDatabase(getContext(), appName);
        db.beginTransaction();

        boolean success = false;
        try {
            success = ODKDatabaseUtils.get().hasTableId(db, tableId);
        } catch (Exception e) {
            e.printStackTrace();
            throw new SQLException("Unknown URI (exception testing for tableId) " + uri);
        }
        if (!success) {
            throw new SQLException("Unknown URI (missing data table for tableId) " + uri);
        }

        dbTableName = "\"" + tableId + "\"";

        try {
            c = db.query(DatabaseConstants.KEY_VALUE_STORE_ACTIVE_TABLE_NAME,
                    new String[] { KeyValueStoreColumns.VALUE },
                    KeyValueStoreColumns.TABLE_ID + "=? AND " + KeyValueStoreColumns.PARTITION + "=? AND "
                            + KeyValueStoreColumns.ASPECT + "=? AND " + KeyValueStoreColumns.KEY + "=?",
                    new String[] { tableId, KeyValueStoreConstants.PARTITION_TABLE,
                            KeyValueStoreConstants.ASPECT_DEFAULT, KeyValueStoreConstants.XML_INSTANCE_NAME },
                    null, null, null);

            if (c.getCount() == 1) {
                c.moveToFirst();
                int idxInstanceName = c.getColumnIndex(KeyValueStoreColumns.VALUE);
                instanceName = c.getString(idxInstanceName);
            }
        } finally {
            c.close();
        }

        // ARGH! we must ensure that we have records in our UPLOADS_TABLE_NAME
        // for every distinct instance in the data table.
        b.setLength(0);
        //@formatter:off
        b.append("INSERT INTO ").append(DatabaseConstants.UPLOADS_TABLE_NAME).append("(")
                .append(InstanceColumns.DATA_INSTANCE_ID).append(",")
                .append(InstanceColumns.DATA_TABLE_TABLE_ID).append(") ").append("SELECT ")
                .append(InstanceColumns.DATA_INSTANCE_ID).append(",")
                .append(InstanceColumns.DATA_TABLE_TABLE_ID).append(" FROM (").append("SELECT DISTINCT ")
                .append(DATA_TABLE_ID_COLUMN).append(" as ").append(InstanceColumns.DATA_INSTANCE_ID)
                .append(",").append("? as ").append(InstanceColumns.DATA_TABLE_TABLE_ID).append(" FROM ")
                .append(dbTableName).append(" EXCEPT SELECT DISTINCT ").append(InstanceColumns.DATA_INSTANCE_ID)
                .append(",").append(InstanceColumns.DATA_TABLE_TABLE_ID).append(" FROM ")
                .append(DatabaseConstants.UPLOADS_TABLE_NAME).append(")");
        //@formatter:on

        // TODO: should we collapse across FORM_ID or leave it this way?
        String[] args = { tableId };
        db.execSQL(b.toString(), args);

        // Can't get away with dataTable.* because of collision with _ID column
        // get map of (elementKey -> ColumnDefinition)
        try {
            orderedDefns = TableUtil.get().getColumnDefinitions(db, appName, tableId);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw new SQLException("Unable to retrieve column definitions for tableId " + tableId);
        }

        db.setTransactionSuccessful();
    } finally {
        if (db != null) {
            db.endTransaction();
            db.close();
        }
    }

    ////////////////////////////////////////////////////////////////
    // OK we have the info we need -- now build the query we want...

    // We can now join through and access the data table rows

    b.setLength(0);
    // @formatter:off
    b.append("SELECT ");
    b.append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".").append(InstanceColumns._ID).append(" as ")
            .append(InstanceColumns._ID).append(",").append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".")
            .append(InstanceColumns.DATA_INSTANCE_ID).append(" as ").append(InstanceColumns.DATA_INSTANCE_ID)
            .append(",").append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".")
            .append(InstanceColumns.SUBMISSION_INSTANCE_ID).append(" as ")
            .append(InstanceColumns.SUBMISSION_INSTANCE_ID).append(",");
    // add the dataTable metadata except for _ID (which conflicts with InstanceColumns._ID)
    b.append(dbTableName).append(".").append(DataTableColumns.ROW_ETAG).append(" as ")
            .append(DataTableColumns.ROW_ETAG).append(",").append(dbTableName).append(".")
            .append(DataTableColumns.SYNC_STATE).append(" as ").append(DataTableColumns.SYNC_STATE).append(",")
            .append(dbTableName).append(".").append(DataTableColumns.CONFLICT_TYPE).append(" as ")
            .append(DataTableColumns.CONFLICT_TYPE).append(",").append(dbTableName).append(".")
            .append(DataTableColumns.FILTER_TYPE).append(" as ").append(DataTableColumns.FILTER_TYPE)
            .append(",").append(dbTableName).append(".").append(DataTableColumns.FILTER_VALUE).append(" as ")
            .append(DataTableColumns.FILTER_VALUE).append(",").append(dbTableName).append(".")
            .append(DataTableColumns.FORM_ID).append(" as ").append(DataTableColumns.FORM_ID).append(",")
            .append(dbTableName).append(".").append(DataTableColumns.LOCALE).append(" as ")
            .append(DataTableColumns.LOCALE).append(",").append(dbTableName).append(".")
            .append(DataTableColumns.SAVEPOINT_TYPE).append(" as ").append(DataTableColumns.SAVEPOINT_TYPE)
            .append(",").append(dbTableName).append(".").append(DataTableColumns.SAVEPOINT_TIMESTAMP)
            .append(" as ").append(DataTableColumns.SAVEPOINT_TIMESTAMP).append(",").append(dbTableName)
            .append(".").append(DataTableColumns.SAVEPOINT_CREATOR).append(" as ")
            .append(DataTableColumns.SAVEPOINT_CREATOR).append(",");
    // add the user-specified data fields in this dataTable
    for (ColumnDefinition cd : orderedDefns) {
        if (cd.isUnitOfRetention()) {
            b.append(dbTableName).append(".").append(cd.getElementKey()).append(" as ")
                    .append(cd.getElementKey()).append(",");
        }
    }
    b.append("CASE WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" IS NULL THEN null")
            .append(" WHEN ").append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" IS NULL THEN null")
            .append(" WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" > ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" THEN null").append(" ELSE ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" END as ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(",");
    b.append("CASE WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" IS NULL THEN null")
            .append(" WHEN ").append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" IS NULL THEN null")
            .append(" WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" > ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" THEN null").append(" ELSE ")
            .append(InstanceColumns.XML_PUBLISH_STATUS).append(" END as ")
            .append(InstanceColumns.XML_PUBLISH_STATUS).append(",");
    b.append("CASE WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" IS NULL THEN null")
            .append(" WHEN ").append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" IS NULL THEN null")
            .append(" WHEN ").append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(" > ")
            .append(InstanceColumns.XML_PUBLISH_TIMESTAMP).append(" THEN null").append(" ELSE ")
            .append(InstanceColumns.DISPLAY_SUBTEXT).append(" END as ").append(InstanceColumns.DISPLAY_SUBTEXT)
            .append(",");
    if (instanceName == null) {
        b.append(DataTableColumns.SAVEPOINT_TIMESTAMP);
    } else {
        b.append(instanceName);
    }
    b.append(" as ").append(InstanceColumns.DISPLAY_NAME);
    b.append(" FROM ");
    b.append("( SELECT * FROM ").append(dbTableName).append(" AS T WHERE T.")
            .append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append("=(SELECT MAX(V.")
            .append(DATA_TABLE_SAVEPOINT_TIMESTAMP_COLUMN).append(") FROM ").append(dbTableName)
            .append(" AS V WHERE V.").append(DATA_TABLE_ID_COLUMN).append("=T.").append(DATA_TABLE_ID_COLUMN)
            .append(" AND V.").append(DATA_TABLE_SAVEPOINT_TYPE_COLUMN).append(" IS NOT NULL").append(")")
            .append(") as ").append(dbTableName);
    b.append(" JOIN ").append(DatabaseConstants.UPLOADS_TABLE_NAME).append(" ON ").append(dbTableName)
            .append(".").append(DATA_TABLE_ID_COLUMN).append("=").append(DatabaseConstants.UPLOADS_TABLE_NAME)
            .append(".").append(InstanceColumns.DATA_INSTANCE_ID).append(" AND ").append("? =")
            .append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".")
            .append(InstanceColumns.DATA_TABLE_TABLE_ID);
    b.append(" WHERE ").append(DATA_TABLE_SAVEPOINT_TYPE_COLUMN).append("=?");
    // @formatter:on

    if (instanceId != null) {
        b.append(" AND ").append(DatabaseConstants.UPLOADS_TABLE_NAME).append(".").append(InstanceColumns._ID)
                .append("=?");
        String tempArgs[] = { tableId, InstanceColumns.STATUS_COMPLETE, instanceId };
        filterArgs = tempArgs;
    } else {
        String tempArgs[] = { tableId, InstanceColumns.STATUS_COMPLETE };
        filterArgs = tempArgs;
    }

    if (selection != null) {
        b.append(" AND (").append(selection).append(")");
    }

    if (selectionArgs != null) {
        String[] tempArgs = new String[filterArgs.length + selectionArgs.length];
        for (int i = 0; i < filterArgs.length; ++i) {
            tempArgs[i] = filterArgs[i];
        }
        for (int i = 0; i < selectionArgs.length; ++i) {
            tempArgs[filterArgs.length + i] = selectionArgs[i];
        }
        filterArgs = tempArgs;
    }

    if (sortOrder != null) {
        b.append(" ORDER BY ").append(sortOrder);
    }

    fullQuery = b.toString();

    db = null;
    boolean success = false;
    try {
        db = DatabaseFactory.get().getDatabase(getContext(), appName);
        c = db.rawQuery(fullQuery, filterArgs);
        // Tell the cursor what uri to watch, so it knows when its source data
        // changes
        c.setNotificationUri(getContext().getContentResolver(), uri);
        success = true;
        return c;
    } finally {
        if (db != null && !success) {
            // leave database open for cursor...
            db.close();
        }
    }
}