/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* 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 net.java.sip.communicator.plugin.addrbook.macosx;
import java.util.*;
import java.util.regex.*;
import net.java.sip.communicator.plugin.addrbook.*;
import net.java.sip.communicator.service.contactsource.*;
import net.java.sip.communicator.service.contactsource.ContactDetail.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* Implements ContactQuery for the Address Book of Mac OS X.
*
* @author Lyubomir Marinov
*/
public class MacOSXAddrBookContactQuery
extends AbstractAddrBookContactQuery
{
/**
* The Logger used by the MacOSXAddrBookContactQuery class
* and its instances for logging output.
*/
private static final Logger logger
= Logger.getLogger(MacOSXAddrBookContactQuery.class);
/**
* The properties of ABPerson which are to be queried by the
* MacOSXAddrBookContactQuery instances.
*/
public static final long[] ABPERSON_PROPERTIES
= new long[]
{
kABAIMInstantProperty(),
kABEmailProperty(),
kABFirstNameProperty(),
kABFirstNamePhoneticProperty(),
kABICQInstantProperty(),
kABJabberInstantProperty(),
kABLastNameProperty(),
kABLastNamePhoneticProperty(),
kABMiddleNameProperty(),
kABMiddleNamePhoneticProperty(),
kABMSNInstantProperty(),
kABNicknameProperty(),
kABPhoneProperty(),
kABYahooInstantProperty(),
kABPersonFlags(),
kABOrganizationProperty(),
kABMaidenNameProperty(),
kABBirthdayProperty(),
kABJobTitleProperty(),
kABHomePageProperty(),
kABURLsProperty(),
kABCalendarURIsProperty(),
kABAddressProperty(),
kABOtherDatesProperty(),
kABRelatedNamesProperty(),
kABDepartmentProperty(),
kABNoteProperty(),
kABTitleProperty(),
kABSuffixProperty()
};
/**
* The index of the kABAIMInstantProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABAIMInstantProperty = 0;
/**
* The index of the kABEmailProperty ABPerson property in
* {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABEmailProperty = 1;
/**
* The index of the kABFirstNameProperty ABPerson property
* in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABFirstNameProperty = 2;
/**
* The index of the kABFirstNamePhoneticProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABFirstNamePhoneticProperty = 3;
/**
* The index of the kABICQInstantProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABICQInstantProperty = 4;
/**
* The index of the kABJabberInstantProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABJabberInstantProperty = 5;
/**
* The index of the kABLastNameProperty ABPerson property
* in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABLastNameProperty = 6;
/**
* The index of the kABLastNamePhoneticProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABLastNamePhoneticProperty = 7;
/**
* The index of the kABMiddleNameProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABMiddleNameProperty = 8;
/**
* The index of the kABMiddleNamePhoneticProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABMiddleNamePhoneticProperty = 9;
/**
* The index of the kABMSNInstantProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABMSNInstantProperty = 10;
/**
* The index of the kABNicknameProperty ABPerson property
* in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABNicknameProperty = 11;
/**
* The index of the kABOrganizationProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABOrganizationProperty = 15;
/**
* The index of the kABPersonFlags ABPerson property in
* {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABPersonFlags = 14;
/**
* The index of the kABPhoneProperty ABPerson property in
* {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABPhoneProperty = 12;
/**
* The flag which indicates that an ABRecord is to be displayed as
* a company.
*/
public static final long kABShowAsCompany = 1;
/**
* The mask which extracts the kABShowAsXXX flag from the
* personFlags of an ABPerson.
*/
public static final long kABShowAsMask = 7;
/**
* The index of the kABYahooInstantProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABYahooInstantProperty = 13;
/**
* The index of the kABMaidenNameProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABMaidenNameProperty = 16;
/**
* The index of the kABBirthdayProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABBirthdayProperty = 17;
/**
* The index of the kABJobTitleProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABJobTitleProperty = 18;
/**
* The index of the kABHomePageProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABHomePageProperty = 19;
/**
* The index of the kABURLsProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABURLsProperty = 20;
/**
* The index of the kABCalendarURIsProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABCalendarURIsProperty = 21;
/**
* The index of the kABAddressProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABAddressProperty = 22;
/**
* The index of the kABOtherDatesProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABOtherDatesProperty = 23;
/**
* The index of the kABRelatedNamesProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABRelatedNamesProperty = 24;
/**
* The index of the kABDepartmentProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABDepartmentProperty = 25;
/**
* The index of the kABNoteProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABNoteProperty = 26;
/**
* The index of the kABTitleProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABTitleProperty = 27;
/**
* The index of the kABSuffixProperty ABPerson
* property in {@link #ABPERSON_PROPERTIES}.
*/
public static final int kABSuffixProperty = 28;
/**
* The regex which matches the superfluous parts of an ABMultiValue
* label.
*/
private static final Pattern LABEL_PATTERN
= Pattern.compile(
"kAB|Email|Phone|Label|(\\p{Punct}*)",
Pattern.CASE_INSENSITIVE);
static
{
System.loadLibrary("jmacosxaddrbook");
}
/**
* Initializes a new MacOSXAddrBookContactQuery which is to perform
* a specific query in the Address Book of Mac OS X on behalf of a
* specific MacOSXAddrBookContactSourceService.
*
* @param contactSource the MacOSXAddrBookContactSourceService
* which is to perform the new ContactQuery instance
* @param query the Pattern for which contactSource i.e.
* the Address Book of Mac OS X is being queried
*/
public MacOSXAddrBookContactQuery(
MacOSXAddrBookContactSourceService contactSource,
Pattern query)
{
super(contactSource, query);
}
/**
* Gets the imageData of a specific ABPerson instance.
*
* @param person the pointer to the ABPerson instance to get the
* imageData of
* @return the imageData of the specified ABPerson
* instance
*/
public static native byte[] ABPerson_imageData(long person);
/**
* Gets the values of a specific set of ABRecord properties for a
* specific ABRecord instance.
*
* @param record the pointer to the ABRecord to get the property
* values of
* @param properties the set of ABRecord properties to get the
* values of
* @return the values of the specified set of ABRecord properties
* for the specified ABRecord instance
*/
public static native Object[] ABRecord_valuesForProperties(
long record,
long[] properties);
/**
* Returns the unique id of a record.
* @param record the record which id is retrieved.
* @return the record id.
*/
public static native String ABRecord_uniqueId(long record);
/**
* Sets property for the supplied person id.
* @param id the person id
* @param property the property to use.
* @param subPropety any sub property if available.
* @param value the value to set.
* @return whether the result was successfully added.
*/
public static native boolean setProperty(
String id, long property, String subPropety, Object value);
/**
* Remove a property.
* @param id the person id.
* @param property the property.
* @return whether the result was successfully removed.
*/
public static native boolean removeProperty(String id, long property);
/**
* Removes a contact from the address book.
*
* @param id the person id.
*
* @return whether the contact was successfully removed.
*/
public static native boolean deleteContact(String id);
/**
* Creates a new address book contact.
*
* @return The identifier of the created contact. null if failed.
*/
public static native String createContact();
/**
* Gets the pointer of the given contact.
*
* @param id the person id.
*
* @return The pointer of the given contact. Null if failed.
*/
public static native long getContactPointer(String id);
/**
* Initializes a new ContactDetail instance which is to reperesent
* a specific contact address that is the value of a specific
* ABPerson property and, optionally, has a specific label.
*
* @param property the index in {@link #ABPERSON_PROPERTIES} of the
* ABPerson property to be represented by ContactDetail
* @param contactAddress the contact address to be represented by the new
* ContactDetail instance
* @param label an optional label to be added to the set of labels, if any,
* determined by property
* @param id The id of the detail.
*
* @return a new ContactDetail instance which represents the
* specified contactAddress
*/
private ContactDetail createContactDetail(
int property,
String contactAddress,
Object label,
String additionalProperty,
String id)
{
Category c;
SubCategory sc = null;
switch (property)
{
case kABEmailProperty:
c = Category.Email;
break;
case kABPhoneProperty:
c = Category.Phone;
break;
case kABAIMInstantProperty:
sc = SubCategory.AIM;
c = Category.InstantMessaging;
break;
case kABICQInstantProperty:
sc = SubCategory.ICQ;
c = Category.InstantMessaging;
break;
case kABJabberInstantProperty:
sc = SubCategory.Jabber;
c = Category.InstantMessaging;
break;
case kABMSNInstantProperty:
sc = SubCategory.Skype;
c = Category.InstantMessaging;
break;
case kABYahooInstantProperty:
sc = SubCategory.Yahoo;
c = Category.InstantMessaging;
break;
case kABMaidenNameProperty:
case kABFirstNameProperty:
sc = SubCategory.Name;
c = Category.Personal;
break;
case kABFirstNamePhoneticProperty:
sc = SubCategory.Name;
c = Category.Personal;
break;
case kABLastNameProperty:
sc = SubCategory.LastName;
c = Category.Personal;
break;
case kABLastNamePhoneticProperty:
sc = SubCategory.LastName;
c = Category.Personal;
break;
case kABMiddleNameProperty:
case kABMiddleNamePhoneticProperty:
case kABNicknameProperty:
sc = SubCategory.Nickname;
c = Category.Personal;
break;
case kABBirthdayProperty:
case kABURLsProperty:
case kABHomePageProperty:
sc = SubCategory.HomePage;
c = Category.Personal;
break;
case kABOtherDatesProperty:
case kABRelatedNamesProperty:
case kABNoteProperty:
case kABTitleProperty:
case kABSuffixProperty:
c = Category.Personal;
break;
case kABOrganizationProperty:
case kABJobTitleProperty:
sc = SubCategory.JobTitle;
c = Category.Organization;
break;
case kABDepartmentProperty:
c = Category.Organization;
sc = SubCategory.Name;
break;
case kABAddressProperty:
c = Category.Address;
break;
default:
c = null;
break;
}
if (sc == null)
{
if (label == null)
sc = null;
else
{
sc = getSubCategoryFromLabel(label);
}
}
SubCategory[] subCategories;
SubCategory additionalSubCategory = null;
if(additionalProperty != null)
additionalSubCategory = getSubCategoryFromLabel(additionalProperty);
if(additionalSubCategory != null)
subCategories = new SubCategory[]
{ sc, additionalSubCategory };
else
subCategories = new SubCategory[]{ sc };
return new MacOSXAddrBookContactDetail(
property,
contactAddress,
c,
subCategories,
additionalProperty,
id);
}
/**
* Returns the SubCategory corresponding to the given label.
*
* @param label the label to match to a SubDirectory
* @return the SubDirectory corresponding to the
* given label
*/
private SubCategory getSubCategoryFromLabel(Object label)
{
String labelString
= LABEL_PATTERN.matcher((String) label).replaceAll("").trim();
if (labelString.length() < 1)
return null;
SubCategory subCategory = null;
if (labelString.equalsIgnoreCase("home"))
subCategory = SubCategory.Home;
else if (labelString.equalsIgnoreCase("work"))
subCategory = SubCategory.Work;
else if (labelString.equalsIgnoreCase("other"))
subCategory = SubCategory.Other;
else if (labelString.equalsIgnoreCase("mobile"))
subCategory = SubCategory.Mobile;
else if (labelString.equalsIgnoreCase("homepage"))
subCategory = SubCategory.HomePage;
else if (labelString.equalsIgnoreCase("street"))
subCategory = SubCategory.Street;
else if (labelString.equalsIgnoreCase("state"))
subCategory = SubCategory.State;
else if (labelString.equalsIgnoreCase("ZIP"))
subCategory = SubCategory.PostalCode;
else if (labelString.equalsIgnoreCase("country"))
subCategory = SubCategory.Country;
else if (labelString.equalsIgnoreCase("city"))
subCategory = SubCategory.City;
else if (labelString.equalsIgnoreCase("InstantMessageUsername"))
subCategory = SubCategory.Nickname;
else if (labelString.equalsIgnoreCase("workfax"))
subCategory = SubCategory.Fax;
else if (labelString.equalsIgnoreCase("fax"))
subCategory = SubCategory.Fax;
return subCategory;
}
/**
* Calls back to a specific PtrCallback for each ABPerson
* found in the Address Book of Mac OS X which matches a specific
* String query.
*
* @param query the String for which the Address Book of Mac OS X
* is to be queried. Warning: Ignored at the time of this writing.
* @param callback the PtrCallback to be notified about the
* matching ABPersons
*/
private static native void foreachPerson(
String query,
PtrCallback callback);
/**
* Gets the contactDetails to be set on a SourceContact
* which is to represent an ABPerson specified by the values of its
* {@link #ABPERSON_PROPERTIES}.
*
* @param values the values of the ABPERSON_PROPERTIES which
* represent the ABPerson to get the contactDetails of
* @param id The id of the detail.
*
* @return the contactDetails to be set on a SourceContact
* which is to represent the ABPerson specified by values
*/
private List getContactDetails(Object[] values, String id)
{
List contactDetails = new LinkedList();
for (int i = 0; i < ABPERSON_PROPERTIES.length; i++)
{
int property = i;
Object value = values[property];
if (value instanceof String)
{
String stringValue = (String) value;
if (stringValue.length() != 0)
{
if (kABPhoneProperty == property)
stringValue
= AddrBookActivator.getPhoneNumberI18nService()
.normalize(stringValue);
contactDetails.add(
setCapabilities(
createContactDetail(
property,
stringValue,
null,
null,
id),
property));
}
}
else if (value instanceof Object[])
{
parseMultiDetails(contactDetails,
(Object[]) value,
property,
null,
id);
}
}
return contactDetails;
}
/**
* Parses the multi value data resulting it in contact details.
* @param contactDetails the result list
* @param multiValue the values to parse.
* @param property the current property being parsed.
* @param id The id of the detail.
*/
private void parseMultiDetails(
List contactDetails,
Object[] multiValue,
int property,
String label,
String id)
{
if(multiValue == null)
return;
for (int multiValueIndex = 0;
multiValueIndex < multiValue.length;
multiValueIndex += 2)
{
Object subValue = multiValue[multiValueIndex];
if (subValue instanceof String)
{
String stringSubValue = (String) subValue;
if (stringSubValue.length() != 0)
{
if (kABPhoneProperty == property)
{
stringSubValue
= AddrBookActivator.getPhoneNumberI18nService()
.normalize(stringSubValue);
}
Object l = multiValue[multiValueIndex + 1];
contactDetails.add(
setCapabilities(
createContactDetail(
property,
stringSubValue,
l,
label,
id),
property));
}
}
else if (subValue instanceof Object[])
{
String l = null;
Object lObject = multiValue[multiValueIndex + 1];
if(lObject instanceof String)
l = (String)lObject;
parseMultiDetails(contactDetails,
(Object[]) subValue,
property,
l,
id);
}
}
}
/**
* Gets the displayName to be set on a SourceContact
* which is to represent an ABPerson specified by the values of its
* {@link #ABPERSON_PROPERTIES}.
*
* @param values the values of the ABPERSON_PROPERTIES which
* represent the ABPerson to get the displayName of
* @return the displayName to be set on a SourceContact
* which is to represent the ABPerson specified by values
*/
private static String getDisplayName(Object[] values)
{
long personFlags
= (values[kABPersonFlags] instanceof Long)
? ((Long) values[kABPersonFlags]).longValue()
: 0;
String displayName;
if ((personFlags & kABShowAsMask) == kABShowAsCompany)
{
displayName
= (values[kABOrganizationProperty] instanceof String)
? (String) values[kABOrganizationProperty]
: "";
if (displayName.length() != 0)
return displayName;
}
displayName
= (values[kABNicknameProperty] instanceof String)
? (String) values[kABNicknameProperty]
: "";
if (displayName.length() != 0)
return displayName;
String firstName
= (values[kABFirstNameProperty] instanceof String)
? (String) values[kABFirstNameProperty]
: "";
if ((firstName.length() == 0)
&& (values[kABFirstNamePhoneticProperty] instanceof String))
{
firstName = (String) values[kABFirstNamePhoneticProperty];
}
String lastName
= (values[kABLastNameProperty] instanceof String)
? (String) values[kABLastNameProperty]
: "";
if ((lastName.length() == 0)
&& (values[kABLastNamePhoneticProperty] instanceof String))
lastName = (String) values[kABLastNamePhoneticProperty];
if ((lastName.length() == 0)
&& (values[kABMiddleNameProperty] instanceof String))
lastName = (String) values[kABMiddleNameProperty];
if ((lastName.length() == 0)
&& (values[kABMiddleNamePhoneticProperty] instanceof String))
lastName = (String) values[kABMiddleNamePhoneticProperty];
if (firstName.length() == 0)
displayName = lastName;
else
{
displayName
= (lastName.length() == 0)
? firstName
: (firstName + " " + lastName);
}
if (displayName.length() != 0)
return displayName;
for (int i = 0; i < ABPERSON_PROPERTIES.length; i++)
{
Object value = values[i];
if (value instanceof String)
{
String stringValue = (String) value;
if (stringValue.length() != 0)
{
displayName = stringValue;
break;
}
}
else if (value instanceof Object[])
{
Object[] multiValue = (Object[]) value;
for (int multiValueIndex = 0;
multiValueIndex < multiValue.length;
multiValueIndex += 2)
{
Object subValue = multiValue[multiValueIndex];
if (subValue instanceof String)
{
String stringSubValue = (String) subValue;
if (stringSubValue.length() != 0)
{
displayName = stringSubValue;
break;
}
}
}
}
}
return displayName;
}
/**
* Gets the organization name to be set on a SourceContact.
*
* @param values the values of the ABPERSON_PROPERTIES which
* represent the ABPerson to get the organization name of.
*
* @return The organization name to be set on a SourceContact.
*/
private static String getOrganization(Object[] values)
{
String organization = "";
long personFlags
= (values[kABPersonFlags] instanceof Long)
? ((Long) values[kABPersonFlags]).longValue()
: 0;
if ((personFlags & kABShowAsMask) != kABShowAsCompany)
{
organization = (values[kABOrganizationProperty] instanceof String)
? (String) values[kABOrganizationProperty]
: "";
}
return organization;
}
/**
* Gets the value of the kABAIMInstantProperty constant.
*
* @return the value of the kABAIMInstantProperty constant
*/
public static native long kABAIMInstantProperty();
/**
* Gets the value of the kABEmailProperty constant.
*
* @return the value of the kABEmailProperty constant
*/
public static native long kABEmailProperty();
/**
* Gets the value of the kABFirstNameProperty constant.
*
* @return the value of the kABFirstNameProperty constant
*/
public static native long kABFirstNameProperty();
/**
* Gets the value of the kABFirstNamePhoneticProperty constant.
*
* @return the value of the kABFirstNamePhoneticProperty constant
*/
public static native long kABFirstNamePhoneticProperty();
/**
* Gets the value of the kABICQInstantProperty constant.
*
* @return the value of the kABICQInstantProperty constant
*/
public static native long kABICQInstantProperty();
/**
* Gets the value of the kABJabberInstantProperty constant.
*
* @return the value of the kABJabberInstantProperty constant
*/
public static native long kABJabberInstantProperty();
/**
* Gets the value of the kABLastNameProperty constant.
*
* @return the value of the kABLastNameProperty constant
*/
public static native long kABLastNameProperty();
/**
* Gets the value of the kABLastNamePhoneticProperty constant.
*
* @return the value of the kABLastNamePhoneticProperty constant
*/
public static native long kABLastNamePhoneticProperty();
/**
* Gets the value of the kABMiddleNameProperty constant.
*
* @return the value of the kABMiddleNameProperty constant
*/
public static native long kABMiddleNameProperty();
/**
* Gets the value of the kABMiddleNamePhoneticProperty constant.
*
* @return the value of the kABMiddleNamePhoneticProperty constant
*/
public static native long kABMiddleNamePhoneticProperty();
/**
* Gets the value of the kABMSNInstantProperty constant.
*
* @return the value of the kABMSNInstantProperty constant
*/
public static native long kABMSNInstantProperty();
/**
* Gets the value of the kABNicknameProperty constant.
*
* @return the value of the kABNicknameProperty constant
*/
public static native long kABNicknameProperty();
/**
* Gets the value of the kABOrganizationProperty constant.
*
* @return the value of the kABOrganizationProperty constant
*/
public static native long kABOrganizationProperty();
/**
* Gets the value of the kABPersonFlags constant.
*
* @return the value of the kABPersonFlags constant
*/
public static native long kABPersonFlags();
/**
* Gets the value of the kABPhoneProperty constant.
*
* @return the value of the kABPhoneProperty constant
*/
public static native long kABPhoneProperty();
/**
* Gets the value of the kABYahooInstantProperty constant.
*
* @return the value of the kABYahooInstantProperty constant
*/
public static native long kABYahooInstantProperty();
/**
* Gets the value of the kABMaidenNameProperty constant.
*
* @return the value of the kABMaidenNameProperty constant
*/
public static native long kABMaidenNameProperty();
/**
* Gets the value of the kABBirthdayProperty constant.
*
* @return the value of the kABBirthdayProperty constant
*/
public static native long kABBirthdayProperty();
/**
* Gets the value of the kABJobTitleProperty constant.
*
* @return the value of the kABJobTitleProperty constant
*/
public static native long kABJobTitleProperty();
/**
* Gets the value of the kABHomePageProperty constant.
*
* @return the value of the kABHomePageProperty constant
*/
public static native long kABHomePageProperty();
/**
* Gets the value of the kABURLsProperty constant.
*
* @return the value of the kABURLsProperty constant
*/
public static native long kABURLsProperty();
/**
* Gets the value of the kABCalendarURIsProperty constant.
*
* @return the value of the kABCalendarURIsProperty constant
*/
public static native long kABCalendarURIsProperty();
/**
* Gets the value of the kABAddressProperty constant.
*
* @return the value of the kABAddressProperty constant
*/
public static native long kABAddressProperty();
/**
* Gets the value of the kABOtherDatesProperty constant.
*
* @return the value of the kABOtherDatesProperty constant
*/
public static native long kABOtherDatesProperty();
/**
* Gets the value of the kABRelatedNamesProperty constant.
*
* @return the value of the kABRelatedNamesProperty constant
*/
public static native long kABRelatedNamesProperty();
/**
* Gets the value of the kABDepartmentProperty constant.
*
* @return the value of the kABDepartmentProperty constant
*/
public static native long kABDepartmentProperty();
/**
* Gets the value of the kABInstantMessageProperty constant.
*
* @return the value of the kABInstantMessageProperty constant
*/
public static native long kABInstantMessageProperty();
/**
* Gets the value of the kABNoteProperty constant.
*
* @return the value of the kABNoteProperty constant
*/
public static native long kABNoteProperty();
/**
* Gets the value of the kABTitleProperty constant.
*
* @return the value of the kABTitleProperty constant
*/
public static native long kABTitleProperty();
/**
* Gets the value of the kABSuffixProperty constant.
*
* @return the value of the kABSuffixProperty constant
*/
public static native long kABSuffixProperty();
public static native String kABEmailWorkLabel();
public static native String kABEmailHomeLabel();
public static native String kABAddressHomeLabel();
public static native String kABAddressWorkLabel();
public static native String kABPhoneWorkLabel();
public static native String kABPhoneHomeLabel();
public static native String kABPhoneMobileLabel();
public static native String kABPhoneMainLabel();
public static native String kABPhoneWorkFAXLabel();
public static native String kABHomeLabel();
public static native String kABWorkLabel();
public static native String kABOtherLabel();
public static native String kABAddressStreetKey();
public static native String kABAddressCityKey();
public static native String kABAddressStateKey();
public static native String kABAddressZIPKey();
public static native String kABAddressCountryKey();
/**
* Determines whether a specific ABPerson property with a specific
* value matches the {@link #query} of this
* AsyncContactQuery.
*
* @param property the ABPerson property to check
* @param value the value of the property to check
* @return true if the specified value of the specified
* property matches the query of this
* AsyncContactQuery; otherwise, false
*/
private boolean matches(int property, String value)
{
return
query.matcher(value).find()
|| ((kABPhoneProperty == property) && phoneNumberMatches(value));
}
/**
* Determines whether an ABPerson represented by the values of its
* {@link #ABPERSON_PROPERTIES} matches {@link #query}.
*
* @param values the values of the ABPERSON_PROPERTIES which
* represent the ABPerson to be determined whether it matches
* query
* @return true if the ABPerson represented by the
* specified values matches query; otherwise,
* false
*/
private boolean matches(Object[] values)
{
int property = 0;
for (Object value : values)
{
if (value instanceof String)
{
if (matches(property, (String) value))
return true;
}
else if (value instanceof Object[])
{
Object[] multiValue = (Object[]) value;
for (int multiValueIndex = 0;
multiValueIndex < multiValue.length;
multiValueIndex += 2)
{
Object subValue = multiValue[multiValueIndex];
if ((subValue instanceof String)
&& matches(property, (String) subValue))
return true;
}
}
property++;
}
return false;
}
/**
* Notifies this MacOSXAddrBookContactQuery about a specific
* ABPerson.
*
* @param person a pointer to the ABPerson instance to notify about
* @return true if this MacOSXAddrBookContactQuery is to
* continue being called; otherwise, false
*/
private boolean onPerson(long person)
{
Object[] values
= ABRecord_valuesForProperties(person, ABPERSON_PROPERTIES);
final String id = ABRecord_uniqueId(person);
String displayName = getDisplayName(values);
if ((displayName.length() != 0)
&& (query.matcher(displayName).find() || matches(values)))
{
List contactDetails = getContactDetails(values, id);
if (!contactDetails.isEmpty())
{
final MacOSXAddrBookSourceContact sourceContact
= new MacOSXAddrBookSourceContact(
getContactSource(),
displayName,
contactDetails);
sourceContact.setData(SourceContact.DATA_ID, id);
sourceContact.setDisplayDetails(getOrganization(values));
try
{
byte[] image = ABPerson_imageData(person);
if (image != null)
sourceContact.setImage(image);
}
catch (OutOfMemoryError oome)
{
// Ignore it, the image is not vital.
}
addQueryResult(sourceContact);
}
}
return (getStatus() == QUERY_IN_PROGRESS);
}
/**
* Performs this AsyncContactQuery in a background Thread.
*
* @see AsyncContactQuery#run()
*/
@Override
protected void run()
{
foreachPerson(
query.toString(),
new PtrCallback()
{
@Override
public boolean callback(long person)
{
return onPerson(person);
}
});
}
/**
* Sets the capabilities of a specific ContactDetail (e.g.
* supportedOpSets) depending on the ABPerson property
* that it stands for.
*
* @param contactDetail the ContactDetail to set the capabilities
* of
* @param property the index in {@link #ABPERSON_PROPERTIES} of the
* ABPerson property represented by ContactDetail
* @return contactDetail
*/
private ContactDetail setCapabilities(
ContactDetail contactDetail,
int property)
{
List> supportedOpSets
= new LinkedList>();
Map, String> preferredProtocols
= new HashMap, String>();
// can be added as contacts
supportedOpSets.add(OperationSetPersistentPresence.class);
switch (property)
{
case kABAIMInstantProperty:
supportedOpSets.add(OperationSetBasicInstantMessaging.class);
preferredProtocols.put(
OperationSetBasicInstantMessaging.class,
ProtocolNames.AIM);
break;
case kABEmailProperty:
supportedOpSets.add(OperationSetBasicTelephony.class);
break;
case kABICQInstantProperty:
supportedOpSets.add(OperationSetBasicInstantMessaging.class);
preferredProtocols.put(
OperationSetBasicInstantMessaging.class,
ProtocolNames.ICQ);
break;
case kABJabberInstantProperty:
supportedOpSets.add(OperationSetBasicInstantMessaging.class);
preferredProtocols.put(
OperationSetBasicInstantMessaging.class,
ProtocolNames.JABBER);
supportedOpSets.add(OperationSetBasicTelephony.class);
preferredProtocols.put(
OperationSetBasicTelephony.class,
ProtocolNames.JABBER);
break;
case kABPhoneProperty:
supportedOpSets.add(OperationSetBasicTelephony.class);
break;
default:
break;
}
contactDetail.setSupportedOpSets(supportedOpSets);
if (!preferredProtocols.isEmpty())
contactDetail.setPreferredProtocols(preferredProtocols);
return contactDetail;
}
/**
* Callback method when receiving notifications for inserted items.
*/
public void inserted(long person)
{
onPerson(person);
}
/**
* Callback method when receiving notifications for updated items.
*/
public void updated(long person)
{
SourceContact sourceContact =
findSourceContactByID(ABRecord_uniqueId(person));
if(sourceContact != null
&& sourceContact instanceof MacOSXAddrBookSourceContact)
{
// let's update the the details
Object[] values
= ABRecord_valuesForProperties(person, ABPERSON_PROPERTIES);
String displayName = getDisplayName(values);
final String id = ABRecord_uniqueId(person);
MacOSXAddrBookSourceContact editableSourceContact
= (MacOSXAddrBookSourceContact)sourceContact;
editableSourceContact.setDisplayName(displayName);
editableSourceContact.setDisplayDetails(getOrganization(values));
List contactDetails = getContactDetails(values, id);
editableSourceContact.setDetails(contactDetails);
fireContactChanged(sourceContact);
}
}
/**
* Callback method when receiving notifications for deleted items.
*/
public void deleted(String id)
{
SourceContact sourceContact = findSourceContactByID(id);
if(sourceContact != null)
fireContactRemoved(sourceContact);
}
/**
* Find the property from category and subcategories.
*
* @param category
* @param subCategories
* @return
*/
public static int getProperty(
Category category,
Collection subCategories)
{
switch(category)
{
case Personal:
if(subCategories.contains(SubCategory.Name))
return kABFirstNameProperty;
else if(subCategories.contains(SubCategory.LastName))
return kABLastNameProperty;
else if(subCategories.contains(SubCategory.Nickname))
return kABNicknameProperty;
else if(subCategories.contains(SubCategory.HomePage))
return kABHomePageProperty;
break;
case Organization:
if(subCategories.contains(SubCategory.JobTitle))
return kABJobTitleProperty;
else
return kABDepartmentProperty;
case Email:
return kABEmailProperty;
case InstantMessaging:
if(subCategories.contains(SubCategory.AIM))
return kABAIMInstantProperty;
else if(subCategories.contains(SubCategory.ICQ))
return kABICQInstantProperty;
else if(subCategories.contains(SubCategory.Skype))
return kABMSNInstantProperty;
else if(subCategories.contains(SubCategory.Jabber))
return kABJabberInstantProperty;
else if(subCategories.contains(SubCategory.Yahoo))
return kABYahooInstantProperty;
break;
case Phone:
return kABPhoneProperty;
case Address:
return kABAddressProperty;
default: return -1;
}
return -1;
}
/**
* Finds the label from category and sub categories.
* @param subCategory
* @return
*/
public static String getLabel(
int property,
SubCategory subCategory,
String subProperty)
{
switch(property)
{
case kABEmailProperty:
if(subCategory == SubCategory.Home)
return kABEmailHomeLabel();
if(subCategory == SubCategory.Work)
return kABEmailWorkLabel();
break;
case kABICQInstantProperty:
case kABAIMInstantProperty:
case kABYahooInstantProperty:
case kABMSNInstantProperty:
case kABJabberInstantProperty:
return subProperty;
case kABPhoneProperty:
if(subCategory == SubCategory.Home)
return kABPhoneHomeLabel();
if(subCategory == SubCategory.Work)
return kABPhoneWorkLabel();
if(subCategory == SubCategory.Fax)
return kABPhoneWorkFAXLabel();
if(subCategory == SubCategory.Mobile)
return kABPhoneMobileLabel();
if(subCategory == SubCategory.Other)
return "other";
break;
case kABAddressProperty:
if(subCategory == SubCategory.Street)
return kABAddressStreetKey();
if(subCategory == SubCategory.City)
return kABAddressCityKey();
if(subCategory == SubCategory.State)
return kABAddressStateKey();
if(subCategory == SubCategory.Country)
return kABAddressCountryKey();
if(subCategory == SubCategory.PostalCode)
return kABAddressZIPKey();
break;
default: return null;
}
return null;
}
/**
* Adds a new empty contact, which will be filled in later.
*
* @param id The ID of the contact to add.
*/
public void addEmptyContact(String id)
{
if(id != null)
{
final MacOSXAddrBookSourceContact sourceContact
= new MacOSXAddrBookSourceContact(
getContactSource(),
null,
new LinkedList());
sourceContact.setData(SourceContact.DATA_ID, id);
addQueryResult(sourceContact);
}
}
/**
* Fires a contact changed event for the given contact.
*
* @param sourceContact The contact which has changed.
*/
public void contactChanged(SourceContact sourceContact)
{
fireContactChanged(sourceContact);
}
}