自己动手写 android 数据库(2)

package com.neolink.providers.contacts;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Pattern;

import com.android.common.content.ProjectionMap;
import com.google.android.collect.Maps;
import com.neolink.providers.contacts.PrivateContactsDataHelper.Tables;
import com.neolink.providers.contacts.PrivateContactsDataHelper.Views;
import com.neolink.providers.util.HanziToPinyin;
import com.neolink.providers.util.HanziToPinyin.Token;
import com.neolink.providers.util.Utils;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.UriMatcher;
import android.content.pm.ProviderInfo;
import android.content.res.Resources;
import android.database.AbstractCursor;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteCantOpenDatabaseException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDoneException;
import android.database.sqlite.SQLiteFullException;
import android.database.sqlite.SQLiteQueryBuilder;
import android.database.sqlite.SQLiteStatement;
import android.database.sqlite.SQLiteTransactionListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.Process;
import android.os.StrictMode;
import android.provider.BaseColumns;
import android.provider.OpenableColumns;
import android.provider.Settings;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.ContactCounts;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MHTUtil;
import neolink.telephony.PrivateContactConst;
import neolink.telephony.PrivateContactContracts;
import neolink.telephony.PrivateManager;
import neolink.telephony.PrivateMode;
import neolink.telephony.PrivateContactConst.DataKindMimeType;
import neolink.telephony.PrivateContactContracts.CallLogColumns;
import neolink.telephony.PrivateContactContracts.Contacts;
import neolink.telephony.PrivateContactContracts.ContactsColumns;
import neolink.telephony.PrivateContactContracts.Data;
import neolink.telephony.PrivateContactContracts.DataColumns;
import neolink.telephony.PrivateContactContracts.GroupContact;
import neolink.telephony.PrivateContactContracts.GroupContactColumns;
import neolink.telephony.PrivateContactContracts.MimetypesColumns;
import neolink.telephony.PrivateContactContracts.ZoneColumns;
import android.app.Application;
import android.app.SearchManager;

