/*
* *
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* /
*/
package org.anhonesteffort.flock.sync.addressbook;
import android.accounts.Account;
import android.content.ContentValues;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.util.Log;
import ezvcard.VCard;
import ezvcard.VCardVersion;
import ezvcard.parameter.AddressType;
import ezvcard.parameter.EmailType;
import ezvcard.parameter.ImageType;
import ezvcard.parameter.ImppType;
import ezvcard.parameter.TelephoneType;
import ezvcard.property.Address;
import ezvcard.property.Birthday;
import ezvcard.property.Email;
import ezvcard.property.FormattedName;
import ezvcard.property.Impp;
import ezvcard.property.Nickname;
import ezvcard.property.Note;
import ezvcard.property.Organization;
import ezvcard.property.Photo;
import ezvcard.property.RawProperty;
import ezvcard.property.Role;
import ezvcard.property.StructuredName;
import ezvcard.property.Telephone;
import ezvcard.property.Uid;
import ezvcard.property.Url;
import org.anhonesteffort.flock.util.guava.Optional;
import org.anhonesteffort.flock.sync.InvalidLocalComponentException;
import org.anhonesteffort.flock.util.Base64;
import org.anhonesteffort.flock.webdav.carddav.CardDavConstants;
import org.anhonesteffort.flock.webdav.ComponentETagPair;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
/**
* Programmer: rhodey
*
* Much thanks to the DAVDroid project and especially
* Richard Hirner (bitfire web engineering) for leading
* the way in shoving VCard objects into Androids Contacts
* Content Provider. This would have been much more of a
* pain without a couple hints from the DAVDroid codebase.
*/
public class ContactFactory {
private static final String TAG = "org.anhonesteffort.flock.sync.addressbook.ContactFactory";
public static final String COLUMN_NAME_CONTACT_UID = ContactsContract.RawContacts.SOURCE_ID;
public static final String COLUMN_NAME_CONTACT_ETAG = ContactsContract.RawContacts.SYNC1;
public static final String PROPERTY_PHONETIC_GIVEN_NAME = "X-PHONETIC-GIVEN-NAME";
public static final String PROPERTY_PHONETIC_MIDDLE_NAME = "X-PHONETIC-MIDDLE-NAME";
public static final String PROPERTY_PHONETIC_FAMILY_NAME = "X-PHONETIC-FAMILY-NAME";
public static final EmailType EMAIL_TYPE_MOBILE = EmailType.get("X-MOBILE");
public static final String PROPERTY_SIP = "X-SIP";
public static final String PROPERTY_STARRED = "X-STARRED";
public static final String PROPERTY_EVENT_ANNIVERSARY = "X-EVENT-ANNIVERSARY";
public static final String PROPERTY_EVENT_OTHER = "X-EVENT-OTHER";
public static final String PROPERTY_EVENT_CUSTOM = "X-EVENT-CUSTOM";
public static final String PARAMETER_EVENT_CUSTOM_LABEL = "X-EVENT-CUSTOM-LABEL";
public static final String PROPERTY_INVISIBLE_CONTACT = "X-INVISIBLE-CONTACT";
public static final String PROPERTY_AGGREGATION_EXCEPTIONS = "X-AGGREGATION-EXCEPTIONS";
private static String getUid(VCard vCard) {
if (vCard.getUid() != null)
return vCard.getUid().getValue();
return null;
}
/*
TODO:
neither of the below two methods were necessary originally but are now due to legacy :[
*/
public static String propertyNameToLabel(String propertyName) {
return WordUtils.capitalize(propertyName.toLowerCase().replace("x-", "").replace("_", " "));
}
public static String labelToPropertyName(String label) {
return "X-" + label.replace(" ","_").toUpperCase();
}
public static String[] getProjectionForRawContact() {
return new String[] {
ContactsContract.RawContacts._ID,
COLUMN_NAME_CONTACT_UID,
COLUMN_NAME_CONTACT_ETAG,
ContactsContract.RawContacts.STARRED
};
}
public static ContentValues getValuesForRawContact(Cursor cursor) {
ContentValues values = new ContentValues(4);
values.put(ContactsContract.RawContacts._ID, cursor.getLong(0));
values.put(COLUMN_NAME_CONTACT_UID, cursor.getString(1));
values.put(COLUMN_NAME_CONTACT_ETAG, cursor.getString(2));
values.put(ContactsContract.RawContacts.STARRED, (cursor.getInt(3) != 0));
return values;
}
public static ContentValues getValuesForRawContact(ComponentETagPair<VCard> vCard) {
ContentValues values = new ContentValues();
Uid uid = vCard.getComponent().getUid();
if (uid != null)
values.put(COLUMN_NAME_CONTACT_UID, uid.getValue());
if (vCard.getETag().isPresent())
values.put(COLUMN_NAME_CONTACT_ETAG, vCard.getETag().get());
RawProperty starredProp = vCard.getComponent().getExtendedProperty(PROPERTY_STARRED);
if (starredProp != null) {
boolean is_starred = Integer.parseInt(starredProp.getValue()) != 0;
values.put(ContactsContract.RawContacts.STARRED, is_starred);
}
return values;
}
public static ComponentETagPair<VCard> getVCard(ContentValues rawContactValues) {
String uidText = rawContactValues.getAsString(COLUMN_NAME_CONTACT_UID);
String eTagText = rawContactValues.getAsString(COLUMN_NAME_CONTACT_ETAG);
Boolean starred = rawContactValues.getAsBoolean(ContactsContract.RawContacts.STARRED);
VCard vCard = new VCard();
vCard.setVersion(VCardVersion.V3_0);
vCard.setUid(new Uid(uidText));
if (starred != null)
vCard.setExtendedProperty(PROPERTY_STARRED, starred ? "1" : "0");
return new ComponentETagPair<VCard>(vCard, Optional.fromNullable(eTagText));
}
public static String[] getProjectionForStructuredName() {
return new String[] {
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, // 00
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, // 01
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, // 02
ContactsContract.CommonDataKinds.StructuredName.PREFIX, // 03
ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, // 04
ContactsContract.CommonDataKinds.StructuredName.SUFFIX, // 05
ContactsContract.CommonDataKinds.StructuredName.PHONETIC_GIVEN_NAME, // 06
ContactsContract.CommonDataKinds.StructuredName.PHONETIC_MIDDLE_NAME, // 07
ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME // 08
};
}
public static ContentValues getValuesForStructuredName(Cursor cursor) {
ContentValues values = new ContentValues(9);
values.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, cursor.getString(0));
values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, cursor.getString(1));
values.put(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, cursor.getString(2));
values.put(ContactsContract.CommonDataKinds.StructuredName.PREFIX, cursor.getString(3));
values.put(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, cursor.getString(4));
values.put(ContactsContract.CommonDataKinds.StructuredName.SUFFIX, cursor.getString(5));
values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_GIVEN_NAME, cursor.getString(6));
values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_MIDDLE_NAME, cursor.getString(7));
values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME, cursor.getString(8));
return values;
}
public static Optional<ContentValues> getValuesForStructuredName(VCard vCard) {
FormattedName formattedName = vCard.getFormattedName();
StructuredName structuredName = vCard.getStructuredName();
if (formattedName == null && structuredName == null)
return Optional.absent();
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
if (formattedName != null) {
values.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
formattedName.getValue());
}
if (structuredName != null) {
values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
structuredName.getGiven());
values.put(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
structuredName.getFamily());
if (structuredName.getPrefixes().size() > 0) {
values.put(ContactsContract.CommonDataKinds.StructuredName.PREFIX,
StringUtils.join(structuredName.getPrefixes(), " "));
}
if (structuredName.getAdditional().size() > 0)
values.put(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME,
StringUtils.join(structuredName.getAdditional(), " "));
if (structuredName.getSuffixes().size() > 0)
values.put(ContactsContract.CommonDataKinds.StructuredName.SUFFIX,
StringUtils.join(structuredName.getSuffixes(), " "));
}
RawProperty phoneticGivenName = vCard.getExtendedProperty(PROPERTY_PHONETIC_GIVEN_NAME);
if (phoneticGivenName != null)
values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_GIVEN_NAME,
phoneticGivenName.getValue());
RawProperty phoneticMiddleName = vCard.getExtendedProperty(PROPERTY_PHONETIC_MIDDLE_NAME);
if (phoneticMiddleName != null)
values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_MIDDLE_NAME,
phoneticMiddleName.getValue());
RawProperty phoneticFamilyName = vCard.getExtendedProperty(PROPERTY_PHONETIC_FAMILY_NAME);
if (phoneticFamilyName != null)
values.put(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME,
phoneticFamilyName.getValue());
return Optional.of(values);
}
public static void addStructuredName(VCard vCard, ContentValues structuredNameValues) {
String displayName = structuredNameValues.getAsString(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
String givenName = structuredNameValues.getAsString(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
String familyName = structuredNameValues.getAsString(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
String prefixes = structuredNameValues.getAsString(ContactsContract.CommonDataKinds.StructuredName.PREFIX);
String middleName = structuredNameValues.getAsString(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME);
String suffixes = structuredNameValues.getAsString(ContactsContract.CommonDataKinds.StructuredName.SUFFIX);
String phoneticGivenName = structuredNameValues.getAsString(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_GIVEN_NAME);
String phoneticMiddleName = structuredNameValues.getAsString(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_MIDDLE_NAME);
String phoneticFamilyName = structuredNameValues.getAsString(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME);
if (displayName == null) {
Log.w(TAG, "display name missing, nothing to add");
return;
}
FormattedName formattedName = new FormattedName(displayName);
StructuredName structuredName = new StructuredName();
vCard.addFormattedName(formattedName);
if (givenName != null)
structuredName.setGiven(givenName);
if (familyName != null)
structuredName.setFamily(familyName);
if (prefixes != null) {
for (String prefix : StringUtils.split(prefixes))
structuredName.addPrefix(prefix);
}
if (middleName != null)
structuredName.addAdditional(middleName);
if (suffixes != null) {
for (String suffix : StringUtils.split(suffixes))
structuredName.addSuffix(suffix);
}
vCard.setStructuredName(structuredName);
if (phoneticGivenName != null)
vCard.setExtendedProperty(PROPERTY_PHONETIC_GIVEN_NAME, phoneticGivenName);
if (phoneticMiddleName != null)
vCard.setExtendedProperty(PROPERTY_PHONETIC_MIDDLE_NAME, phoneticMiddleName);
if (phoneticFamilyName != null)
vCard.setExtendedProperty(PROPERTY_PHONETIC_FAMILY_NAME, phoneticFamilyName);
}
public static String[] getProjectionForPhoneNumber() {
return new String[] {
ContactsContract.CommonDataKinds.Phone.TYPE, // 00
ContactsContract.CommonDataKinds.Phone.LABEL, // 01
ContactsContract.CommonDataKinds.Phone.NUMBER, // 02
ContactsContract.CommonDataKinds.Phone.IS_PRIMARY, // 03
ContactsContract.CommonDataKinds.Phone.IS_SUPER_PRIMARY // 04
};
}
public static ContentValues getValuesForPhoneNumber(Cursor cursor) {
ContentValues values = new ContentValues(5);
values.put(ContactsContract.CommonDataKinds.Phone.TYPE, cursor.getInt(0));
values.put(ContactsContract.CommonDataKinds.Phone.LABEL, cursor.getString(1));
values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, cursor.getString(2));
values.put(ContactsContract.CommonDataKinds.Phone.IS_PRIMARY, (cursor.getInt(3) != 0));
values.put(ContactsContract.CommonDataKinds.Phone.IS_SUPER_PRIMARY, (cursor.getInt(4) != 0));
return values;
}
public static List<ContentValues> getValuesForPhoneNumbers(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
List<Telephone> telephones = vCard.getTelephoneNumbers();
for (Telephone telephone : telephones) {
ContentValues values = new ContentValues();
int phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_OTHER;
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
if (telephone.getTypes().contains(TelephoneType.FAX)) {
if (telephone.getTypes().contains(TelephoneType.HOME))
phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME;
else if (telephone.getTypes().contains(TelephoneType.WORK))
phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK;
else
phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_OTHER_FAX;
}
else if (telephone.getTypes().contains(TelephoneType.CELL))
phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE;
else if (telephone.getTypes().contains(TelephoneType.PAGER))
phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_PAGER;
else if (telephone.getTypes().contains(TelephoneType.WORK))
phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_WORK;
else if (telephone.getTypes().contains(TelephoneType.HOME))
phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_HOME;
else if (telephone.getTypes().contains(TelephoneType.PREF))
phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_MAIN;
else if (!telephone.getTypes().isEmpty()) {
phone_type = ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM;
values.put(ContactsContract.CommonDataKinds.Phone.LABEL,
propertyNameToLabel(telephone.getTypes().iterator().next().getValue()));
}
values.put(ContactsContract.CommonDataKinds.Phone.TYPE, phone_type);
values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, telephone.getText());
values.put(ContactsContract.CommonDataKinds.Phone.IS_PRIMARY,
telephone.getTypes().contains(TelephoneType.PREF) ? 1 : 0);
values.put(ContactsContract.CommonDataKinds.Phone.IS_SUPER_PRIMARY,
telephone.getTypes().contains(TelephoneType.PREF) ? 1 : 0);
valuesList.add(values);
}
return valuesList;
}
public static void addPhoneNumber(VCard vCard, ContentValues phoneNumberValues) {
Integer type = phoneNumberValues.getAsInteger(ContactsContract.CommonDataKinds.Phone.TYPE);
String label = phoneNumberValues.getAsString(ContactsContract.CommonDataKinds.Phone.LABEL);
String number = phoneNumberValues.getAsString(ContactsContract.CommonDataKinds.Phone.NUMBER);
Boolean isPrimary = phoneNumberValues.getAsBoolean(ContactsContract.CommonDataKinds.Phone.IS_PRIMARY);
Boolean isSuperPrimary = phoneNumberValues.getAsBoolean(ContactsContract.CommonDataKinds.Phone.IS_SUPER_PRIMARY);
if (type == null || number == null) {
Log.w(TAG, "phone type or number is null, not adding anything");
return;
}
Telephone telephone = new Telephone(number);
switch (type) {
case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE:
telephone.addType(TelephoneType.CELL);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_WORK:
telephone.addType(TelephoneType.WORK);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_HOME:
telephone.addType(TelephoneType.HOME);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK:
telephone.addType(TelephoneType.FAX);
telephone.addType(TelephoneType.WORK);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME:
telephone.addType(TelephoneType.FAX);
telephone.addType(TelephoneType.HOME);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_PAGER:
telephone.addType(TelephoneType.PAGER);
break;
case ContactsContract.CommonDataKinds.Phone.TYPE_MAIN:
telephone.addType(TelephoneType.PREF);
break;
default:
if (label != null)
telephone.addType(TelephoneType.get(labelToPropertyName(label)));
}
if (isPrimary != null && isPrimary)
telephone.addType(TelephoneType.PREF);
else if (isSuperPrimary != null && isSuperPrimary)
telephone.addType(TelephoneType.PREF);
vCard.addTelephoneNumber(telephone);
}
public static String[] getProjectionForEmailAddress() {
return new String[] {
ContactsContract.CommonDataKinds.Email.TYPE, // 00
ContactsContract.CommonDataKinds.Email.ADDRESS, // 01
ContactsContract.CommonDataKinds.Email.LABEL, // 02
ContactsContract.CommonDataKinds.Email.IS_PRIMARY, // 03
ContactsContract.CommonDataKinds.Email.IS_SUPER_PRIMARY // 04
};
}
public static ContentValues getValuesForEmailAddress(Cursor cursor) {
ContentValues values = new ContentValues(5);
values.put(ContactsContract.CommonDataKinds.Email.TYPE, cursor.getInt(0));
values.put(ContactsContract.CommonDataKinds.Email.ADDRESS, cursor.getString(1));
values.put(ContactsContract.CommonDataKinds.Email.LABEL, cursor.getString(2));
values.put(ContactsContract.CommonDataKinds.Email.IS_PRIMARY, (cursor.getInt(3) != 0));
values.put(ContactsContract.CommonDataKinds.Email.IS_SUPER_PRIMARY, (cursor.getInt(4) != 0));
return values;
}
public static List<ContentValues> getValuesForEmailAddresses(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
List<Email> emails = vCard.getEmails();
for (Email email : emails) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
if (email.getTypes().contains(EmailType.HOME))
values.put(ContactsContract.CommonDataKinds.Email.TYPE,
ContactsContract.CommonDataKinds.Email.TYPE_HOME);
else if (email.getTypes().contains(EmailType.WORK))
values.put(ContactsContract.CommonDataKinds.Email.TYPE,
ContactsContract.CommonDataKinds.Email.TYPE_WORK);
else if (email.getTypes().contains(EMAIL_TYPE_MOBILE))
values.put(ContactsContract.CommonDataKinds.Email.TYPE,
ContactsContract.CommonDataKinds.Email.TYPE_MOBILE);
else if (!email.getTypes().isEmpty()) {
values.put(ContactsContract.CommonDataKinds.Email.TYPE,
ContactsContract.CommonDataKinds.Email.TYPE_CUSTOM);
values.put(ContactsContract.CommonDataKinds.Email.LABEL,
propertyNameToLabel(email.getTypes().iterator().next().getValue()));
}
else
values.put(ContactsContract.CommonDataKinds.Email.TYPE,
ContactsContract.CommonDataKinds.Email.TYPE_OTHER);
values.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email.getValue());
values.put(ContactsContract.CommonDataKinds.Email.IS_PRIMARY,
email.getTypes().contains(EmailType.PREF) ? 1 : 0);
values.put(ContactsContract.CommonDataKinds.Email.IS_SUPER_PRIMARY,
email.getTypes().contains(EmailType.PREF) ? 1 : 0);
valuesList.add(values);
}
return valuesList;
}
public static void addEmailAddress(VCard vCard, ContentValues emailValues) {
Integer type = emailValues.getAsInteger(ContactsContract.CommonDataKinds.Email.TYPE);
String label = emailValues.getAsString(ContactsContract.CommonDataKinds.Email.LABEL);
String address = emailValues.getAsString(ContactsContract.CommonDataKinds.Email.ADDRESS);
Boolean isPrimary = emailValues.getAsBoolean(ContactsContract.CommonDataKinds.Email.IS_PRIMARY);
Boolean isSuperPrimary = emailValues.getAsBoolean(ContactsContract.CommonDataKinds.Email.IS_SUPER_PRIMARY);
if (type == null || address == null) {
Log.w(TAG, "email type or address is null, not adding anything");
return;
}
Email email = new Email(address);
switch (type) {
case ContactsContract.CommonDataKinds.Email.TYPE_HOME:
email.addType(EmailType.HOME);
break;
case ContactsContract.CommonDataKinds.Email.TYPE_WORK:
email.addType(EmailType.WORK);
break;
case ContactsContract.CommonDataKinds.Email.TYPE_MOBILE:
email.addType(EMAIL_TYPE_MOBILE);
break;
default:
if (label != null)
email.addType(EmailType.get(label));
break;
}
if (isPrimary != null && isPrimary)
email.addType(EmailType.PREF);
else if (isSuperPrimary != null && isSuperPrimary)
email.addType(EmailType.PREF);
vCard.addEmail(email);
}
public static String[] getProjectionForPhoto() {
return new String[] {
ContactsContract.CommonDataKinds.Photo.PHOTO // 00 raw bytes of image
};
}
public static ContentValues getValuesForPhoto(Cursor cursor) {
ContentValues values = new ContentValues(1);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, cursor.getBlob(0));
return values;
}
public static Optional<Photo> getPhotoForValues(ContentValues values) {
byte[] thumbnailBytes = values.getAsByteArray(ContactsContract.CommonDataKinds.Photo.PHOTO);
if (thumbnailBytes == null || thumbnailBytes.length <= 0)
return Optional.absent();
return Optional.of(
new Photo(thumbnailBytes, ImageType.PNG)
);
}
public static Optional<ContentValues> getValuesForPhoto(VCard vCard) {
if (vCard.getPhotos().size() > 0) {
ContentValues values = new ContentValues();
values.put("skip_processing", true); // 0.o see >> com.android.providers.contacts.DataRowHandlerForPhoto
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO,
vCard.getPhotos().get(0).getData());
return Optional.of(values);
}
return Optional.absent();
}
public static Integer getSizeOfPhotoInBytes(ContentValues photoValues) {
return photoValues.getAsByteArray(ContactsContract.CommonDataKinds.Photo.PHOTO).length;
}
public static String[] getProjectionForOrganization() {
return new String[] {
ContactsContract.CommonDataKinds.Organization.COMPANY, // 00
ContactsContract.CommonDataKinds.Organization.TITLE // 01
};
}
public static ContentValues getValuesForOrganization(Cursor cursor) {
ContentValues values = new ContentValues(2);
values.put(ContactsContract.CommonDataKinds.Organization.COMPANY, cursor.getString(0));
values.put(ContactsContract.CommonDataKinds.Organization.TITLE, cursor.getString(1));
return values;
}
public static List<ContentValues> getValuesForOrganizations(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
for (int i = 0; i < vCard.getOrganizations().size(); i++) {
Organization organization = vCard.getOrganizations().get(i);
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Organization.COMPANY,
organization.getValues().get(0));
if (vCard.getRoles().size() > i)
values.put(ContactsContract.CommonDataKinds.Organization.TITLE,
vCard.getRoles().get(i).getValue());
valuesList.add(values);
}
return valuesList;
}
public static void addOrganization(VCard vCard, ContentValues organizationValues) {
String companyText = organizationValues.getAsString(ContactsContract.CommonDataKinds.Organization.COMPANY);
String roleText = organizationValues.getAsString(ContactsContract.CommonDataKinds.Organization.TITLE);
if (companyText != null) {
Organization organization = new Organization();
organization.addValue(companyText);
vCard.addOrganization(organization);
}
if (roleText != null) {
Role role = new Role(roleText);
vCard.addRole(role);
}
}
public static String[] getProjectionForInstantMessaging() {
return new String[] {
ContactsContract.CommonDataKinds.Im.TYPE, // 00
ContactsContract.CommonDataKinds.Im.DATA, // 01
ContactsContract.CommonDataKinds.Im.LABEL, // 02
ContactsContract.CommonDataKinds.Im.PROTOCOL, // 03
ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL // 04
};
}
public static ContentValues getValuesForInstantMessaging(Cursor cursor) {
ContentValues values = new ContentValues(5);
values.put(ContactsContract.CommonDataKinds.Im.TYPE, cursor.getInt(0));
values.put(ContactsContract.CommonDataKinds.Im.DATA, cursor.getString(1));
values.put(ContactsContract.CommonDataKinds.Im.LABEL, cursor.getString(2));
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL, cursor.getInt(3));
values.put(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL, cursor.getString(4));
return values;
}
public static List<ContentValues> getValuesForInstantMessaging(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
for (Impp messenger : vCard.getImpps()) {
if (messenger.getProtocol() == null || messenger.getProtocol().equalsIgnoreCase("sip"))
break;
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Im.TYPE,
ContactsContract.CommonDataKinds.Im.TYPE_OTHER);
values.put(ContactsContract.CommonDataKinds.Im.DATA, messenger.getHandle());
if (messenger.isAim())
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_AIM);
else if (messenger.isMsn())
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_MSN);
else if (messenger.isYahoo())
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_YAHOO);
else if (messenger.isSkype())
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_SKYPE);
else if (messenger.isIcq())
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_ICQ);
else if (messenger.isXmpp())
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER);
else if (messenger.getProtocol().equalsIgnoreCase("jabber"))
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER);
else if (messenger.getProtocol().equalsIgnoreCase("qq"))
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_QQ);
else if (messenger.getProtocol().equalsIgnoreCase("google-talk"))
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_GOOGLE_TALK);
else if (messenger.getProtocol().equalsIgnoreCase("netmeeting"))
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_NETMEETING);
else {
values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL,
ContactsContract.CommonDataKinds.Im.PROTOCOL_CUSTOM);
values.put(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL,
messenger.getProtocol());
}
valuesList.add(values);
}
return valuesList;
}
public static void addInstantMessaging(VCard vCard, ContentValues imValues) {
Integer protocol = imValues.getAsInteger(ContactsContract.CommonDataKinds.Im.PROTOCOL);
String customProtocol = imValues.getAsString(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL);
String handle = imValues.getAsString(ContactsContract.CommonDataKinds.Im.DATA);
if (protocol == null || handle == null) {
Log.w(TAG, "im protocol, or handle is null, not adding anything");
return;
}
Impp impp;
switch (protocol) {
case ContactsContract.CommonDataKinds.Im.PROTOCOL_AIM:
impp = Impp.aim(handle);
break;
case ContactsContract.CommonDataKinds.Im.PROTOCOL_MSN:
impp = Impp.msn(handle);
break;
case ContactsContract.CommonDataKinds.Im.PROTOCOL_YAHOO:
impp = Impp.yahoo(handle);
break;
case ContactsContract.CommonDataKinds.Im.PROTOCOL_SKYPE:
impp = Impp.skype(handle);
break;
case ContactsContract.CommonDataKinds.Im.PROTOCOL_ICQ:
impp = Impp.icq(handle);
break;
case ContactsContract.CommonDataKinds.Im.PROTOCOL_QQ:
impp = new Impp("qq", handle);
break;
case ContactsContract.CommonDataKinds.Im.PROTOCOL_GOOGLE_TALK:
impp = new Impp("google-talk", handle);
break;
case ContactsContract.CommonDataKinds.Im.PROTOCOL_NETMEETING:
impp = new Impp("netmeeting", handle);
break;
case ContactsContract.CommonDataKinds.Im.PROTOCOL_CUSTOM:
impp = new Impp(customProtocol, handle);
break;
default:
impp = Impp.xmpp(handle);
break;
}
impp.addType(ImppType.PERSONAL);
vCard.addImpp(impp);
}
public static String[] getProjectionForNickName() {
return new String[] {
ContactsContract.CommonDataKinds.Nickname.NAME // 00
};
}
public static ContentValues getValuesForNickName(Cursor cursor) {
ContentValues values = new ContentValues(1);
values.put(ContactsContract.CommonDataKinds.Nickname.NAME, cursor.getString(0));
return values;
}
public static List<ContentValues> getValuesForNickNames(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
for (Nickname nickname : vCard.getNicknames()) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Nickname.NAME,
nickname.getValues().get(0));
valuesList.add(values);
}
return valuesList;
}
public static void addNickName(VCard vCard, ContentValues nickNameValues) {
String nickNameText = nickNameValues.getAsString(ContactsContract.CommonDataKinds.Nickname.NAME);
if (nickNameText != null) {
Nickname nickname = new Nickname();
nickname.addValue(nickNameText);
vCard.addNickname(nickname);
}
}
public static String[] getProjectionForNote() {
return new String[] {
ContactsContract.CommonDataKinds.Note.NOTE // 00
};
}
public static ContentValues getValuesForNote(Cursor cursor) {
ContentValues values = new ContentValues(1);
values.put(ContactsContract.CommonDataKinds.Note.NOTE, cursor.getString(0));
return values;
}
public static List<ContentValues> getValuesForNotes(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
for (Note note : vCard.getNotes()) {
ContentValues values = new ContentValues();
String noteContents = note.getValue();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE);
try {
noteContents = new String(Base64.decode(noteContents));
} catch (IOException e) {
Log.w(TAG, "error base64 decoding note, skipping decode", e);
}
values.put(ContactsContract.CommonDataKinds.Note.NOTE, noteContents);
valuesList.add(values);
}
return valuesList;
}
public static void addNote(VCard vCard, ContentValues noteValues) {
String noteText = noteValues.getAsString(ContactsContract.CommonDataKinds.Note.NOTE);
if (noteText != null) {
Note note = new Note(Base64.encodeBytes(noteText.getBytes()));
vCard.addNote(note);
}
}
public static Integer getSizeOfNoteInBytes(ContentValues noteValues) {
return noteValues.getAsString(ContactsContract.CommonDataKinds.Note.NOTE).getBytes().length;
}
public static String[] getProjectionForPostalAddress() {
return new String[] {
ContactsContract.CommonDataKinds.StructuredPostal.TYPE, // 00
ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, // 01
ContactsContract.CommonDataKinds.StructuredPostal.LABEL, // 02
ContactsContract.CommonDataKinds.StructuredPostal.STREET, // 03
ContactsContract.CommonDataKinds.StructuredPostal.POBOX, // 04
ContactsContract.CommonDataKinds.StructuredPostal.NEIGHBORHOOD, // 05
ContactsContract.CommonDataKinds.StructuredPostal.CITY, // 06
ContactsContract.CommonDataKinds.StructuredPostal.REGION, // 07
ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, // 08
ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY // 09
};
}
public static ContentValues getValuesForPostalAddress(Cursor cursor) {
ContentValues values = new ContentValues(10);
values.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, cursor.getInt(0));
values.put(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, cursor.getString(1));
values.put(ContactsContract.CommonDataKinds.StructuredPostal.LABEL, cursor.getString(2));
values.put(ContactsContract.CommonDataKinds.StructuredPostal.STREET, cursor.getString(3));
values.put(ContactsContract.CommonDataKinds.StructuredPostal.POBOX, cursor.getString(4));
values.put(ContactsContract.CommonDataKinds.StructuredPostal.NEIGHBORHOOD, cursor.getString(5));
values.put(ContactsContract.CommonDataKinds.StructuredPostal.CITY, cursor.getString(6));
values.put(ContactsContract.CommonDataKinds.StructuredPostal.REGION, cursor.getString(7));
values.put(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, cursor.getString(8));
values.put(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, cursor.getString(9));
return values;
}
public static List<ContentValues> getValuesForPostalAddresses(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
for (ezvcard.property.Address address : vCard.getAddresses()) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
if (address.getTypes().contains(AddressType.HOME))
values.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE,
ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME);
else if (address.getTypes().contains(AddressType.WORK))
values.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE,
ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK);
else if (!address.getTypes().isEmpty()) {
values.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE,
ContactsContract.CommonDataKinds.StructuredPostal.TYPE_CUSTOM);
values.put(ContactsContract.CommonDataKinds.StructuredPostal.LABEL,
address.getTypes().iterator().next().getValue());
}
else
values.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE,
ContactsContract.CommonDataKinds.StructuredPostal.TYPE_OTHER);
if (address.getLabel() != null) {
String formattedAddress = address.getLabel();
try {
formattedAddress = new String(Base64.decode(formattedAddress));
} catch (IOException e) {
Log.w(TAG, "formatted address is not base64 encoded, skipping decode.");
}
values.put(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, formattedAddress);
values.put(ContactsContract.CommonDataKinds.StructuredPostal.STREET, address.getStreetAddress());
values.put(ContactsContract.CommonDataKinds.StructuredPostal.POBOX, address.getPoBox());
values.put(ContactsContract.CommonDataKinds.StructuredPostal.NEIGHBORHOOD, address.getExtendedAddress());
values.put(ContactsContract.CommonDataKinds.StructuredPostal.CITY, address.getLocality());
values.put(ContactsContract.CommonDataKinds.StructuredPostal.REGION, address.getRegion());
values.put(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, address.getPostalCode());
values.put(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, address.getCountry());
valuesList.add(values);
}
}
return valuesList;
}
public static void addPostalAddress(VCard vCard, ContentValues addressValues) {
Integer addressType = addressValues.getAsInteger(ContactsContract.CommonDataKinds.StructuredPostal.TYPE);
String formattedAddress = addressValues.getAsString(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS);
String label = addressValues.getAsString(ContactsContract.CommonDataKinds.StructuredPostal.LABEL);
String street = addressValues.getAsString(ContactsContract.CommonDataKinds.StructuredPostal.STREET);
String poBox = addressValues.getAsString(ContactsContract.CommonDataKinds.StructuredPostal.POBOX);
String neighborhood = addressValues.getAsString(ContactsContract.CommonDataKinds.StructuredPostal.NEIGHBORHOOD);
String city = addressValues.getAsString(ContactsContract.CommonDataKinds.StructuredPostal.CITY);
String region = addressValues.getAsString(ContactsContract.CommonDataKinds.StructuredPostal.REGION);
String postcode = addressValues.getAsString(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE);
String country = addressValues.getAsString(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY);
if (addressType == null || formattedAddress == null) {
Log.w(TAG, "address type or formatted address is null, not adding anything");
return;
}
Address address = new Address();
address.setLabel(Base64.encodeBytes(formattedAddress.getBytes()));
switch (addressType) {
case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME:
address.addType(AddressType.HOME);
break;
case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK:
address.addType(AddressType.WORK);
break;
case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_CUSTOM:
if (label != null)
address.addType(AddressType.get(label));
break;
}
if (street != null)
address.setStreetAddress(street);
if (poBox != null)
address.setPoBox(poBox);
if (neighborhood != null)
address.setExtendedAddress(neighborhood);
if (city != null)
address.setLocality(city);
if (region != null)
address.setRegion(region);
if (postcode != null)
address.setPostalCode(postcode);
if (country != null)
address.setCountry(country);
vCard.addAddress(address);
}
public static String[] getProjectionForWebsite() {
return new String[] {
ContactsContract.CommonDataKinds.Website.URL // 00
};
}
public static ContentValues getValuesForWebsite(Cursor cursor) {
ContentValues values = new ContentValues(1);
values.put(ContactsContract.CommonDataKinds.Website.URL, cursor.getString(0));
return values;
}
public static List<ContentValues> getValuesForWebsites(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
for (Url url : vCard.getUrls()) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Website.URL, url.getValue());
valuesList.add(values);
}
return valuesList;
}
public static void addWebsite(VCard vCard, ContentValues websiteValues) {
String urlText = websiteValues.getAsString(ContactsContract.CommonDataKinds.Website.URL);
if (urlText != null) {
Url url = new Url(urlText);
vCard.addUrl(url);
}
}
public static String[] getProjectionForEvent() {
return new String[] {
ContactsContract.CommonDataKinds.Event.TYPE, // 00
ContactsContract.CommonDataKinds.Event.LABEL, // 01
ContactsContract.CommonDataKinds.Event.START_DATE // 02
};
}
public static ContentValues getValuesForEvent(Cursor cursor) {
ContentValues values = new ContentValues(3);
values.put(ContactsContract.CommonDataKinds.Event.TYPE, cursor.getInt(0));
values.put(ContactsContract.CommonDataKinds.Event.LABEL, cursor.getString(1));
values.put(ContactsContract.CommonDataKinds.Event.START_DATE, cursor.getString(2));
return values;
}
public static List<ContentValues> getValuesForEvents(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
if (vCard.getBirthday() != null && vCard.getBirthday().getDate() != null) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
String formatted = formatter.format(vCard.getBirthday().getDate());
ContentValues values = new ContentValues();
/*
aCalendar birthday with "year unknown" option...
https://github.com/WhisperSystems/Flock/issues/26
*/
if (formatted.startsWith("0001-"))
formatted = "-" + formatted.substring(4);
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Event.TYPE,
ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY);
values.put(ContactsContract.CommonDataKinds.Event.START_DATE,
formatted);
valuesList.add(values);
}
if (vCard.getExtendedProperty(PROPERTY_EVENT_ANNIVERSARY) != null) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Event.TYPE,
ContactsContract.CommonDataKinds.Event.TYPE_ANNIVERSARY);
values.put(ContactsContract.CommonDataKinds.Event.START_DATE,
vCard.getExtendedProperty(PROPERTY_EVENT_ANNIVERSARY).getValue());
valuesList.add(values);
}
if (vCard.getExtendedProperty(PROPERTY_EVENT_OTHER) != null) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Event.TYPE,
ContactsContract.CommonDataKinds.Event.TYPE_OTHER);
values.put(ContactsContract.CommonDataKinds.Event.START_DATE,
vCard.getExtendedProperty(PROPERTY_EVENT_OTHER).getValue());
valuesList.add(values);
}
if (vCard.getExtendedProperty(PROPERTY_EVENT_CUSTOM) != null) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Event.TYPE,
ContactsContract.CommonDataKinds.Event.TYPE_CUSTOM);
values.put(ContactsContract.CommonDataKinds.Event.LABEL,
vCard.getExtendedProperty(PROPERTY_EVENT_CUSTOM).getParameter(PARAMETER_EVENT_CUSTOM_LABEL));
values.put(ContactsContract.CommonDataKinds.Event.START_DATE,
vCard.getExtendedProperty(PROPERTY_EVENT_CUSTOM).getValue());
valuesList.add(values);
}
return valuesList;
}
public static void addEvent(String path, VCard vCard, ContentValues eventValues)
throws InvalidLocalComponentException
{
Integer eventType = eventValues.getAsInteger(ContactsContract.CommonDataKinds.Event.TYPE);
String eventLabel = eventValues.getAsString(ContactsContract.CommonDataKinds.Event.LABEL);
String eventStartDate = eventValues.getAsString(ContactsContract.CommonDataKinds.Event.START_DATE);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
if (eventType == null || eventStartDate == null) {
Log.w(TAG, "event type or event start date is null, not adding anything");
return;
}
try {
if (eventType == ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY) {
/*
aCalendar birthday with "year unknown" option...
https://github.com/WhisperSystems/Flock/issues/26
*/
if (eventStartDate.startsWith("-"))
eventStartDate = "0001" + eventStartDate.substring(1);
Birthday birthday = new Birthday(formatter.parse(eventStartDate));
vCard.setBirthday(birthday);
}
} catch (ParseException e) {
throw new InvalidLocalComponentException("caught exception while parsing birthday",
CardDavConstants.CARDDAV_NAMESPACE, path, getUid(vCard), e);
}
if (eventType == ContactsContract.CommonDataKinds.Event.TYPE_ANNIVERSARY)
vCard.setExtendedProperty(PROPERTY_EVENT_ANNIVERSARY, eventStartDate);
else if (eventType == ContactsContract.CommonDataKinds.Event.TYPE_OTHER)
vCard.setExtendedProperty(PROPERTY_EVENT_OTHER, eventStartDate);
else if (eventType == ContactsContract.CommonDataKinds.Event.TYPE_CUSTOM)
vCard.setExtendedProperty(PROPERTY_EVENT_CUSTOM, eventStartDate)
.setParameter(PARAMETER_EVENT_CUSTOM_LABEL, eventLabel);
}
public static String[] getProjectionForSipAddress() {
return new String[] {
ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, // 00
ContactsContract.CommonDataKinds.SipAddress.TYPE, // 01
ContactsContract.CommonDataKinds.SipAddress.LABEL // 02
};
}
public static ContentValues getValuesForSipAddress(Cursor cursor) {
ContentValues values = new ContentValues(3);
values.put(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, cursor.getString(0));
values.put(ContactsContract.CommonDataKinds.SipAddress.TYPE, cursor.getInt(1));
values.put(ContactsContract.CommonDataKinds.SipAddress.LABEL, cursor.getString(2));
return values;
}
public static List<ContentValues> getValuesForSipAddresses(VCard vCard) {
List<ContentValues> valuesList = new LinkedList<ContentValues>();
for (RawProperty sipAddress : vCard.getExtendedProperties(PROPERTY_SIP)) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS,
sipAddress.getValue());
values.put(ContactsContract.CommonDataKinds.SipAddress.TYPE,
ContactsContract.CommonDataKinds.SipAddress.TYPE_OTHER);
valuesList.add(values);
}
return valuesList;
}
public static void addSipAddress(VCard vCard, ContentValues sipAddressValues) {
String sipAddress = sipAddressValues.getAsString(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
if (sipAddress != null)
vCard.setExtendedProperty(PROPERTY_SIP, sipAddress);
}
public static String[] getProjectionForGroupMembership() {
return new String[] {
ContactsContract.Data.DATA1, // 00
};
}
public static Long getIdForGroupMembership(Cursor cursor) {
return cursor.getLong(0);
}
public static void addInvisibleProperty(VCard vCard) {
Log.d(TAG, "addInvisibleProperty()");
vCard.setExtendedProperty(PROPERTY_INVISIBLE_CONTACT, "true");
}
public static boolean hasInvisibleProperty(VCard vCard) {
return vCard.getExtendedProperty(PROPERTY_INVISIBLE_CONTACT) != null;
}
public static List<AggregationException> getAggregationExceptions(VCard vCard)
throws IllegalArgumentException
{
List<AggregationException> exceptions = new LinkedList<AggregationException>();
RawProperty exceptionsProp = vCard.getExtendedProperty(PROPERTY_AGGREGATION_EXCEPTIONS);
if (exceptionsProp != null && exceptionsProp.getValue() != null) {
String[] exceptionStrings = exceptionsProp.getValue().split(",");
for (String exceptionString : exceptionStrings)
exceptions.add(AggregationException.build(exceptionString));
}
return exceptions;
}
public static void addAggregationExceptions(VCard vCard, List<AggregationException> exceptions) {
if (exceptions.isEmpty())
return;
Log.d(TAG, "need to add " + exceptions.size() + " aggregate exceptions.");
String exceptionsString = null;
for (AggregationException exception : exceptions) {
if (exceptionsString != null)
exceptionsString += "," + exception.toString();
else
exceptionsString = exception.toString();
}
vCard.setExtendedProperty(PROPERTY_AGGREGATION_EXCEPTIONS, exceptionsString);
}
public static class AggregationException {
private int type;
private Account contactAccount;
private String contactUid;
public AggregationException(int type, Account contactAccount, String contactUid) {
this.type = type;
this.contactAccount = contactAccount;
this.contactUid = contactUid;
}
public static AggregationException build(String stringEncodedAggregateException)
throws IllegalArgumentException
{
String[] parts = stringEncodedAggregateException.split(":");
if (parts.length < 4)
throw new IllegalArgumentException("invalid encoding for aggregate exception.");
try {
return new AggregationException(
Integer.parseInt(parts[0]),
new Account(
new String(Base64.decode(parts[1])),
new String(Base64.decode(parts[2]))
),
new String(Base64.decode(parts[3])
));
} catch (IOException e) {
throw new IllegalArgumentException("invalid encoding for aggregate exception.");
} catch (NumberFormatException e) {
throw new IllegalArgumentException("invalid encoding for aggregate exception.");
}
}
public int getType() {
return type;
}
public Account getContactAccount() {
return contactAccount;
}
public String getContactUid() {
return contactUid;
}
@Override
public String toString() {
return type + ":" + Base64.encodeBytes(contactAccount.name.getBytes()) +
":" + Base64.encodeBytes(contactAccount.type.getBytes()) +
":" + Base64.encodeBytes(contactUid.getBytes());
}
}
}