FileDocCategorySizeDatePackage
JapaneseContactListIndexer.javaAPI DocAndroid 1.5 API6656Wed May 06 22:42:44 BST 2009com.android.contacts

JapaneseContactListIndexer

public final class JapaneseContactListIndexer extends android.database.DataSetObserver implements android.widget.SectionIndexer
SectionIndexer which is for "phonetically sortable" String. This class heavily depends on the algorithm of the SQL function "GET_PHONETICALLY_SORTABLE_STRING", whose implementation is written in C++.

Fields Summary
private static String
TAG
private static final String[]
sSections
private static final int
sSectionsLength
private int
mColumnIndex
private android.database.Cursor
mDataCursor
private android.util.SparseIntArray
mStringMap
Constructors Summary
public JapaneseContactListIndexer(android.database.Cursor cursor, int columnIndex)

    
         
        int len = sSections.length;
        mColumnIndex = columnIndex;
        mDataCursor = cursor;
        mStringMap = new SparseIntArray(sSectionsLength);
        if (cursor != null) {
            cursor.registerDataSetObserver(this);
        }
    
Methods Summary
public intgetPositionForSection(int sectionIndex)

        final SparseIntArray stringMap = mStringMap;
        final Cursor cursor = mDataCursor;

        if (cursor == null || sectionIndex <= 0) {
            return 0;
        }
        
        if (sectionIndex >= sSectionsLength) {
            sectionIndex = sSectionsLength - 1;
        }

        int savedCursorPos = cursor.getPosition();

        String targetLetter = sSections[sectionIndex];
        int key = targetLetter.codePointAt(0);

        // Check cache map
        {
            int tmp = stringMap.get(key, Integer.MIN_VALUE);
            if (Integer.MIN_VALUE != tmp) {
                return tmp;
            }
        }

        int end = cursor.getCount();
        int pos = 0;

        {
            // Note that sectionIndex > 0.
            int prevLetter = sSections[sectionIndex - 1].codePointAt(0);
            int prevLetterPos = stringMap.get(prevLetter, Integer.MIN_VALUE);
            if (prevLetterPos != Integer.MIN_VALUE) {
                pos = prevLetterPos;
            }
        }
        
        // Do rough binary search if there are a lot of entries.
        while (end - pos > 100) {
            int tmp = (end + pos) / 2;
            cursor.moveToPosition(tmp);
            String sort_name;
            do {
                sort_name = cursor.getString(mColumnIndex);
                if (sort_name == null || sort_name.length() == 0) {
                    // This should not happen, since sort_name field is created
                    // automatically when syncing to a server, or creating/editing
                    // the entry...
                    Log.e(TAG, "sort_name is null or its length is 0. index: " + tmp);
                    cursor.moveToNext();
                    tmp++;
                    continue;
                }
                break;
            } while (tmp < end);
            if (tmp == end) {
                break;
            }
            int codePoint = sort_name.codePointAt(0);
            if (codePoint < getSectionCodePoint(sectionIndex)) {
                pos = tmp;
            } else {
                end = tmp;
            }
        }
        
        for (cursor.moveToPosition(pos); !cursor.isAfterLast(); ++pos, cursor.moveToNext()) {
            String sort_name = cursor.getString(mColumnIndex);
            if (sort_name == null || sort_name.length() == 0) {
                // This should not happen, since sort_name field is created
                // automatically when syncing to a server, or creating/editing
                // the entry...
                Log.e(TAG, "sort_name is null or its length is 0. index: " + pos);
                continue;
            }
            int codePoint = sort_name.codePointAt(0);
            if (codePoint >= getSectionCodePoint(sectionIndex)) {
                break;
            }
        }
        
        stringMap.put(key, pos);
        cursor.moveToPosition(savedCursorPos);
        return pos;
    
private intgetSectionCodePoint(int index)

        if (index < sSections.length - 2) {
            return sSections[index].codePointAt(0);
        } else if (index == sSections.length - 2) {
            return 0xFF66;  // Numbers are mapped from 0xFF66.
        } else {  // index == mSections.length - 1
            return 0xFF70;  // Symbols are mapped from 0xFF70.
        }
    
public intgetSectionForPosition(int position)

        // Not used in Contacts. Ignore for now.
        return 0;
    
public java.lang.Object[]getSections()

        return sSections;
    
public voidonChanged()

        super.onChanged();
        mStringMap.clear();
    
public voidonInvalidated()

        super.onInvalidated();
        mStringMap.clear();
    
public voidsetCursor(android.database.Cursor cursor)

        if (mDataCursor != null) {
            mDataCursor.unregisterDataSetObserver(this);
        }
        mDataCursor = cursor;
        if (cursor != null) {
            mDataCursor.registerDataSetObserver(this);
        }