void deleteContactFromDataBase(Contact contact, ContactList list) {
    String selection = Imps.Contacts.USERNAME + "=? AND " + Imps.Contacts.CONTACTLIST + "=?";
    long listId = getContactListAdapter(list.getAddress()).getDataBaseId();
    String username = contact.getAddress().getFullName();
    String[] selectionArgs = {username, Long.toString(listId)};

    mResolver.delete(mContactUrl, selection, selectionArgs);

    // clear the history message if the contact doesn't exist in any list
    // anymore.
    if (mAdaptee.getContact(contact.getAddress()) == null) {
      clearHistoryMessages(username);
    }
  }
  void updatePresenceContent(Contact[] contacts) {
    ArrayList<String> usernames = new ArrayList<String>();
    ArrayList<String> statusArray = new ArrayList<String>();
    ArrayList<String> customStatusArray = new ArrayList<String>();
    ArrayList<String> clientTypeArray = new ArrayList<String>();

    for (Contact c : contacts) {
      String username = c.getAddress().getFullName();
      Presence p = c.getPresence();
      int status = convertPresenceStatus(p);
      String customStatus = p.getStatusText();
      int clientType = translateClientType(p);

      usernames.add(username);
      statusArray.add(String.valueOf(status));
      customStatusArray.add(customStatus);
      clientTypeArray.add(String.valueOf(clientType));
    }

    ContentValues values = new ContentValues();
    values.put(Imps.Contacts.ACCOUNT, mAccountId);
    putStringArrayList(values, Imps.Contacts.USERNAME, usernames);
    putStringArrayList(values, Imps.Presence.PRESENCE_STATUS, statusArray);
    putStringArrayList(values, Imps.Presence.PRESENCE_CUSTOM_STATUS, customStatusArray);
    putStringArrayList(values, Imps.Presence.CONTENT_TYPE, clientTypeArray);

    mResolver.update(Imps.Presence.BULK_CONTENT_URI, values, null, null);
  }
  void updateAvatarsContent(Contact[] contacts) {
    ArrayList<ContentValues> avatars = new ArrayList<ContentValues>();
    ArrayList<String> usernames = new ArrayList<String>();

    for (Contact contact : contacts) {
      byte[] avatarData = contact.getPresence().getAvatarData();
      if (avatarData == null) {
        continue;
      }

      String username = contact.getAddress().getFullName();

      ContentValues values = new ContentValues(2);
      values.put(Imps.Avatars.CONTACT, username);
      values.put(Imps.Avatars.DATA, avatarData);
      avatars.add(values);
      usernames.add(username);
    }
    if (avatars.size() > 0) {
      // ImProvider will replace the avatar content if it already exist.
      mResolver.bulkInsert(mAvatarUrl, avatars.toArray(new ContentValues[avatars.size()]));

      // notify avatar changed
      Intent i = new Intent(ImServiceConstants.ACTION_AVATAR_CHANGED);
      i.putExtra(ImServiceConstants.EXTRA_INTENT_FROM_ADDRESS, usernames);
      i.putExtra(ImServiceConstants.EXTRA_INTENT_PROVIDER_ID, mProviderId);
      i.putExtra(ImServiceConstants.EXTRA_INTENT_ACCOUNT_ID, mAccountId);
      mContext.sendBroadcast(i);
    }
  }
 public void onSubScriptionRequest(final Contact from) {
   String username = from.getAddress().getFullName();
   String nickname = from.getName();
   queryOrInsertContact(from); // FIXME Miron
   Uri uri =
       insertOrUpdateSubscription(
           username,
           nickname,
           Imps.Contacts.SUBSCRIPTION_TYPE_FROM,
           Imps.Contacts.SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING);
   mContext
       .getStatusBarNotifier()
       .notifySubscriptionRequest(
           mProviderId, mAccountId, ContentUris.parseId(uri), username, nickname);
   final int N = mRemoteSubscriptionListeners.beginBroadcast();
   for (int i = 0; i < N; i++) {
     ISubscriptionListener listener = mRemoteSubscriptionListeners.getBroadcastItem(i);
     try {
       listener.onSubScriptionRequest(from);
     } catch (RemoteException e) {
       // The RemoteCallbackList will take care of removing the
       // dead listeners.
     }
   }
   mRemoteSubscriptionListeners.finishBroadcast();
 }
 private long insertTemporary(Contact c) {
   synchronized (mTemporaryContacts) {
     mTemporaryContacts.put(c.getAddress().getFullName(), c);
   }
   Uri uri = insertContactContent(c, FAKE_TEMPORARY_LIST_ID);
   return ContentUris.parseId(uri);
 }
  void removeBlockedContactFromDataBase(Contact contact) {
    String address = contact.getAddress().getFullName();

    Uri.Builder builder = Imps.BlockedList.CONTENT_URI.buildUpon();
    ContentUris.appendId(builder, mProviderId);
    ContentUris.appendId(builder, mAccountId);

    Uri uri = builder.build();
    mResolver.delete(uri, Imps.BlockedList.USERNAME + "=?", new String[] {address});

    int type = isTemporary(address) ? Imps.Contacts.TYPE_TEMPORARY : Imps.Contacts.TYPE_NORMAL;
    updateContactType(address, type);
  }
  private ContentValues getContactContentValues(Contact contact, long listId) {
    final String username = contact.getAddress().getFullName();
    final String nickname = contact.getName();
    int type = Imps.Contacts.TYPE_NORMAL;
    if (isTemporary(username)) {
      type = Imps.Contacts.TYPE_TEMPORARY;
    }
    if (isBlocked(username)) {
      type = Imps.Contacts.TYPE_BLOCKED;
    }

    ContentValues values = new ContentValues(4);
    values.put(Imps.Contacts.USERNAME, username);
    values.put(Imps.Contacts.NICKNAME, nickname);
    values.put(Imps.Contacts.CONTACTLIST, listId);
    values.put(Imps.Contacts.TYPE, type);
    return values;
  }
  void insertBlockedContactToDataBase(Contact contact) {
    // Remove the blocked contact if it already exists, to avoid duplicates and
    // handle the odd case where a blocked contact's nickname has changed
    removeBlockedContactFromDataBase(contact);

    Uri.Builder builder = Imps.BlockedList.CONTENT_URI.buildUpon();
    ContentUris.appendId(builder, mProviderId);
    ContentUris.appendId(builder, mAccountId);
    Uri uri = builder.build();

    String username = contact.getAddress().getFullName();
    ContentValues values = new ContentValues(2);
    values.put(Imps.BlockedList.USERNAME, username);
    values.put(Imps.BlockedList.NICKNAME, contact.getName());

    mResolver.insert(uri, values);

    mValidatedBlockedContacts.add(username);
  }
  public long queryOrInsertContact(Contact c) {
    long result;

    String username = c.getAddress().getFullName();
    String selection = Imps.Contacts.USERNAME + "=?";
    String[] selectionArgs = {username};
    String[] projection = {Imps.Contacts._ID};

    Cursor cursor = mResolver.query(mContactUrl, projection, selection, selectionArgs, null);

    if (cursor != null && cursor.moveToFirst()) {
      result = cursor.getLong(0);
    } else {
      result = insertTemporary(c);
    }

    if (cursor != null) {
      cursor.close();
    }
    return result;
  }
  void addContactListContent(ContactList list) {
    String selection =
        Imps.ContactList.NAME
            + "=? AND "
            + Imps.ContactList.PROVIDER
            + "=? AND "
            + Imps.ContactList.ACCOUNT
            + "=?";
    String[] selectionArgs = {
      list.getName(), Long.toString(mProviderId), Long.toString(mAccountId)
    };
    Cursor cursor =
        mResolver.query(
            Imps.ContactList.CONTENT_URI,
            CONTACT_LIST_ID_PROJECTION,
            selection,
            selectionArgs,
            null); // no sort order
    long listId = 0;
    Uri uri = null;
    try {
      if (cursor.moveToFirst()) {
        listId = cursor.getLong(0);
        uri = ContentUris.withAppendedId(Imps.ContactList.CONTENT_URI, listId);
        // Log.d(TAG,"Found and removing ContactList with name "+list.getName());
      }
    } finally {
      cursor.close();
    }
    if (uri != null) {
      // remove existing ContactList and Contacts of that list for replacement by the newly
      // downloaded list
      mResolver.delete(
          mContactUrl, Imps.Contacts.CONTACTLIST + "=?", new String[] {Long.toString(listId)});
      mResolver.delete(uri, selection, selectionArgs);
    }

    ContentValues contactListValues = new ContentValues(3);
    contactListValues.put(Imps.ContactList.NAME, list.getName());
    contactListValues.put(Imps.ContactList.PROVIDER, mProviderId);
    contactListValues.put(Imps.ContactList.ACCOUNT, mAccountId);

    // Log.d(TAG, "Adding ContactList name="+list.getName());
    mValidatedContactLists.add(list.getName());
    uri = mResolver.insert(Imps.ContactList.CONTENT_URI, contactListValues);
    listId = ContentUris.parseId(uri);

    synchronized (mContactLists) {
      mContactLists.put(list.getAddress(), new ContactListAdapter(list, listId));
    }

    Collection<Contact> contacts = list.getContacts();
    if (contacts == null || contacts.size() == 0) {
      return;
    }

    Iterator<Contact> iter = contacts.iterator();
    while (iter.hasNext()) {
      Contact c = iter.next();
      String address = c.getAddress().getFullName();
      if (isTemporary(address)) {
        moveTemporaryContactToList(address, listId);
        iter.remove();
      }
      mValidatedContacts.add(address);
    }

    ArrayList<String> usernames = new ArrayList<String>();
    ArrayList<String> nicknames = new ArrayList<String>();
    ArrayList<String> contactTypeArray = new ArrayList<String>();
    for (Contact c : contacts) {
      String username = c.getAddress().getFullName();
      String nickname = c.getName();
      int type = Imps.Contacts.TYPE_NORMAL;
      if (isTemporary(username)) {
        type = Imps.Contacts.TYPE_TEMPORARY;
      }
      if (isBlocked(username)) {
        type = Imps.Contacts.TYPE_BLOCKED;
      }

      usernames.add(username);
      nicknames.add(nickname);
      contactTypeArray.add(String.valueOf(type));
    }
    ContentValues values = new ContentValues(6);

    values.put(Imps.Contacts.PROVIDER, mProviderId);
    values.put(Imps.Contacts.ACCOUNT, mAccountId);
    values.put(Imps.Contacts.CONTACTLIST, listId);
    putStringArrayList(values, Imps.Contacts.USERNAME, usernames);
    putStringArrayList(values, Imps.Contacts.NICKNAME, nicknames);
    putStringArrayList(values, Imps.Contacts.TYPE, contactTypeArray);

    mResolver.insert(Imps.Contacts.BULK_CONTENT_URI, values);
  }
    public void onContactChange(final int type, final ContactList list, final Contact contact) {
      ContactListAdapter removed = null;
      String notificationText = null;

      switch (type) {
        case LIST_LOADED:
        case LIST_CREATED:
          addContactListContent(list);
          break;

        case LIST_DELETED:
          removed = removeContactListFromDataBase(list.getName());
          // handle case where a list is deleted before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a cached contact list is deleted before the actual contact list is
            // downloaded from the server, we will have to remove the list again once
            // once mAllContactsLoaded is true
            if (!mValidatedContactLists.contains(list.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }
          break;

        case LIST_CONTACT_ADDED:
          long listId = getContactListAdapter(list.getAddress()).getDataBaseId();
          String contactAddress = contact.getAddress().getFullName();
          if (isTemporary(contactAddress)) {
            moveTemporaryContactToList(contactAddress, listId);
          } else {
            insertContactContent(contact, listId);
          }
          notificationText =
              mContext.getResources().getString(R.string.add_contact_success, contact.getName());
          // handle case where a contact is added before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a contact is added to a cached contact list before the actual contact
            // list is downloaded from the server, we will have to add the contact to
            // the contact list once mAllContactsLoaded is true
            if (!mValidatedContactLists.contains(list.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }
          break;

        case LIST_CONTACT_REMOVED:
          deleteContactFromDataBase(contact, list);
          // handle case where a contact is removed before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a contact is added to a cached contact list before the actual contact
            // list is downloaded from the server, we will have to add the contact to
            // the contact list once mAllContactsLoaded is true
            if (!mValidatedContactLists.contains(list.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }

          // Clear ChatSession if any.
          String address = contact.getAddress().getFullName();
          closeChatSession(address);

          notificationText =
              mContext.getResources().getString(R.string.delete_contact_success, contact.getName());
          break;

        case LIST_RENAMED:
          updateListNameInDataBase(list);
          // handle case where a list is renamed before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a contact list name is updated before the actual contact list is
            // downloaded from the server, we will have to update the list name again
            // once mAllContactsLoaded is true
            if (!mValidatedContactLists.contains(list.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }
          break;

        case CONTACT_BLOCKED:
          insertBlockedContactToDataBase(contact);
          address = contact.getAddress().getFullName();
          updateContactType(address, Imps.Contacts.TYPE_BLOCKED);
          closeChatSession(address);
          notificationText =
              mContext.getResources().getString(R.string.block_contact_success, contact.getName());
          break;

        case CONTACT_UNBLOCKED:
          removeBlockedContactFromDataBase(contact);
          notificationText =
              mContext
                  .getResources()
                  .getString(R.string.unblock_contact_success, contact.getName());
          // handle case where a contact is unblocked before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a contact list name is updated before the actual contact list is
            // downloaded from the server, we will have to update the list name again
            // once mAllContactsLoaded is true
            if (!mValidatedBlockedContacts.contains(contact.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }
          break;

        default:
          Log.e(TAG, "Unknown list update event!");
          break;
      }

      final ContactListAdapter listAdapter;
      if (type == LIST_DELETED) {
        listAdapter = removed;
      } else {
        listAdapter = (list == null) ? null : getContactListAdapter(list.getAddress());
      }
      final int N = mRemoteContactListeners.beginBroadcast();
      for (int i = 0; i < N; i++) {
        IContactListListener listener = mRemoteContactListeners.getBroadcastItem(i);
        try {
          listener.onContactChange(type, listAdapter, contact);
        } catch (RemoteException e) {
          // The RemoteCallbackList will take care of removing the
          // dead listeners.
        }
      }
      mRemoteContactListeners.finishBroadcast();

      if (mAllContactsLoaded && notificationText != null) {
        mContext.showToast(notificationText, Toast.LENGTH_SHORT);
      }
    }