public class PrivateContactsProvider extends ContentProvider implements
        SQLiteTransactionListener {
    public static final String LOG_TAG = "PrivateContactsProvider";
    private HandlerThread mBackgroundThread;
    private Handler mBackgroundHandler;
    private static final UriMatcher URI_MATCHER = new UriMatcher(
            UriMatcher.NO_MATCH);

    private PrivateContactsDataHelper mPrivateContactsDatabaseHelper;
    private SQLiteStatement mContactDisplayNameUpdate;
    private SQLiteStatement mContactToDataUpdate;
    private SQLiteStatement mContactToCallLogUpdate;
    private SQLiteStatement mGroupToDataUpdate;

    private PrivateContactTransactionContext mContactTransactionContext = new PrivateContactTransactionContext();
    private final ThreadLocal<PrivateContactTransactionContext> mTransactionContext = new ThreadLocal<PrivateContactTransactionContext>();

    private static final int PRIVATE_CONTACTS = 100;
    private static final int PRIVATE_CONTACTS_ID = 101;
    private static final int PRIVATE_CONTACTS_ID_DATAS = 102;
    private static final int DATABASE_VERSION = 2;
    private static HashMap<String, String> sNotesProjectionMap;
    private static final int PRIVATE_DATA = 200;
    private static final int PRIVATE_DATA_GROUP = 201;
    private static final int PRIVATE_DATA_CONTACTS = 202;
    private static final int PRIVATE_DATA_ID = 203;

    private static final int PRIVATE_GROUP_CONTACT = 300;
    private static final int PRIVATE_GROUP_CONTACT_ID = 301;

    private static final int PRIVATE_GROUP_TYPE = 111;

    private static final int PRIVATE_CALLLOG = 115;
    private static final int PRIVATE_CALLLOG_ID = 116;

    private static final int PRIVATE_INDEXSEARCH_ID = 800;
    private static final int PRIVATE_GROUP_ZONE = 801;
    private static final int PRIVATE_MIMETYPE = 802;

    private final ThreadLocal<SQLiteDatabase> mDb = new ThreadLocal<SQLiteDatabase>();
    private final ThreadLocal<PrivateContactsDataHelper> mDbHelper = new ThreadLocal<PrivateContactsDataHelper>();

    private HashMap<String, Long> mMimeTypeCache;
    private final HashMap<String, Long> mZoneIdCache = new HashMap<String, Long>();

    public static final String UPDATE_CONTACTS = "SELECT "
            + DataColumns.MIMETYPE_ID + "," + Data.DATA1 + "," + Data.DATA2
            + "," + Data.DATA3 + " FROM " + Tables.PRIVATE_DATA + " WHERE "
            + Data.CONTACT_ID + " = ?";

    public static final String UPDATE_CALL_LOG_FROM_CONTACTS = "SELECT "
            + ContactsColumns._ID + "," + ContactsColumns.DISPLAY_NAME
            + " FROM " + Tables.PRIVATE_CONTACT + " WHERE "
            + ContactsColumns.NUMBER + " =? ";

    public static final String UPDATE_CALL_LOG_FROM_GROUP = "SELECT "
            + GroupContactColumns._ID + ","
            + GroupContactColumns.GROUP_MODE_TYPE + ","
            + GroupContactColumns.GROUP_CONTACT_NUMBER + " FROM "
            + Tables.PRIVATE_CONTACT + " WHERE ("
            + GroupContactColumns.GROUP_MODE_TYPE + " = ?" + " AND "
            + GroupContactColumns.GROUP_CONTACT_NUMBER + " = ?" + " )";

    static {

        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "contacts",
                PRIVATE_CONTACTS);
        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "contacts/#",
                PRIVATE_CONTACTS_ID);

        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY,
                "contacts_filter/#", PRIVATE_INDEXSEARCH_ID);

        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY,
                "contacts/#/datas", PRIVATE_CONTACTS_ID_DATAS);

        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "p_data",
                PRIVATE_DATA);
        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "p_data/#",
                PRIVATE_DATA_ID);

        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "p_data_group",
                PRIVATE_DATA_GROUP);
        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "p_data_contact",
                PRIVATE_DATA_CONTACTS);

        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "p_groups",
                PRIVATE_GROUP_CONTACT);

        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY,
                "PrivateGroupContact/#", PRIVATE_GROUP_CONTACT_ID);
        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY,
                "PrivateGroupContact/#", PRIVATE_GROUP_TYPE);
        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "p_calls/#",
                PRIVATE_CALLLOG_ID);
        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "p_calls",
                PRIVATE_CALLLOG);

        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "p_zone",
                PRIVATE_GROUP_ZONE);
        URI_MATCHER.addURI(PrivateContactContracts.AUTHORITY, "p_type",
                PRIVATE_MIMETYPE);
    }

    /** Contains just the contacts columns */
    private static final ProjectionMap sContactsColumns = ProjectionMap
            .builder().add(PrivateContactContracts.ContactsColumns._ID)
            .add(ContactsColumns.NUMBER).add(ContactsColumns.DISPLAY_NAME)
            .add(ContactsColumns.CONTACTS_PCTOOLS)
            .add(ContactsColumns.CONTACTS_TYPE)
            .add(ContactsColumns.CURRENT_MODE).add(ContactsColumns.SORT_KEY)
            .build();

    /** Contains just the zone columns */
    private static final ProjectionMap sZoneColumns = ProjectionMap.builder()
            .add(PrivateContactContracts.ZoneColumns._ID)
            .add(ZoneColumns.ZONE_NAME).build();

    /** Contains just the group columns */
    private static final ProjectionMap sGroupsColumns = ProjectionMap.builder()
            .add(PrivateContactContracts.ContactsColumns._ID)
            .add(GroupContactColumns.GROUP_ID)
            .add(GroupContactColumns.GROUP_CONTACT_NAME)
            .add(GroupContactColumns.GROUP_CONTACT_NUMBER)
            .add(GroupContactColumns.GROUP_CONTACT_TYPE)
            .add(GroupContactColumns.GROUP_ZONE_NAME)
            .add(GroupContactColumns.GROUP_ZONE_ID)
            .add(GroupContactColumns.GROUP_DEFAULT)
            .add(GroupContactColumns.GROUP_MODE_TYPE).build();

    /** Contains just the data columns */
    private static final ProjectionMap sDataColumns = ProjectionMap.builder()
            .add(DataColumns._ID).add(DataColumns.GROUP_ID)
            .add(DataColumns.MIMETYPE_ID).add(DataColumns.CONTACT_ID)
            .add(DataColumns.DATA1).add(DataColumns.DATA2)
            .add(DataColumns.DATA3).build();

    /** Contains just the call log columns */
    private static final ProjectionMap sCallLogColumns = ProjectionMap
            .builder().add(CallLogColumns._ID).add(CallLogColumns.NUMBER)
            .add(CallLogColumns.DISPLAY_NAME).add(CallLogColumns.DATE)
            .add(CallLogColumns.DURATION).add(CallLogColumns.CALL_LOG_MODE)
            .add(CallLogColumns.IS_READ).add(CallLogColumns.IS_HANDUP)
            .add(CallLogColumns.IS_NEW).build();

    /** Contains just the call the mimetype columns */
    private static final ProjectionMap sMimetypeColumns = ProjectionMap
            .builder().add(MimetypesColumns._ID).add(MimetypesColumns.MIMETYPE)
            .build();

    private volatile PrivateContactsCountDownLatch mReadAccessLatch;
    private volatile PrivateContactsCountDownLatch mWriteAccessLatch;
    private int mMode;

    @Override
    public boolean onCreate() {
        Utils.logProvider("on create");
        mPrivateContactsDatabaseHelper = PrivateContactsDataHelper
                .getInstance(getContext());
        mTransactionContext.set(mContactTransactionContext);
        mMimeTypeCache = mPrivateContactsDatabaseHelper.mMimetypeCache;
        mDbHelper.set(mPrivateContactsDatabaseHelper);
        initialize();
        return true;
    }

    private boolean initialize() {

        mReadAccessLatch = new PrivateContactsCountDownLatch(1);
        mWriteAccessLatch = new PrivateContactsCountDownLatch(1);
        mBackgroundThread = new HandlerThread("ContactsProviderWorker",
                Process.THREAD_PRIORITY_BACKGROUND);
        mBackgroundThread.start();
        mBackgroundHandler = new Handler(mBackgroundThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                performBackgroundTask(msg.what, msg.obj);
            }
        };

        return true;
    }

    protected void performBackgroundTask(int task, Object arg) {
        switch (task) {
        }
    }

    private void waitForAccess(PrivateContactsCountDownLatch latch) {
        if (latch == null) {
            return;
        }

        while (true) {
            try {
                latch.await();
                return;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    protected void scheduleBackgroundTask(int task) {
        mBackgroundHandler.sendEmptyMessage(task);
    }

    protected void scheduleBackgroundTask(int task, Object arg) {
        mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(task,
                arg));
    }

    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {

        int match = URI_MATCHER.match(uri);
        Utils.logProvider("PrivateContactsProvider   query uri is:" + uri
                + " selection is:" + selection + "  sortOrder is:" + sortOrder
                + "match=" + match);

        if (selectionArgs != null) {
            for (int i = 0; i < selectionArgs.length; i++) {
                Utils.logProvider("selectionArgs==" + selectionArgs[i]);
            }
        }
        checkReadableDB();
        // waitForAccess(mWriteAccessLatch);
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        switch (match) {
        case PRIVATE_INDEXSEARCH_ID:

            setTablesAndProjectionMapFroPrivateIndexSearch(qb, uri);
            final String[] PROJECTION = new String[] {
                    PrivateContactContracts.ContactsColumns._ID,
                    Contacts.DISPLAY_NAME, Contacts.SEARCH_INDEX_NAME,
                    Contacts.SEARCH_INDEX_NUMBER };
            String[] selectionArgsIndex = null;
            if (!TextUtils.isEmpty(selection)) {

                String pingyingName = getFullPinYin(selection);// get the
                                                                // pingyin name;
                String firstName = getFirstPinYin(selection); // get the first
                                                                // name;
                selectionArgsIndex = new String[pingyingName.length()];

                if (!isNumeric(pingyingName)) {

                    selection = "search_index like ?";
                    for (int i = 0; i < pingyingName.length() - 1; i++) {
                        selection = selection + "or search_index like ?"
                                + "or number like ?";
                    }
                    for (int i = 0; i < pingyingName.length(); i++) {
                        selectionArgsIndex[i] = "%" + pingyingName + "%";
                    }

                } else {
                    selection = "number like ?";
                    for (int i = 0; i < pingyingName.length() - 1; i++) {
                        selection = selection + "or number like ?"
                                + "or number like ?";
                    }
                    for (int i = 0; i < pingyingName.length(); i++) {
                        selectionArgsIndex[i] = "%" + pingyingName + "%";
                    }

                }
            } else {
                selection = null;
                selectionArgs = null;

            }
            Cursor cursorIndex = qb.query(mDb.get(), PROJECTION, selection,
                    selectionArgsIndex, null, null, sortOrder);
            if (cursorIndex != null) {
                cursorIndex.setNotificationUri(getContext()
                        .getContentResolver(),
                        PrivateContactContracts.AUTHORITY_URI);
            }
            return cursorIndex;

        case PRIVATE_CONTACTS:
            setTablesAndProjectionMapForPrivateContact(qb, uri);
            Cursor contactscursor = qb.query(mDb.get(), projection, selection,
                    selectionArgs, null, null, sortOrder);
            Utils.logProvider("PrivateContatProvider after nomal query cursor :"
                    + contactscursor);
            if (contactscursor != null) {
                contactscursor.setNotificationUri(getContext()
                        .getContentResolver(),
                        PrivateContactContracts.AUTHORITY_URI);
            }
            return contactscursor;
        case PRIVATE_CONTACTS_ID_DATAS:
            List<String> pathSegments = uri.getPathSegments();

            for (String s : pathSegments) {
                Utils.logProvider("PrivateContactsProvider query pathSegments s:"
                        + s);
            }
            long contactId = Long.parseLong(pathSegments.get(1));
            setTablesAndProjectionMapForData(qb, uri);
            selectionArgs = insertSelectionArg(selectionArgs,
                    String.valueOf(contactId));
            qb.appendWhere(Data.CONTACT_ID + " = ? ");
            StringBuffer sbTemp = new StringBuffer();
            for (String s : projection) {
                sbTemp.append(s + ",");
            }
            Utils.logProvider("PrivateContactsProvider projection :"
                    + sbTemp.toString() + " selection :" + selection
                    + " selectionArgs :" + sbTemp.toString());
            sbTemp = new StringBuffer();
            for (String s : selectionArgs) {
                sbTemp.append(s + ",");
            }
            break;
        case PRIVATE_CONTACTS_ID:
            long contact_Id = ContentUris.parseId(uri);
            setTablesAndProjectionMapForData(qb, uri);
            selectionArgs = insertSelectionArg(selectionArgs,
                    String.valueOf(contact_Id));
            qb.appendWhere(Data.CONTACT_ID + " = ? ");
            break;
        case PRIVATE_GROUP_ZONE:
            setTablesAndProjectionMapFroPrivateZone(qb, uri);
            Cursor groupCursor = qb.query(mDb.get(), projection, selection,
                    selectionArgs, null, null, sortOrder);
            return groupCursor;

        case PRIVATE_GROUP_CONTACT:
            setTablesAndProjectionMapFroPrivateGroupContact(qb, uri);
            Cursor zoneCursor = qb.query(mDb.get(), projection, selection,
                    selectionArgs, null, null, sortOrder);
            return zoneCursor;
        case PRIVATE_CALLLOG:
            setTablesAndProjectionMapFroPrivateCall(qb, uri);
            Cursor CallLogCursor = qb.query(mDb.get(), projection, selection,
                    selectionArgs, null, null, sortOrder);
            return CallLogCursor;
        case PRIVATE_DATA:

            setTablesAndProjectionMapForData(qb, uri);
            Cursor cursor = qb.query(mDb.get(), projection, selection,
                    selectionArgs, null, null, sortOrder);

            return cursor;
        case PRIVATE_DATA_CONTACTS:

            setTablesAndProjectionMapForData(qb, uri);
            Cursor datacursor = qb.query(mDb.get(), projection, selection,
                    selectionArgs, null, null, sortOrder);

            return datacursor;

        case PRIVATE_DATA_GROUP:

            setTablesAndProjectionMapForData(qb, uri);
            Cursor groupcursor = qb.query(mDb.get(), projection, selection,
                    selectionArgs, null, null, sortOrder);

            return groupcursor;
        default:
            Utils.logProvider(" the url is error");
        }
        return null;
    }

    private String[] insertSelectionArg(String[] selectionArgs, String arg) {
        if (selectionArgs == null) {
            return new String[] { arg };
        } else {
            int newLength = selectionArgs.length + 1;
            String[] newSelectionArgs = new String[newLength];
            newSelectionArgs[0] = arg;
            System.arraycopy(selectionArgs, 0, newSelectionArgs, 1,
                    selectionArgs.length);
            return newSelectionArgs;
        }
    }

    private static final class AddressBookIndexQuery {
        public static final String LETTER = "letter";
        public static final String TITLE = "title";
        public static final String COUNT = "count";

        public static final String[] COLUMNS = new String[] { LETTER, TITLE,
                COUNT };

        public static final int COLUMN_LETTER = 0;
        public static final int COLUMN_TITLE = 1;
        public static final int COLUMN_COUNT = 2;

        // The first letter of the sort key column is what is used for the index
        // headings.
        public static final String SECTION_HEADING = "SUBSTR(%1$s,1,1)";

        public static final String ORDER_BY = LETTER + " COLLATE "
                + "PHONEBOOK";
    }

    private Cursor bundleLetterCountExtras(Cursor cursor,
            final SQLiteDatabase DB, SQLiteQueryBuilder qb, String selection,
            String[] selectionArgs, String sortOrder, String countExpression) {
        if (!(cursor instanceof AbstractCursor)) {
            Log.w(LOG_TAG,
                    "Unable to bundle extras.  Cursor is not AbstractCursor.");
            return cursor;
        }
        checkReadableDB();
        String sortKey;
        String sortOrderSuffix = "";
        if (sortOrder != null) {
            int spaceIndex = sortOrder.indexOf(' ');
            if (spaceIndex != -1) {
                sortKey = sortOrder.substring(0, spaceIndex);
                sortOrderSuffix = sortOrder.substring(spaceIndex);
            } else {
                sortKey = sortOrder;
            }
        } else {
            sortKey = Contacts.SORT_KEY;
        }

        String locale = Locale.getDefault().toString();

        HashMap<String, String> projectionMap = Maps.newHashMap();
        String sectionHeading = String.format(Locale.US,
                AddressBookIndexQuery.SECTION_HEADING, sortKey);
        projectionMap.put(AddressBookIndexQuery.LETTER, sectionHeading + " AS "
                + AddressBookIndexQuery.LETTER);

        // If "what to count" is not specified, we just count all records.
        if (TextUtils.isEmpty(countExpression)) {
            countExpression = "*";
        }
        projectionMap.put(AddressBookIndexQuery.TITLE, "GET_PHONEBOOK_INDEX("
                + sectionHeading + ",'" + locale + "')" + " AS "
                + AddressBookIndexQuery.TITLE);
        projectionMap.put(AddressBookIndexQuery.COUNT, "COUNT("
                + countExpression + ") AS " + AddressBookIndexQuery.COUNT);
        qb.setProjectionMap(projectionMap);

        Cursor indexCursor = qb.query(mDb.get(), AddressBookIndexQuery.COLUMNS,
                selection, selectionArgs, AddressBookIndexQuery.ORDER_BY,
                null /* having */, AddressBookIndexQuery.ORDER_BY
                        + sortOrderSuffix);

        try {
            int groupCount = indexCursor.getCount();
            Utils.logProvider("ContactsProvider2 bundleLetterCountExtra groupCount is:"
                    + groupCount);
            String titles[] = new String[groupCount];
            int counts[] = new int[groupCount];
            int indexCount = 0;
            String currentTitle = null;

            // Since GET_PHONEBOOK_INDEX is a many-to-1 function, we may end up
            // with multiple entries for the same title. The following code
            // collapses those duplicates.
            for (int i = 0; i < groupCount; i++) {
                indexCursor.moveToNext();
                String title = indexCursor
                        .getString(AddressBookIndexQuery.COLUMN_TITLE);
                int count = indexCursor
                        .getInt(AddressBookIndexQuery.COLUMN_COUNT);
                Utils.logProvider("ContactsProvider2 bundleLetterCountExtra currentTitle is:"
                        + currentTitle
                        + "  title is:"
                        + title
                        + " count is:"
                        + count);
                if (indexCount == 0 || !TextUtils.equals(title, currentTitle)) {
                    titles[indexCount] = currentTitle = title;
                    counts[indexCount] = count;
                    indexCount++;
                } else {
                    counts[indexCount - 1] += count;
                }
            }
            Utils.logProvider("ContactsProvider2 bundleLetterCountExtra indexCount is:"
                    + indexCount);
            if (indexCount < groupCount) {
                String[] newTitles = new String[indexCount];
                System.arraycopy(titles, 0, newTitles, 0, indexCount);
                titles = newTitles;

                int[] newCounts = new int[indexCount];
                System.arraycopy(counts, 0, newCounts, 0, indexCount);
                counts = newCounts;
            }

            final Bundle bundle = new Bundle();
            bundle.putStringArray(
                    ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, titles);
            bundle.putIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS,
                    counts);
            ((AbstractCursor) cursor).setExtras(bundle);
            return cursor;
        } finally {
            indexCursor.close();
        }
    }

    private boolean readBooleanQueryParameter(Uri uri, String parameter,
            boolean defaultValue) {
        String query = uri.getEncodedQuery();
        if (query == null) {
            return defaultValue;
        }
        int index = query.indexOf(parameter);
        if (index == -1) {
            return defaultValue;
        }
        index += parameter.length();
        return !matchQueryParameter(query, index, "=0", false)
                && !matchQueryParameter(query, index, "=false", true);
    }

    private static boolean matchQueryParameter(String query, int index,
            String value, boolean ignoreCase) {
        Utils.logProvider("COntactsProvider2 matchQueryParameter query is:"
                + query + " index is:" + index + "value is:" + value
                + "ingnore is:" + ignoreCase);
        int length = value.length();
        return query.regionMatches(ignoreCase, index, value, 0, length)
                && (query.length() == index + length || query.charAt(index
                        + length) == '&');
    }

    private void setTablesAndProjectionMapForPrivateContact(
            SQLiteQueryBuilder qb, Uri uri) {
        StringBuilder sb = new StringBuilder();
        sb.append(Views.PRIVATE_CONTACT);
        qb.setProjectionMap(sContactsColumns);
        qb.setTables(sb.toString());
    }

    private void setTablesAndProjectionMapFroPrivateGroupContact(
            SQLiteQueryBuilder qb, Uri uri) {
        qb.setTables(Tables.PRIVATE_GROUP_CONTACT);
        qb.setProjectionMap(sGroupsColumns);
    }

    private void setTablesAndProjectionMapFroPrivateZone(SQLiteQueryBuilder qb,
            Uri uri) {
        qb.setTables(Tables.PRIVATE_ZONE);
        qb.setProjectionMap(sZoneColumns);
    }

    private void setTablesAndProjectionMapFroPrivateIndexSearch(
            SQLiteQueryBuilder qb, Uri uri) {
        qb.setTables(Tables.PRIVATE_CONTACT);
    }

    private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri) {
        StringBuilder sb = new StringBuilder();
        sb.append(Tables.PRIVATE_DATA);
        qb.setTables(sb.toString());
        qb.setProjectionMap(sDataColumns);
    }

    private void setTablesAndProjectionMapFroPrivateCall(SQLiteQueryBuilder qb,
            Uri uri) {
        qb.setTables(Tables.PRIVATE_CALL);
        qb.setProjectionMap(sCallLogColumns);
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        Utils.logProvider("PrivateContactsProvider update uri is:" + uri
                + " contentValues is:" + values + "selection=" + selection
                + "URI_MATCHER.match(uri)" + URI_MATCHER.match(uri));

        if (selectionArgs != null) {
            for (int i = 0; i < selectionArgs.length; i++) {
                Utils.logProvider("selectionArgs==" + selectionArgs[i]);
            }
        }
        checkWritableDb();
        // waitForAccess(mWriteAccessLatch);
        return doUpdateActionInTransaction(uri, values, selection,
                selectionArgs);
    }

    private Uri doInsertActionInTransaction(Uri uri, ContentValues values) {
        Uri result = null;
        SQLiteDatabase db = mPrivateContactsDatabaseHelper
                .getWritableDatabase();
        db.beginTransactionWithListener(this);
        try {

            result = insertInTransaction(uri, values);

            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
            contactyChanged(uri);

        }

        return result;
    }

    private void contactyChanged(Uri uri) {
        // Log.d(LOG_TAG, "do***************noticefy>>r" + uri);
        if (uri.equals(PrivateContactContracts.Contacts.CONTENT_URI)) {
            getContext().getContentResolver().notifyChange(
                    Contacts.CONTENT_URI, null, false);
        } else if (uri.equals(PrivateContactContracts.Data.CONTENT_URI)) {
            getContext().getContentResolver().notifyChange(Data.CONTENT_URI,
                    null, false);
            // } else if
            // (uri.equals(PrivateContactContract.Contacts.CONTENT_LOG_URI)) {
            // // getContext().getContentResolver().notifyChange(
            // // Contacts.CONTENT_LOG_URI, null, false);
            // } else if
            // (uri.getEncodedAuthority().equals("com.neolink.contacts")) {
            getContext().getContentResolver().notifyChange(
                    Contacts.CONTENT_URI, null, false);
        } else {
            Log.d(LOG_TAG, "do***************noticefy error" + uri);
        }
    }

    private int doUpdateActionInTransaction(Uri uri, ContentValues values,
            String selection, String[] selectionArgs) {
        int result = 0;
        SQLiteDatabase db = mPrivateContactsDatabaseHelper
                .getWritableDatabase();
        db.beginTransaction();
        try {
            result = updateInTransaction(uri, values, selection, selectionArgs);
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
            contactyChanged(uri);
        }
        return result;
    }

    private int doDeleteActionInTransaction(Uri uri, String selection,
            String[] selectionArgs) {
        int result = 0;
        SQLiteDatabase db = mPrivateContactsDatabaseHelper
                .getWritableDatabase();
        Utils.logProvider("PrivateContactsProvider doDeleteActionInTransaction uri is:"
                + uri);
        db.beginTransaction();
        try {
            result = deleteInTransaction(uri, selection, selectionArgs);
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
            if (uri.equals(PrivateContactContracts.GroupContact.CONTENT_URI)) {
                getContext().getContentResolver().notifyChange(
                        GroupContact.CONTENT_URI, null, false);
            } else {
                contactyChanged(uri);
            }
        }
        return result;
    }

    private Uri insertInTransaction(Uri uri, ContentValues values) {
        int match = URI_MATCHER.match(uri);
        Utils.logProvider("PrivateContactsProvider insertInTransaction uri is:"
                + uri + " match is:" + match);
        switch (match) {
        case PRIVATE_CONTACTS:
            return insertContact(uri, values);
        case PRIVATE_DATA:
            return insertData(uri, values);
        case PRIVATE_GROUP_CONTACT:
            return insertGroupContact(uri, values);
        case PRIVATE_CALLLOG:
            return insertCallLogData(uri, values);
        default:
            return null;
        }

    }

    private int updateInTransaction(Uri uri, ContentValues values,
            String selection, String[] selectionArgs) {
        int count = 0;
        int match = URI_MATCHER.match(uri);
        Log.d(LOG_TAG, "updateInTransaction update uri is:" + uri
                + " contentValues is:" + values + "match==" + match);
        switch (match) {
        case PRIVATE_CONTACTS:
            count = updateContact(values, selection, selectionArgs);
            return count;
        case PRIVATE_CONTACTS_ID:
            count = updateContact(ContentUris.parseId(uri), values);
            return count;
        case PRIVATE_DATA:
            count = updateData(values, selection, selectionArgs);
            return count;
        case PRIVATE_DATA_ID:
            long dataId = ContentUris.parseId(uri);
            count = updateData(dataId, values, selection, selectionArgs);
            return count;
        case PRIVATE_CALLLOG:
            count = updateDataCallLog(values, selection, selectionArgs);
            return count;
        case PRIVATE_CALLLOG_ID:
            count = updateDataCallLogId(uri, values, selection, selectionArgs);
            return count;
        case PRIVATE_GROUP_CONTACT:
            count = updateDataGroup(values, selection, selectionArgs);
            return count;
        default:
            break;
        }
        return -1;
    }

    private int updateData(long dataId, ContentValues values, String selection,
            String[] selectionArgs) {
        int count = 0;
        count = mDb.get().update(Tables.PRIVATE_DATA, values, selection,
                selectionArgs);
        return count;
    }

    private int updateDataCallLog(ContentValues values, String selection,
            String[] selectionArgs) {
        int count = 0;
        count = mDb.get().update(Tables.PRIVATE_CALL, values, selection,
                selectionArgs);
        return count;
    }

    private int updateDataCallLogId(Uri url, ContentValues values,
            String selection, String[] selectionArgs) {
        int count = 0;
        String selectionWithId = (PrivateContactContracts.CallLogColumns._ID
                + "=" + ContentUris.parseId(url) + " ")
                + (selection == null ? "" : " AND (" + selection + ")");
        count = mDb.get().update(Tables.PRIVATE_CALL, values, selectionWithId,
                selectionArgs);
        return count;
    }

    private int updateDataGroup(ContentValues values, String selection,
            String[] selectionArgs) {
        int count = 0;
        count = mDb.get().update(Tables.PRIVATE_GROUP_CONTACT, values,
                selection, selectionArgs);
        return count;
    }

    private int updateData(ContentValues values, String selection,
            String[] selectionArgs) {
        Utils.logProvider("PrivateContactsProvider updateData22 selection "
                + selection + "values==" + values);
        int count = 0;
        int contacts_id = 0;
        String contacts_type = "";
        Cursor cursor = mDb.get().query(
                Tables.PRIVATE_DATA,
                new String[] { DataColumns._ID, Data.CONTACT_ID,
                        Data.MIMETYPE_ID }, selection, selectionArgs, null,
                null, null);

        try {
            while (cursor.moveToNext()) {
                long dataId = cursor.getLong(0);
                contacts_id = cursor.getInt(1);
                contacts_type = cursor.getString(2);
                count += updateData(dataId, values, selection, selectionArgs);
                Utils.logProvider("PrivateContactsProvider updateData22 dataContact_id"
                        + " "
                        + "values=="
                        + values
                        + "contacts_id"
                        + contacts_id
                        + "count=="
                        + count
                        + "dataId=="
                        + dataId
                        + "contacts_type==" + contacts_type);
            }
        } finally {
            cursor.close();
        }
        // Utils.logProvider("PrivateContactsProvider updateData22 selection "+selection+"values=="+values+"dataId"+"count=="+count);

        // if ("1".equals(contacts_type) || "2".equals(contacts_type)) {
        // updateContactDisplayName(values, contacts_id);
        // }

        return count;
    }

    private int updateContact(ContentValues values, String selection,
            String[] selectionArgs) {
        Utils.logProvider("PrivateContactsProvider updateContact22 selection:"
                + selection + ",values:" + values);
        int count = 0;

        Cursor cursor = mDb.get().query(Views.PRIVATE_CONTACT,
                new String[] { ContactsColumns._ID }, selection, selectionArgs,
                null, null, null);
        try {
            while (cursor.moveToNext()) {
                long contactId = cursor.getLong(0);
                updateContact(contactId, values);
                count++;
            }
        } finally {
            cursor.close();
        }
        return count;
    }

    private int updateContact(long contactId, ContentValues values) {
        Utils.logProvider("PrivateContactProvider updateContact11 contactId :"
                + contactId + ",contentValues:" + values);
        String[] whereArgs = new String[] { String.valueOf(contactId) };
        int rslt = mDb.get().update(Tables.PRIVATE_CONTACT, values,
                ContactsColumns._ID + " = ?", whereArgs);
        return rslt;
    }

    private int deleteInTransaction(Uri uri, String selection,
            String[] selectionArgs) {
        int match = URI_MATCHER.match(uri);
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        switch (match) {
        case PRIVATE_CONTACTS:
            return mDb.get().delete(Tables.PRIVATE_CONTACT, selection,
                    selectionArgs);
        case PRIVATE_CONTACTS_ID:
            long contactId = ContentUris.parseId(uri);
            Utils.logProvider("PrivateContactsPRovider deleteInTransaction contactId :"
                    + contactId);
            setTablesAndProjectionMapForPrivateContact(qb, null);
            qb.appendWhere(ContactsColumns._ID + " =? ");
            String[] args = new String[] { String.valueOf(contactId) };
            Cursor c = qb.query(mDb.get(), null, null, args, null, null, null);
            try {
                if (c.getCount() == 1) {
                    return deleteContact(contactId);
                } else {
                    return 0;
                }
            } finally {
                c.close();
            }
        case PRIVATE_GROUP_CONTACT:
            return deleteGroupData(uri, selection, selectionArgs);
        case PRIVATE_DATA:
            return deleteData(selection, selectionArgs);

        case PRIVATE_CALLLOG:
            return deleteCalllog(uri, selection, selectionArgs);
        case PRIVATE_CALLLOG_ID:
            long callLogId = ContentUris.parseId(uri);
            Utils.logProvider("PrivateContactsPRovider deleteInTransaction Id :"
                    + callLogId);
            setTablesAndProjectionMapFroPrivateCall(qb, null);
            qb.appendWhere(CallLogColumns._ID + " =? ");
            String[] args1 = new String[] { String.valueOf(callLogId) };
            Cursor c1 = qb
                    .query(mDb.get(), null, null, args1, null, null, null);
            try {
                if (c1.getCount() == 1) {
                    return deleteCalllogId(callLogId);
                } else {
                    return 0;
                }
            } finally {
                c1.close();
            }
        case PRIVATE_DATA_ID:
            long dataId = ContentUris.parseId(uri);
            selectionArgs = new String[] { String.valueOf(dataId) };
            return deleteData(DataColumns._ID + " ?", selectionArgs);

        default:
            break;
        }
        return -1;
    }

    private int deleteGroupData(Uri uri, String where, String[] whereArgs) {
        SQLiteDatabase db = mPrivateContactsDatabaseHelper
                .getWritableDatabase();
        int count = db.delete(
                PrivateContactsDataHelper.Tables.PRIVATE_GROUP_CONTACT, where,
                whereArgs);
        return count;
    }

    private int deleteData(String selection, String[] selectionArgs) {
        // Utils.logProvider("PrivateContactsProvider deleteData selection:"+selection+" selection size:"+(selectionArgs==null?0:selectionArgs.length));
        int count = 0;
        count = mDb.get().delete(Tables.PRIVATE_DATA, selection, selectionArgs);

        return count;
    }

    private int deleteCalllogId(long id) {
        String whereContact = ContactsColumns._ID + " = " + id;
        int count = mDb.get().delete(Tables.PRIVATE_CALL, whereContact, null);
        return count;
    }

    private int deleteCalllog(Uri uri, String selection, String[] selectionArgs) {
        int count = 0;
        count = mDb.get().delete(Tables.PRIVATE_CALL, selection, selectionArgs);
        return count;
    }

    private int deleteContact(long contactId) {
        String whereContact = ContactsColumns._ID + " = " + contactId;
        String whereData = Data.CONTACT_ID + " = " + contactId;
        int count1 = mDb.get().delete(Tables.PRIVATE_CONTACT, whereContact,
                null);
        int count2 = mDb.get().delete(Tables.PRIVATE_DATA, whereData, null);
        Utils.logProvider("PrivateContactsProvider deleteContact count1  and count2 :"
                + count1 + "," + count2);
        return count2;
    }

    private Uri insertContact(Uri uri, ContentValues values) {
        checkTransactionContext();

        ContentValues mValues = new ContentValues(values);

        if (mValues.containsKey(ContactsColumns.DISPLAY_NAME)) {
            mValues.put(ContactsColumns.SEARCH_INDEX_NAME,
                    getFirstPinYin(mValues
                            .getAsString(ContactsColumns.DISPLAY_NAME)));
        }
        if (mValues.containsKey(ContactsColumns.NUMBER))
            mValues.put(ContactsColumns.SEARCH_INDEX_NUMBER,
                    mValues.getAsInteger(ContactsColumns.NUMBER));
        checkTransactionContext();
        checkWritableDb();
        long contactReturnId = mDb.get().insert(Tables.PRIVATE_CONTACT, null,
                mValues);

        Utils.logProvider("contactReturnId=="
                + contactReturnId
                + "<<<<<<<<<<<<>>>>>>>>>>>>>>>>insertmContactToDataUpdate"
                + getMimeTypeId(PrivateContactConst.DataKindMimeType.CONTACTS_NUMBER_CONTENT_ITEM_TYPE)
                + mPrivateContactsDatabaseHelper
                        .getMimeTypeId(PrivateContactConst.DataKindMimeType.CONTACTS_NUMBER_CONTENT_ITEM_TYPE));
        if (contactReturnId < 0) {
            return null;
        }
        if (values.containsKey(Contacts.DISPLAY_NAME)) {
            insertmContactToDataUpdate(
                    contactReturnId,
                    values.getAsString(Contacts.DISPLAY_NAME),
                    (int) getMimeTypeId(PrivateContactConst.DataKindMimeType.CONTACTS_NAME_CONTENT_ITEM_TYPE));
        }
        if (values.containsKey(Contacts.NUMBER)) {
            insertmContactToDataUpdate(
                    contactReturnId,
                    values.getAsString(Contacts.NUMBER),
                    (int) getMimeTypeId(PrivateContactConst.DataKindMimeType.CONTACTS_NUMBER_CONTENT_ITEM_TYPE));
        }
        mTransactionContext.get().contactInsert(contactReturnId);
        uri = ContentUris.withAppendedId(uri, contactReturnId);
        return uri;
    }

    private Uri insertGroupContact(Uri uri, ContentValues values) {
        Utils.logProvider("PrivateContactsProvider insertGroupContact uri:"
                + uri + ",values:" + values);
        checkTransactionContext();
        checkWritableDb();
        int zone_id;
        ContentValues mValues = new ContentValues(values);
        long groupReturnId = mDb.get().insert(Tables.PRIVATE_GROUP_CONTACT,
                null, mValues);
        uri = ContentUris.withAppendedId(uri, groupReturnId);
        Log.d(LOG_TAG, "insertGroupContact_groupReturnId=" + groupReturnId);
        if (groupReturnId < 0) {
            Log.d(LOG_TAG, "insertGroupContact_groupReturnId=" + groupReturnId);
        } else {
            // if (values.containsKey(GroupContact.GROUP_ZONE_NAME)) {
            // getZoneInfo(values.getAsString(GroupContact.GROUP_ZONE_NAME),values.getAsInteger(GroupContact.GROUP_ZONE_ID));
            // }else{
            // getZoneInfo("test1111",15);
            // }

            if (values.containsKey(GroupContact.GROUP_CONTACT_NAME)) {

                Log.d(LOG_TAG,
                        "insertGroupContact_"
                                + mPrivateContactsDatabaseHelper
                                        .getMimeTypeId(PrivateContactConst.DataKindMimeType.GROUP_NAME_CONTENT_ITEM_TYPE));
            }
            if (values.containsKey(GroupContact.GROUP_CONTACT_NUMBER)) {
                insertDataFromGroupUpdate(
                        groupReturnId,
                        values.getAsString(GroupContact.GROUP_CONTACT_NUMBER),
                        (int) getMimeTypeId(PrivateContactConst.DataKindMimeType.GROUP_NUMBER_CONTENT_ITEM_TYPE));
            }
        }

        return uri;
    }

    private Uri insertCallLogData(Uri uri, ContentValues values) {
        Utils.logProvider("PrivateNormalProvider call log uri:" + uri
                + ",values:" + values);
        checkTransactionContext();
        ContentValues mValues = new ContentValues(values);
        checkWritableDb();

        int normalid = 0;
        long normalid1 = mDb.get().insert(Tables.PRIVATE_CALL, null, mValues);
        if (normalid1 < 0) {
            Log.d(LOG_TAG, "normalid==" + normalid1);
        } else {
            if (values.containsKey(CallLogColumns.NUMBER)) {
                insertmCallLogToUpdateSelf(values
                        .getAsString(CallLogColumns.NUMBER));
            }
        }
        return uri;
    }

    /**
     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
     */
    public void insertmCallLogToUpdateSelf(String number) {

        mMode = Settings.Secure.getInt(getContext().getContentResolver(),
                Settings.Secure.PRIVATE_PHONE_MODE, PrivateMode.MODE_UNKNOWN);

        long modeType = 0;
        if (mMode == PrivateMode.MODE_MPT1327_ANALOG_TRUNKING) {
            modeType = (long) PrivateContactContracts.Contacts.CONTACTS_IMPORT_BY_PCTOOL_PDT;
        } else if (mMode == PrivateMode.MODE_PDT_DIGITAL_TRUNKING) {
            modeType = (long) PrivateContactContracts.Contacts.CONTACTS_IMPORT_BY_PCTOOL_MPT;
        }

        String[] selectionArgs = new String[1];
        mMode = 11;
        // selectionArgs[0] = String.valueOf(11);
        selectionArgs[0] = String.valueOf(number);
        checkReadableDB();
        Cursor c = mDb.get().rawQuery(UPDATE_CALL_LOG_FROM_CONTACTS,
                selectionArgs);
        String name = "";
        long ContactId = 0;
        Utils.logProvider("insertmCallLogToUpdateSelf getCOunt is:"
                + c.getCount());
        try {
            if (c.getCount() == 0) {
                c.close();
                return;
            }
            while (c.moveToNext()) {
                Utils.logProvider("insertmCallLogToUpdateSelf getCOunt is:"
                        + c.getCount() + " aa:" + c.getLong(0) + "bb:"
                        + c.getString(1));
                name = c.getString(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            c.close();
        }
        checkWritableDb();
        if (mContactToCallLogUpdate == null) {
            mContactToCallLogUpdate = mDb.get().compileStatement(
                    "UPDATE " + Tables.PRIVATE_CALL + " SET "
                            + CallLogColumns.CONTACTS_ID + " =? " + " , "
                            + CallLogColumns.DISPLAY_NAME + " =? " + " WHERE "
                            + CallLogColumns.NUMBER + " = ?");
        }
        mContactToCallLogUpdate.bindLong(1, ContactId);
        bindString(mContactToCallLogUpdate, 2, name);
        bindString(mContactToCallLogUpdate, 3, number);
        mContactToCallLogUpdate.execute();

    }

    private Uri insertData(Uri uri, ContentValues values) {
        ContentValues mValues = new ContentValues();
        mValues.clear();
        mValues.putAll(values);

        mMode = Settings.Secure.getInt(getContext().getContentResolver(),
                Settings.Secure.PRIVATE_PHONE_MODE, PrivateMode.MODE_UNKNOWN);

        int modeType = 0;
        if (mMode == PrivateMode.MODE_MPT1327_ANALOG_TRUNKING) {
            modeType = PrivateContactContracts.Contacts.CONTACTS_IMPORT_BY_PCTOOL_PDT;
        } else if (mMode == PrivateMode.MODE_PDT_DIGITAL_TRUNKING) {
            modeType = PrivateContactContracts.Contacts.CONTACTS_IMPORT_BY_PCTOOL_MPT;
        }

        long contactDataId = mValues.getAsLong(Data.CONTACT_ID);

        String mimeType = mValues.getAsString(MimetypesColumns.MIMETYPE);
        mValues.put(Data.MIMETYPE_ID, getMimeTypeId(mimeType));
        // mValues.put(Data.IMPORT_TYPE, modeType);
        mValues.remove(MimetypesColumns.MIMETYPE);

        long id = mDb.get().insert(Tables.PRIVATE_DATA, null, mValues);
        Utils.logProvider("PrivateContactsProvider insertData id is:" + id
                + mValues + " mimeType is:" + mimeType + " contactDataId is:"
                + contactDataId);
        if (id < 0) {
            return null;
        }
        // if (DataKindMimeType.NAME_CONTENT_ITEM_TYPE.equals(mimeType)
        // || DataKindMimeType.PHONE_CONTENT_ITEM_TYPE.equals(mimeType)) {
        // updateContactDisplayName(mValues, contactDataId);
        // }
        return ContentUris.withAppendedId(uri, id);
    }

    public long getMimeTypeId(String mimeType) {
        if (mMimeTypeCache.containsKey(mimeType))
            return mMimeTypeCache.get(mimeType);

        return lookupMimeTypeId(mimeType);
    }

    private long lookupMimeTypeId(String mimeType) {
        checkWritableDb();
        final SQLiteStatement mimeTypeQuery = mDb.get().compileStatement(
                "SELECT " + MimetypesColumns._ID + " FROM "
                        + Tables.PRIVATE_MIMETYPE + " WHERE "
                        + MimetypesColumns.MIMETYPE + " = ?");
        final SQLiteStatement mimetypeInsert = mDb.get().compileStatement(
                "INSERT INTO " + Tables.PRIVATE_MIMETYPE + "("
                        + MimetypesColumns.MIMETYPE + " ) VALUES (?)");
        try {
            return lookupAndCacheId(mimeTypeQuery, mimetypeInsert, mimeType,
                    mMimeTypeCache);
        } finally {
            mimetypeInsert.close();
            mimeTypeQuery.close();
        }
    }

    private long lookupAndCacheId(SQLiteStatement query,
            SQLiteStatement insert, String value, HashMap<String, Long> cache) {
        Utils.logProvider("PrivateContactsProvider lookupAndCacheId");
        long id = -1;
        try {
            DatabaseUtils.bindObjectToProgram(query, 1, value);
            id = query.simpleQueryForLong();
            if (id != -1) {
                return id;
            }
        } catch (SQLiteDoneException e) {
            e.printStackTrace();
            DatabaseUtils.bindObjectToProgram(insert, 1, value);
            id = insert.executeInsert();
            Utils.logProvider("PrivateContactsProvider lookupAndCacheId CatchException id is:"
                    + id);
        }
        if (id != -1) {
            cache.put(value, id);
            return id;
        } else {
            throw new IllegalStateException(
                    "Couldn't find or create internal value is:" + value);
        }
    }

    public long getZoneInfo(String zoneName, int id) {
        if (mZoneIdCache.containsKey(zoneName))
            return mZoneIdCache.get(zoneName);

        return lookupZoneId(zoneName, id);
    }

    private long lookupZoneId(String zoneName, int zoneid) {
        checkWritableDb();
        final SQLiteStatement mimeTypeQuery = mDb.get().compileStatement(
                "SELECT " + ZoneColumns._ID + " FROM " + Tables.PRIVATE_ZONE
                        + " WHERE " + ZoneColumns.ZONE_NAME + " = ?");
        final SQLiteStatement mimetypeInsert = mDb.get().compileStatement(
                "INSERT INTO " + Tables.PRIVATE_ZONE + "(" + ZoneColumns._ID
                        + " , " + ZoneColumns.ZONE_NAME + " ) VALUES (?,?)");
        try {
            return lookupZoneAndCacheId(mimeTypeQuery, mimetypeInsert,
                    zoneName, zoneid, mZoneIdCache);
        } finally {
            mimetypeInsert.close();
            mimeTypeQuery.close();
        }
    }

    private long lookupZoneAndCacheId(SQLiteStatement query,
            SQLiteStatement insert, String value, int zoneid,
            HashMap<String, Long> cache) {
        Utils.logProvider("PrivateContactsProvider lookupAndCacheId");
        long id = -1;
        try {
            DatabaseUtils.bindObjectToProgram(query, 1, value);
            id = query.simpleQueryForLong();
        } catch (SQLiteDoneException e) {
            e.printStackTrace();
            DatabaseUtils.bindObjectToProgram(insert, 1, zoneid);
            DatabaseUtils.bindObjectToProgram(insert, 2, value);
            id = insert.executeInsert();
            Utils.logProvider("PrivateContactsProvider lookupAndCacheId CatchException id is:"
                    + id);
        }
        if (id != -1) {
            cache.put(value, id);
            return id;
        } else {
            throw new IllegalStateException(
                    "Couldn't find or create internal value is:" + value);
        }
    }

    private void checkWritableDb() {
        if (mDb.get() == null) {
            mDb.set(mPrivateContactsDatabaseHelper.getWritableDatabase());
        }
    }

    private void checkReadableDB() {
        if (mDb.get() == null) {
            mDb.set(mPrivateContactsDatabaseHelper.getReadableDatabase());
        }
    }

    private void checkTransactionContext() {
        if (mTransactionContext.get() == null) {
            mTransactionContext.set(mContactTransactionContext);
        }
    }

    @Override
    public String getType(Uri uri) {
        final int match = URI_MATCHER.match(uri);
        switch (match) {
        case PRIVATE_CONTACTS:
            return Contacts.CONTENT_TYPE;
        case PRIVATE_CONTACTS_ID:
            return Contacts.CONTENT_ITEM_TYPE;
        case PRIVATE_GROUP_CONTACT:
            return GroupContact.CONTENT_TYPE;
        case PRIVATE_GROUP_CONTACT_ID:
            return GroupContact.CONTENT_ITEM_TYPE;
        }

        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {

        checkWritableDb();
        int match = URI_MATCHER.match(uri);
        Log.d(LOG_TAG, "insert...match==" + match + "values=");
        // waitForAccess(mWriteAccessLatch);
        Uri returnUri = doInsertActionInTransaction(uri, values);
        return returnUri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        Utils.logProvider("PrivateContactsProvider delete uri is:" + uri
                + "selection=" + selection + "URI_MATCHER.match(uri)"
                + URI_MATCHER.match(uri));

        if (selectionArgs != null) {
            for (int i = 0; i < selectionArgs.length; i++) {
                Utils.logProvider("selectionArgs==" + selectionArgs[i]);
            }
        }
        checkWritableDb();
        // waitForAccess(mWriteAccessLatch);
        return doDeleteActionInTransaction(uri, selection, selectionArgs);
    }

    @Override
    public void onCommit() {
        checkReadableDB();
        checkTransactionContext();
        Utils.logProvider(" onCommit ----------done");
        try {
            for (long contactId : mTransactionContext.get()
                    .getInsertContactIdList()) {
                Utils.logProvider("PrivateContactSaveService onCommit ----------contactId=="
                        + contactId);
                // updateContactDisplayName(null, contactId);
            }
        } finally {
            mTransactionContext.get().clear();
        }
    }

    public void onRollback() {
        Utils.logProvider(" onRollback ----------done");
    }

    @Override
    public void onBegin() {
        checkTransactionContext();

        Log.d(LOG_TAG, "PrivateContactsProvider onBegin");
        mTransactionContext.get().clear();
    }

    public void updateContactDisplayName(ContentValues NumbermValues,
            long contact_id) {

        Long modeType = (long) -1;
        mMode = Settings.Secure.getInt(getContext().getContentResolver(),
                Settings.Secure.PRIVATE_PHONE_MODE, PrivateMode.MODE_UNKNOWN);

        if (mMode == PrivateMode.MODE_MPT1327_ANALOG_TRUNKING) {
            modeType = (long) PrivateContactContracts.Contacts.CONTACTS_IMPORT_BY_PCTOOL_PDT;
        } else if (mMode == PrivateMode.MODE_PDT_DIGITAL_TRUNKING) {
            modeType = (long) PrivateContactContracts.Contacts.CONTACTS_IMPORT_BY_PCTOOL_MPT;
        }

        String[] selectionArgs = new String[1];
        selectionArgs[0] = String.valueOf(contact_id);
        checkReadableDB();
        Cursor c = mDb.get().rawQuery(UPDATE_CONTACTS, selectionArgs);
        String name = "";
        String phone = "";
        Utils.logProvider("updateContactDisplayName getCOunt is:"
                + c.getCount() + " contact_id is:" + contact_id + "new  "
                + NumbermValues);
        try {
            if (c.getCount() == 0) {
                c.close();
                return;
            }
            while (c.moveToNext()) {
                int mimeType = c.getInt(c
                        .getColumnIndexOrThrow(DataColumns.MIMETYPE_ID));
                Utils.logProvider("PrivateContactsProvider updateContactDisplayName mimeType is:"
                        + mimeType
                        + "=="
                        + lookupMimeTypeId(DataKindMimeType.CONTACTS_NAME_CONTENT_ITEM_TYPE));
                /*
                 * if (mimeType ==
                 * lookupMimeTypeId(DataKindMimeType.CONTACTS_NAME_CONTENT_ITEM_TYPE
                 * )) { name = c.getString(c
                 * .getColumnIndexOrThrow(PrivateContactConst
                 * .NameEditorDataKind)); } if (mimeType ==
                 * lookupMimeTypeId(DataKindMimeType
                 * .CONTACTS_NUMBER_CONTENT_ITEM_TYPE)) { phone = c .getString(c
                 * .
                 * getColumnIndexOrThrow(PrivateContactConst.NameEditorDataKind)
                 * ); }
                 */
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            c.close();
        }
        checkWritableDb();
        if (mContactDisplayNameUpdate == null) {
            mContactDisplayNameUpdate = mDb.get().compileStatement(
                    "UPDATE " + Tables.PRIVATE_CONTACT + " SET "
                            + Contacts.DISPLAY_NAME + " =? " + " , "
                            + Contacts.SORT_KEY + " =? " + " , "
                            + Contacts.SEARCH_INDEX_NAME + " =? " + " , "
                            + Contacts.SEARCH_INDEX_NUMBER + " =? " + " , "
                            + Contacts.NUMBER + " =? " + " WHERE "
                            + ContactsColumns._ID + " = ?");
        }
        Utils.logProvider("PrivateContactsProvider updateContactDisplayName1111 is:"
                + name + "--contact.id" + contact_id + phone);

        if (TextUtils.isEmpty(name)) {
            Utils.logProvider("PrivateContactsProvider updateContactDisplayName1111 is:"
                    + name + "--contact.id" + contact_id + phone);

            bindString(mContactDisplayNameUpdate, 1, phone);
            bindString(mContactDisplayNameUpdate, 2, phone);
            bindString(mContactDisplayNameUpdate, 3, phone);
            bindString(mContactDisplayNameUpdate, 4, phone);
            bindInt(mContactDisplayNameUpdate, 5, modeType);

        } else {

            bindString(mContactDisplayNameUpdate, 1, name);// display_name
            bindString(mContactDisplayNameUpdate, 2, getFullPinYin(name));// sort_ley
            bindString(mContactDisplayNameUpdate, 3, getFirstPinYin(name) + "*"
                    + getFullPinYin(name));// search_full and first_name
            bindString(mContactDisplayNameUpdate, 4, phone);// seach_number
            bindInt(mContactDisplayNameUpdate, 5, modeType);

        }
        mContactDisplayNameUpdate.bindLong(6, contact_id);
        mContactDisplayNameUpdate.execute();
    }

    /**
     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
     */
    public void insertmContactToDataUpdate(long ContactId, String values,
            int mimetype) {
        if (mContactToDataUpdate == null) {
            mDbHelper.set(mPrivateContactsDatabaseHelper);
            mContactToDataUpdate = mDbHelper
                    .get()
                    .getWritableDatabase()
                    .compileStatement(
                            "INSERT OR IGNORE INTO " + Tables.PRIVATE_DATA
                                    + "(" + DataColumns.CONTACT_ID + ","
                                    + DataColumns.MIMETYPE_ID + ","
                                    + DataColumns.DATA1 + ") VALUES (?,?,?)");
        }
        mContactToDataUpdate.bindLong(1, ContactId);
        mContactToDataUpdate.bindLong(2, mimetype);
        bindString(mContactToDataUpdate, 3, values);
        mContactToDataUpdate.executeInsert();

        // if (getMimeTypeId(DataKindMimeType.CONTACTS_NAME_CONTENT_ITEM_TYPE)==
        // mimetype
        // ||
        // getMimeTypeId(DataKindMimeType.CONTACTS_NUMBER_CONTENT_ITEM_TYPE)==
        // mimetype) {
        // updateContactDisplayName(values, ContactId);
        // }
    }

    /**
     * Inserts a record in the {@link Tables#NAME_LOOKUP} table.
     */
    public void insertDataFromGroupUpdate(long GroupId, String values,
            int mimetype) {
        if (mGroupToDataUpdate == null) {
            mDbHelper.set(mPrivateContactsDatabaseHelper);
            mGroupToDataUpdate = mDbHelper
                    .get()
                    .getWritableDatabase()
                    .compileStatement(
                            "INSERT OR IGNORE INTO " + Tables.PRIVATE_DATA
                                    + "(" + DataColumns.GROUP_ID + ","
                                    + DataColumns.MIMETYPE_ID + ","
                                    + DataColumns.DATA1 + ") VALUES (?,?,?)");
        }
        mGroupToDataUpdate.bindLong(1, GroupId);
        mGroupToDataUpdate.bindLong(2, mimetype);
        bindString(mGroupToDataUpdate, 3, values);
        mGroupToDataUpdate.executeInsert();
    }

    @Override
    public ContentProviderResult[] applyBatch(
            ArrayList<ContentProviderOperation> operations)
            throws OperationApplicationException {

        Utils.logProvider("applyBatch has changed!"
                + operations.size());
        SQLiteDatabase db = mPrivateContactsDatabaseHelper
                .getWritableDatabase();
        // waitForAccess(mWriteAccessLatch);
        db.beginTransaction();// start transaction
        // db.beginTransactionWithListener(this);
        try {
            ContentProviderResult[] results = super.applyBatch(operations);
            db.setTransactionSuccessful();// set successful
            return results;
        } finally {
            db.endTransaction();// end transaction
            Utils.logProvider("PrivateContactsProvidernotifyChange>GroupContact has changed");
            getContext().getContentResolver().notifyChange(
                    GroupContact.CONTENT_URI, null, false);
        }

    }

    private void bindString(SQLiteStatement stmt, int index, String value) {
        if (value == null) {
            stmt.bindNull(index);
        } else {
            stmt.bindString(index, value);
        }
    }

    private void bindInt(SQLiteStatement stmt, int index, Long value) {
        if (value == 0) {
            stmt.bindNull(index);
        } else {
            stmt.bindLong(index, value);
        }
    }

    public String getFirstPinYin(String source) {

        if (!Arrays.asList(Collator.getAvailableLocales()).contains(
                Locale.CHINA)) {

            return source;

        }

        ArrayList<Token> tokens = HanziToPinyin.getInstance().get(source);

        if (tokens == null || tokens.size() == 0) {

            return source;

        }

        StringBuffer result = new StringBuffer();

        for (Token token : tokens) {

            if (token.type == Token.PINYIN) {

                result.append(token.target.charAt(0));

            } else {

                result.append("");

            }

        }
        return result.toString().toLowerCase();
    }

    public String getFullPinYin(String source) {
        if (!Arrays.asList(Collator.getAvailableLocales()).contains(
                Locale.CHINA)) {
            return source;
        }
        ArrayList<Token> tokens = HanziToPinyin.getInstance().get(source);
        if (tokens == null || tokens.size() == 0) {
            return source;
        }
        StringBuffer result = new StringBuffer();
        for (Token token : tokens) {
            if (token.type == Token.PINYIN) {
                result.append(token.target);
            } else {
                result.append(token.source);
            }
        }
        return result.toString().toLowerCase();
    }

    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        return pattern.matcher(str).matches();
    }

    private String[] splitNameByWord(String name) {
        int length = name.length();
        String[] subname = new String[length];
        for (int i = 0; i < name.length(); i++) {

            subname[i] = name.charAt(i) + "";
        }
        return subname;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值