/*
* Copyright (C) 2015 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.digits.sdk.android;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import com.digits.sdk.vcard.VCardBuilder;
import com.digits.sdk.vcard.VCardConfig;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
class ContactsHelper {
private static final String[] allProjectionColumns = new String[]{
ContactsContract.Data.MIMETYPE,
ContactsContract.Contacts.LOOKUP_KEY,
Phone.TYPE, Phone.LABEL, Phone.IS_PRIMARY, Phone.NUMBER,
StructuredName.DISPLAY_NAME, StructuredName.GIVEN_NAME, StructuredName.FAMILY_NAME
};
private static final String selectionQuery = ContactsContract.Data.MIMETYPE + "=? OR " +
ContactsContract.Data.MIMETYPE + "=?";
private static final String[] selectionArgs = new String[]{
Phone.CONTENT_ITEM_TYPE,
StructuredName.CONTENT_ITEM_TYPE};
private final Context context;
ContactsHelper(Context context) {
this.context = context;
}
public Cursor getContactsCursor() {
// Get unique values from allProjectionColumns
final HashSet<String> tempSet = new HashSet<>(Arrays.asList(allProjectionColumns));
final String[] projectionColumns = tempSet.toArray(new String[tempSet.size()]);
return context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
projectionColumns, selectionQuery, selectionArgs, null);
}
public List<String> createContactList(Cursor cursor) {
if (cursor == null || cursor.getCount() == 0) {
return Collections.<String>emptyList();
}
final int mimeTypeColumnIndex = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
final int lookupKeyColumnIndex = cursor.getColumnIndex(ContactsContract.Contacts
.LOOKUP_KEY);
final Map<String, List<ContentValues>> mapContactsData = new HashMap<>();
while (cursor.moveToNext()) {
final String mimeType = cursor.getString(mimeTypeColumnIndex);
final ContentValues cv = new ContentValues();
cv.put(ContactsContract.Data.MIMETYPE, mimeType);
switch (mimeType) {
case Phone.CONTENT_ITEM_TYPE:
DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, Phone.TYPE);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Phone.LABEL);
DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, Phone.IS_PRIMARY);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Phone.NUMBER);
break;
case StructuredName.CONTENT_ITEM_TYPE:
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv,
StructuredName.DISPLAY_NAME);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv,
StructuredName.GIVEN_NAME);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv,
StructuredName.FAMILY_NAME);
break;
default:
continue;
}
// Aggregate contacts based on their lookup key.
final String lookupKey = cursor.getString(lookupKeyColumnIndex);
List<ContentValues> contactDetails = mapContactsData.get(lookupKey);
if (contactDetails == null) {
contactDetails = new ArrayList<>();
mapContactsData.put(lookupKey, contactDetails);
}
contactDetails.add(cv);
}
return processContactsMap(mapContactsData);
}
private List<String> processContactsMap(Map<String, List<ContentValues>> mapContactsData) {
final List<String> vCards = new ArrayList<>();
final Map<String, List<ContentValues>> contactMimeTypeMap = new HashMap<>();
final VCardBuilder builder = new VCardBuilder(VCardConfig.VCARD_TYPE_V30_GENERIC,
VCardConfig.DEFAULT_EXPORT_CHARSET);
for (String key : mapContactsData.keySet()) {
final List<ContentValues> contentValuesList = mapContactsData.get(key);
boolean hasPhone = false;
contactMimeTypeMap.clear();
builder.clear();
// Group by type so we can call builder.append<type> below
for (ContentValues cv : contentValuesList) {
final String mimeType = cv.getAsString(ContactsContract.Data.MIMETYPE);
if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
hasPhone = true;
}
List<ContentValues> group = contactMimeTypeMap.get(mimeType);
if (group == null) {
group = new ArrayList<>();
contactMimeTypeMap.put(mimeType, group);
}
group.add(cv);
}
// Digits users are identified by phone, so ignore contacts w/o a phone
if (!hasPhone) {
continue;
}
builder.appendNameProperties(contactMimeTypeMap.get(StructuredName.CONTENT_ITEM_TYPE))
.appendPhones(contactMimeTypeMap.get(Phone.CONTENT_ITEM_TYPE), null);
final String vcard = builder.toString();
vCards.add(vcard);
}
return vCards;
}
}