FileDocCategorySizeDatePackage
AbstractCursor.javaAPI DocAndroid 1.5 API18713Wed May 06 22:41:54 BST 2009android.database

AbstractCursor

public abstract class AbstractCursor extends Object implements CrossProcessCursor
This is an abstract cursor class that handles a lot of the common code that all cursors need to deal with and is provided for convenience reasons.

Fields Summary
private static final String
TAG
DataSetObservable
mDataSetObservable
ContentObservable
mContentObservable
protected HashMap
mUpdatedRows
This HashMap contains a mapping from Long rowIDs to another Map that maps from String column names to new values. A NULL value means to remove an existing value, and all numeric values are in their class forms, i.e. Integer, Long, Float, etc.
protected int
mRowIdColumnIndex
This must be set to the index of the row ID column by any subclass that wishes to support updates.
protected int
mPos
protected Long
mCurrentRowID
protected android.content.ContentResolver
mContentResolver
protected boolean
mClosed
private android.net.Uri
mNotifyUri
private ContentObserver
mSelfObserver
private final Object
mSelfObserverLock
private boolean
mSelfObserverRegistered
Constructors Summary
public AbstractCursor()

        mPos = -1;
        mRowIdColumnIndex = -1;
        mCurrentRowID = null;
        mUpdatedRows = new HashMap<Long, Map<String, Object>>();
    
Methods Summary
public voidabortUpdates()

hide
deprecated

        synchronized(mUpdatedRows) {
            mUpdatedRows.clear();
        }
    
protected voidcheckPosition()
This function throws CursorIndexOutOfBoundsException if the cursor position is out of bounds. Subclass implementations of the get functions should call this before attempting to retrieve data.

throws
CursorIndexOutOfBoundsException

        if (-1 == mPos || getCount() == mPos) {
            throw new CursorIndexOutOfBoundsException(mPos, getCount());
        }
    
public voidclose()

        mClosed = true;
        mContentObservable.unregisterAll();
        deactivateInternal();
    
public booleancommitUpdates(java.util.Map values)

hide
deprecated

        return false;
    
public booleancommitUpdates()

hide
deprecated

        return commitUpdates(null);
    
public voidcopyStringToBuffer(int columnIndex, CharArrayBuffer buffer)

        // Default implementation, uses getString
        String result = getString(columnIndex);
        if (result != null) {
            char[] data = buffer.data;
            if (data == null || data.length < result.length()) {
                buffer.data = result.toCharArray();
            } else {
                result.getChars(0, result.length(), data, 0);
            }
            buffer.sizeCopied = result.length();
        }
    
public voiddeactivate()

        deactivateInternal();
    
public voiddeactivateInternal()

hide

        if (mSelfObserver != null) {
            mContentResolver.unregisterContentObserver(mSelfObserver);
            mSelfObserverRegistered = false;
        }
        mDataSetObservable.notifyInvalidated();
    
public booleandeleteRow()

hide
deprecated

        return false;
    
public voidfillWindow(int position, CursorWindow window)
Copy data from cursor to CursorWindow

param
position start position of data
param
window

        if (position < 0 || position > getCount()) {
            return;
        }
        window.acquireReference();
        try {
            int oldpos = mPos;
            mPos = position - 1;
            window.clear();
            window.setStartPosition(position);
            int columnNum = getColumnCount();
            window.setNumColumns(columnNum);
            while (moveToNext() && window.allocRow()) {            
                for (int i = 0; i < columnNum; i++) {
                    String field = getString(i);
                    if (field != null) {
                        if (!window.putString(field, mPos, i)) {
                            window.freeLastRow();
                            break;
                        }
                    } else {
                        if (!window.putNull(mPos, i)) {
                            window.freeLastRow();
                            break;
                        }
                    }
                }
            }
            
            mPos = oldpos;
        } catch (IllegalStateException e){
            // simply ignore it
        } finally {
            window.releaseReference();
        }
    
protected voidfinalize()

        if (mSelfObserver != null && mSelfObserverRegistered == true) {
            mContentResolver.unregisterContentObserver(mSelfObserver);
        }
    
public byte[]getBlob(int column)


    /* -------------------------------------------------------- */
    /* These need to be implemented by subclasses */
       

       

        
        
        
        
        
        
        

    // TODO implement getBlob in all cursor types
        
        throw new UnsupportedOperationException("getBlob is not supported");
    
public intgetColumnCount()

        return getColumnNames().length;
    
