/**
  * Posts a message to the contributing sync adapters that have opted-in, notifying them that the
  * contact has just been loaded
  */
 private void postViewNotificationToSyncAdapter() {
   Context context = getContext();
   for (RawContact rawContact : mContact.getRawContacts()) {
     final long rawContactId = rawContact.getId();
     if (mNotifiedRawContactIds.contains(rawContactId)) {
       continue; // Already notified for this raw contact.
     }
     mNotifiedRawContactIds.add(rawContactId);
     final AccountType accountType = rawContact.getAccountType(context);
     final String serviceName = accountType.getViewContactNotifyServiceClassName();
     final String servicePackageName = accountType.getViewContactNotifyServicePackageName();
     if (!TextUtils.isEmpty(serviceName) && !TextUtils.isEmpty(servicePackageName)) {
       final Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
       final Intent intent = new Intent();
       intent.setClassName(servicePackageName, serviceName);
       intent.setAction(Intent.ACTION_VIEW);
       intent.setDataAndType(uri, RawContacts.CONTENT_ITEM_TYPE);
       try {
         context.startService(intent);
       } catch (Exception e) {
         Log.e(TAG, "Error sending message to source-app", e);
       }
     }
   }
 }
  /**
   * Loads groups meta-data for all groups associated with all constituent raw contacts' accounts.
   */
  private void loadGroupMetaData(Contact result) {
    StringBuilder selection = new StringBuilder();
    ArrayList<String> selectionArgs = new ArrayList<String>();
    for (RawContact rawContact : result.getRawContacts()) {
      final String accountName = rawContact.getAccountName();
      final String accountType = rawContact.getAccountTypeString();
      final String dataSet = rawContact.getDataSet();
      if (accountName != null && accountType != null) {
        if (selection.length() != 0) {
          selection.append(" OR ");
        }
        selection.append("(" + Groups.ACCOUNT_NAME + "=? AND " + Groups.ACCOUNT_TYPE + "=?");
        selectionArgs.add(accountName);
        selectionArgs.add(accountType);

        if (dataSet != null) {
          selection.append(" AND " + Groups.DATA_SET + "=?");
          selectionArgs.add(dataSet);
        } else {
          selection.append(" AND " + Groups.DATA_SET + " IS NULL");
        }
        selection.append(")");
      }
    }
    final ImmutableList.Builder<GroupMetaData> groupListBuilder =
        new ImmutableList.Builder<GroupMetaData>();
    final Cursor cursor =
        getContext()
            .getContentResolver()
            .query(
                Groups.CONTENT_URI,
                GroupQuery.COLUMNS,
                selection.toString(),
                selectionArgs.toArray(new String[0]),
                null);
    if (cursor != null) {
      try {
        while (cursor.moveToNext()) {
          final String accountName = cursor.getString(GroupQuery.ACCOUNT_NAME);
          final String accountType = cursor.getString(GroupQuery.ACCOUNT_TYPE);
          final String dataSet = cursor.getString(GroupQuery.DATA_SET);
          final long groupId = cursor.getLong(GroupQuery.ID);
          final String title = cursor.getString(GroupQuery.TITLE);
          final boolean defaultGroup =
              cursor.isNull(GroupQuery.AUTO_ADD) ? false : cursor.getInt(GroupQuery.AUTO_ADD) != 0;
          final boolean favorites =
              cursor.isNull(GroupQuery.FAVORITES)
                  ? false
                  : cursor.getInt(GroupQuery.FAVORITES) != 0;

          groupListBuilder.add(
              new GroupMetaData(
                  accountName, accountType, dataSet, groupId, title, defaultGroup, favorites));
        }
      } finally {
        cursor.close();
      }
    }
    result.setGroupMetaData(groupListBuilder.build());
  }
 /**
  * Build an {@link RawContactDelta} using the given {@link RawContact} as a starting point; the
  * "before" snapshot.
  */
 public static RawContactDelta fromBefore(RawContact before) {
   final RawContactDelta rawContactDelta = new RawContactDelta();
   rawContactDelta.mValues = ValuesDelta.fromBefore(before.getValues());
   rawContactDelta.mValues.setIdColumn(RawContacts._ID);
   for (final ContentValues values : before.getContentValues()) {
     rawContactDelta.addEntry(ValuesDelta.fromBefore(values));
   }
   return rawContactDelta;
 }
  public List<Suggestion> getSuggestions() {
    ArrayList<Suggestion> list = Lists.newArrayList();
    if (mDataCursor != null) {
      Suggestion suggestion = null;
      long currentContactId = -1;
      mDataCursor.moveToPosition(-1);
      while (mDataCursor.moveToNext()) {
        long contactId = mDataCursor.getLong(DataQuery.CONTACT_ID);
        if (contactId != currentContactId) {
          suggestion = new Suggestion();
          suggestion.contactId = contactId;
          suggestion.name = mDataCursor.getString(DataQuery.DISPLAY_NAME);
          suggestion.lookupKey = mDataCursor.getString(DataQuery.LOOKUP_KEY);
          suggestion.rawContacts = Lists.newArrayList();
          list.add(suggestion);
          currentContactId = contactId;
        }

        long rawContactId = mDataCursor.getLong(DataQuery.RAW_CONTACT_ID);
        if (!containsRawContact(suggestion, rawContactId)) {
          RawContact rawContact = new RawContact();
          rawContact.rawContactId = rawContactId;
          rawContact.accountName = mDataCursor.getString(DataQuery.ACCOUNT_NAME);
          rawContact.accountType = mDataCursor.getString(DataQuery.ACCOUNT_TYPE);
          rawContact.dataSet = mDataCursor.getString(DataQuery.DATA_SET);
          suggestion.rawContacts.add(rawContact);
        }

        String mimetype = mDataCursor.getString(DataQuery.MIMETYPE);
        if (Phone.CONTENT_ITEM_TYPE.equals(mimetype)) {
          String data = mDataCursor.getString(DataQuery.DATA1);
          int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY);
          if (!TextUtils.isEmpty(data) && (superprimary != 0 || suggestion.phoneNumber == null)) {
            suggestion.phoneNumber = data;
          }
        } else if (Email.CONTENT_ITEM_TYPE.equals(mimetype)) {
          String data = mDataCursor.getString(DataQuery.DATA1);
          int superprimary = mDataCursor.getInt(DataQuery.IS_SUPERPRIMARY);
          if (!TextUtils.isEmpty(data) && (superprimary != 0 || suggestion.emailAddress == null)) {
            suggestion.emailAddress = data;
          }
        } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimetype)) {
          String data = mDataCursor.getString(DataQuery.DATA1);
          if (!TextUtils.isEmpty(data)) {
            suggestion.nickname = data;
          }
        } else if (Photo.CONTENT_ITEM_TYPE.equals(mimetype)) {
          long dataId = mDataCursor.getLong(DataQuery.ID);
          long photoId = mDataCursor.getLong(DataQuery.PHOTO_ID);
          if (dataId == photoId && !mDataCursor.isNull(DataQuery.PHOTO)) {
            suggestion.photo = mDataCursor.getBlob(DataQuery.PHOTO);
          }
        }
      }
    }
    return list;
  }
  private Contact loadContactEntity(ContentResolver resolver, Uri contactUri) {
    Uri entityUri = Uri.withAppendedPath(contactUri, Contacts.Entity.CONTENT_DIRECTORY);
    Cursor cursor =
        resolver.query(entityUri, ContactQuery.COLUMNS, null, null, Contacts.Entity.RAW_CONTACT_ID);
    if (cursor == null) {
      Log.e(TAG, "No cursor returned in loadContactEntity");
      return Contact.forNotFound(mRequestedUri);
    }

    try {
      if (!cursor.moveToFirst()) {
        cursor.close();
        return Contact.forNotFound(mRequestedUri);
      }

      /// M: fix ALPS00328937: Create the loaded contact starting with the header data.
      Contact contact = loadContactHeaderDataEX(cursor, contactUri);

      // Fill in the raw contacts, which is wrapped in an Entity and any
      // status data.  Initially, result has empty entities and statuses.
      long currentRawContactId = -1;
      RawContact rawContact = null;
      ImmutableList.Builder<RawContact> rawContactsBuilder =
          new ImmutableList.Builder<RawContact>();
      ImmutableMap.Builder<Long, DataStatus> statusesBuilder =
          new ImmutableMap.Builder<Long, DataStatus>();
      do {
        long rawContactId = cursor.getLong(ContactQuery.RAW_CONTACT_ID);
        if (rawContactId != currentRawContactId) {
          // First time to see this raw contact id, so create a new entity, and
          // add it to the result's entities.
          currentRawContactId = rawContactId;
          rawContact = new RawContact(loadRawContactValues(cursor));
          rawContactsBuilder.add(rawContact);
        }
        if (!cursor.isNull(ContactQuery.DATA_ID)) {
          ContentValues data = loadDataValues(cursor);
          rawContact.addDataItemValues(data);

          if (!cursor.isNull(ContactQuery.PRESENCE) || !cursor.isNull(ContactQuery.STATUS)) {
            final DataStatus status = new DataStatus(cursor);
            final long dataId = cursor.getLong(ContactQuery.DATA_ID);
            statusesBuilder.put(dataId, status);
          }
        }
      } while (cursor.moveToNext());

      contact.setRawContacts(rawContactsBuilder.build());
      contact.setStatuses(statusesBuilder.build());

      return contact;
    } finally {
      cursor.close();
    }
  }
 /**
  * Iterates over all data items that represent phone numbers are tries to calculate a formatted
  * number. This function can safely be called several times as no unformatted data is overwritten
  */
 private void computeFormattedPhoneNumbers(Contact contactData) {
   final String countryIso = GeoUtil.getCurrentCountryIso(getContext());
   final ImmutableList<RawContact> rawContacts = contactData.getRawContacts();
   final int rawContactCount = rawContacts.size();
   for (int rawContactIndex = 0; rawContactIndex < rawContactCount; rawContactIndex++) {
     final RawContact rawContact = rawContacts.get(rawContactIndex);
     final List<DataItem> dataItems = rawContact.getDataItems();
     final int dataCount = dataItems.size();
     for (int dataIndex = 0; dataIndex < dataCount; dataIndex++) {
       final DataItem dataItem = dataItems.get(dataIndex);
       if (dataItem instanceof PhoneDataItem) {
         final PhoneDataItem phoneDataItem = (PhoneDataItem) dataItem;
         phoneDataItem.computeFormattedPhoneNumber(countryIso);
       }
     }
   }
 }
  private void loadThumbnailBinaryData(Contact contactData) {
    final long photoId = contactData.getPhotoId();
    if (photoId <= 0) {
      // No photo ID
      return;
    }

    for (RawContact rawContact : contactData.getRawContacts()) {
      for (DataItem dataItem : rawContact.getDataItems()) {
        if (dataItem.getId() == photoId) {
          if (!(dataItem instanceof PhotoDataItem)) {
            break;
          }

          final PhotoDataItem photo = (PhotoDataItem) dataItem;
          contactData.setThumbnailPhotoBinaryData(photo.getPhoto());
          break;
        }
      }
    }
  }
  /** Sets the "invitable" account types to {@link Contact#mInvitableAccountTypes}. */
  private void loadInvitableAccountTypes(Contact contactData) {
    final ImmutableList.Builder<AccountType> resultListBuilder =
        new ImmutableList.Builder<AccountType>();
    if (!contactData.isUserProfile()) {
      Map<AccountTypeWithDataSet, AccountType> invitables =
          AccountTypeManager.getInstance(getContext()).getUsableInvitableAccountTypes();
      if (!invitables.isEmpty()) {
        final Map<AccountTypeWithDataSet, AccountType> resultMap = Maps.newHashMap(invitables);

        // Remove the ones that already have a raw contact in the current contact
        for (RawContact rawContact : contactData.getRawContacts()) {
          final AccountTypeWithDataSet type =
              AccountTypeWithDataSet.get(
                  rawContact.getAccountTypeString(), rawContact.getDataSet());
          resultMap.remove(type);
        }

        resultListBuilder.addAll(resultMap.values());
      }
    }

    // Set to mInvitableAccountTypes
    contactData.setInvitableAccountTypes(resultListBuilder.build());
  }
  private void processOneRecord(RawContact rawContact, JSONObject item, String mimetype)
      throws JSONException {
    final ContentValues itemValues = new ContentValues();
    itemValues.put(Data.MIMETYPE, mimetype);
    itemValues.put(Data._ID, -1);

    final Iterator iterator = item.keys();
    while (iterator.hasNext()) {
      String name = (String) iterator.next();
      final Object o = item.get(name);
      if (o instanceof String) {
        itemValues.put(name, (String) o);
      } else if (o instanceof Integer) {
        itemValues.put(name, (Integer) o);
      }
    }
    rawContact.addDataItemValues(itemValues);
  }