public intgetColumnIndex(java.lang.String columnName)

        // Hack according to bug 903852
        final int periodIndex = columnName.lastIndexOf('.");
        if (periodIndex != -1) {
            Exception e = new Exception();
            Log.e(TAG, "requesting column name with table name -- " + columnName, e);
            columnName = columnName.substring(periodIndex + 1);
        }

        String columnNames[] = getColumnNames();
        int length = columnNames.length;
        for (int i = 0; i < length; i++) {
            if (columnNames[i].equalsIgnoreCase(columnName)) {
                return i;
            }
        }

        if (Config.LOGV) {
            if (getCount() > 0) {
                Log.w("AbstractCursor", "Unknown column " + columnName);
            }
        }
        return -1;
    
public intgetColumnIndexOrThrow(java.lang.String columnName)

        final int index = getColumnIndex(columnName);
        if (index < 0) {
            throw new IllegalArgumentException("column '" + columnName + "' does not exist");
        }
        return index;
    
public java.lang.StringgetColumnName(int columnIndex)

        return getColumnNames()[columnIndex];
    
public abstract java.lang.String[]getColumnNames()

public abstract intgetCount()

protected DataSetObservablegetDataSetObservable()
This is hidden until the data set change model has been re-evaluated.

hide

        return mDataSetObservable;
        
    
public abstract doublegetDouble(int column)

public android.os.BundlegetExtras()

        return Bundle.EMPTY;
    
public abstract floatgetFloat(int column)

public abstract intgetInt(int column)

public abstract longgetLong(int column)

public final intgetPosition()

        return mPos;
    
public abstract shortgetShort(int column)

public abstract java.lang.StringgetString(int column)

protected java.lang.ObjectgetUpdatedField(int columnIndex)
This function returns the uncommitted updated value for the field at columnIndex. NOTE: This function and {@link #isFieldUpdated} should be called together inside of a block synchronized on mUpdatedRows.

param
columnIndex the column index of the field to retrieve
return
the updated value

        Map<String, Object> updates = mUpdatedRows.get(mCurrentRowID);
        return updates.get(getColumnNames()[columnIndex]);
    
public booleangetWantsAllOnMoveCalls()

        return false;
    
public CursorWindowgetWindow()
returns a pre-filled window, return NULL if no such window

        return null;
    
public booleanhasUpdates()
Returns true if there are pending updates that have not yet been committed.

return
true if there are pending updates that have not yet been committed.
hide
deprecated

        synchronized(mUpdatedRows) {
            return mUpdatedRows.size() > 0;
        }
    
public final booleanisAfterLast()

        if (getCount() == 0) {
            return true;
        }
        return mPos == getCount();
    
public final booleanisBeforeFirst()

        if (getCount() == 0) {
            return true;
        }
        return mPos == -1;
    
public booleanisClosed()

        return mClosed;
    
protected booleanisFieldUpdated(int columnIndex)
This function returns true if the field has been updated and is used in conjunction with {@link #getUpdatedField} to allow subclasses to support reading uncommitted updates. NOTE: This function and {@link #getUpdatedField} should be called together inside of a block synchronized on mUpdatedRows.

param
columnIndex the column index of the field to check
return
true if the field has been updated, false otherwise

        if (mRowIdColumnIndex != -1 && mUpdatedRows.size() > 0) {
            Map<String, Object> updates = mUpdatedRows.get(mCurrentRowID);
            if (updates != null && updates.containsKey(getColumnNames()[columnIndex])) {
                return true;
            }
        }
        return false;
    
public final booleanisFirst()

        return mPos == 0 && getCount() != 0;
    
public final booleanisLast()

        int cnt = getCount();
        return mPos == (cnt - 1) && cnt != 0;
    
public abstract booleanisNull(int column)

public final booleanmove(int offset)

        return moveToPosition(mPos + offset);
    
public final booleanmoveToFirst()

        return moveToPosition(0);
    
public final booleanmoveToLast()

        return moveToPosition(getCount() - 1);
    
public final booleanmoveToNext()

        return moveToPosition(mPos + 1);
    
public final booleanmoveToPosition(int position)

        // Make sure position isn't past the end of the cursor
        final int count = getCount();
        if (position >= count) {
            mPos = count;
            return false;
        }

        // Make sure position isn't before the beginning of the cursor
        if (position < 0) {
            mPos = -1;
            return false;
        }

        // Check for no-op moves, and skip the rest of the work for them
        if (position == mPos) {
            return true;
        }

        boolean result = onMove(mPos, position);
        if (result == false) {
            mPos = -1;
        } else {
            mPos = position;
            if (mRowIdColumnIndex != -1) {
                mCurrentRowID = Long.valueOf(getLong(mRowIdColumnIndex));
            }
        }

        return result;
    
public final booleanmoveToPrevious()

        return moveToPosition(mPos - 1);
    
protected voidnotifyDataSetChange()
This is hidden until the data set change model has been re-evaluated.

hide

        mDataSetObservable.notifyChanged();
    
protected voidonChange(boolean selfChange)
Subclasses must call this method when they finish committing updates to notify all observers.

param
selfChange

        synchronized (mSelfObserverLock) {
            mContentObservable.dispatchChange(selfChange);
            if (mNotifyUri != null && selfChange) {
                mContentResolver.notifyChange(mNotifyUri, mSelfObserver);
            }
        }
    
public booleanonMove(int oldPosition, int newPosition)
This function is called every time the cursor is successfully scrolled to a new position, giving the subclass a chance to update any state it may have. If it returns false the move function will also do so and the cursor will scroll to the beforeFirst position.

param
oldPosition the position that we're moving from
param
newPosition the position that we're moving to
return
true if the move is successful, false otherwise

        return true;
    
public voidregisterContentObserver(ContentObserver observer)

        mContentObservable.registerObserver(observer);
    
public voidregisterDataSetObserver(DataSetObserver observer)

        mDataSetObservable.registerObserver(observer);
        
    
public booleanrequery()

        if (mSelfObserver != null && mSelfObserverRegistered == false) {
            mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
            mSelfObserverRegistered = true;
        }
        mDataSetObservable.notifyChanged();
        return true;
    
public android.os.Bundlerespond(android.os.Bundle extras)

        return Bundle.EMPTY;
    
public voidsetNotificationUri(android.content.ContentResolver cr, android.net.Uri notifyUri)
Specifies a content URI to watch for changes.

param
cr The content resolver from the caller's context.
param
notifyUri The URI to watch for changes. This can be a specific row URI, or a base URI for a whole class of content.

        synchronized (mSelfObserverLock) {
            mNotifyUri = notifyUri;
            mContentResolver = cr;
            if (mSelfObserver != null) {
                mContentResolver.unregisterContentObserver(mSelfObserver);
            }
            mSelfObserver = new SelfContentObserver(this);
            mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
            mSelfObserverRegistered = true;
        }
    
public booleansupportsUpdates()

hide
deprecated

        return mRowIdColumnIndex != -1;
    
public voidunregisterContentObserver(ContentObserver observer)

        // cursor will unregister all observers when it close
        if (!mClosed) {
            mContentObservable.unregisterObserver(observer);
        }
    
public voidunregisterDataSetObserver(DataSetObserver observer)

        mDataSetObservable.unregisterObserver(observer);
    
public booleanupdate(int columnIndex, java.lang.Object obj)

hide
deprecated

        if (!supportsUpdates()) {
            return false;
        }

        // Long.valueOf() returns null sometimes!
//        Long rowid = Long.valueOf(getLong(mRowIdColumnIndex));
        Long rowid = new Long(getLong(mRowIdColumnIndex));
        if (rowid == null) {
            throw new IllegalStateException("null rowid. mRowIdColumnIndex = " + mRowIdColumnIndex);
        }

        synchronized(mUpdatedRows) {
            Map<String, Object> row = mUpdatedRows.get(rowid);
            if (row == null) {
                row = new HashMap<String, Object>();
                mUpdatedRows.put(rowid, row);
            }
            row.put(getColumnNames()[columnIndex], obj);
        }

        return true;
    
public booleanupdateBlob(int columnIndex, byte[] value)

hide
deprecated

        return update(columnIndex, value);
    
public booleanupdateDouble(int columnIndex, double value)

hide
deprecated

        return update(columnIndex, Double.valueOf(value));
    
public booleanupdateFloat(int columnIndex, float value)

hide
deprecated

        return update(columnIndex, Float.valueOf(value));
    
public booleanupdateInt(int columnIndex, int value)

hide
deprecated

        return update(columnIndex, Integer.valueOf(value));
    
public booleanupdateLong(int columnIndex, long value)

hide
deprecated

        return update(columnIndex, Long.valueOf(value));
    
public booleanupdateShort(int columnIndex, short value)

hide
deprecated

        return update(columnIndex, Short.valueOf(value));
    
public booleanupdateString(int columnIndex, java.lang.String value)

hide
deprecated

        return update(columnIndex, value);
    
public booleanupdateToNull(int columnIndex)

hide
deprecated

        return update(columnIndex, null);