diff --git a/lib/native/mac/libjmacosxaddrbook.jnilib b/lib/native/mac/libjmacosxaddrbook.jnilib index 2a8bc4162..64a5ce4e9 100755 Binary files a/lib/native/mac/libjmacosxaddrbook.jnilib and b/lib/native/mac/libjmacosxaddrbook.jnilib differ diff --git a/src/native/addrbook/macosx/net_java_sip_communicator_plugin_addrbook_macosx_MacOSXAddrBookContactQuery.m b/src/native/addrbook/macosx/net_java_sip_communicator_plugin_addrbook_macosx_MacOSXAddrBookContactQuery.m index 2572adf72..be3ddd397 100644 --- a/src/native/addrbook/macosx/net_java_sip_communicator_plugin_addrbook_macosx_MacOSXAddrBookContactQuery.m +++ b/src/native/addrbook/macosx/net_java_sip_communicator_plugin_addrbook_macosx_MacOSXAddrBookContactQuery.m @@ -173,15 +173,24 @@ MacOSXAddrBookContactQuery_idToJObject } else if ([o isKindOfClass:[ABMultiValue class]]) { + /* + * We changed our minds after the initial implementation and decided + * that we want to display not only the values but the labels as + * well. In order to minimize the scope of the modifications, we'll + * be returning each label in the same array right after its + * corresponding value. + */ ABMultiValue *mv = (ABMultiValue *) o; NSUInteger mvCount = [mv count]; jobjectArray joArray - = (*jniEnv)->NewObjectArray(jniEnv, mvCount, objectClass, NULL); + = (*jniEnv)->NewObjectArray( + jniEnv, + mvCount * 2 /* value, label */, objectClass, NULL); jo = joArray; if (joArray) { - NSUInteger j; + NSUInteger j, j1; for (j = 0; j < mvCount; j++) { @@ -195,6 +204,19 @@ MacOSXAddrBookContactQuery_idToJObject jo = NULL; break; } + /* Because the compiler says ++j may be undefined for j. */ + j1 = j + 1; + MacOSXAddrBookContactQuery_idToJObject( + jniEnv, + [mv labelAtIndex:j], + joArray, j1, + objectClass); + if (JNI_TRUE == (*jniEnv)->ExceptionCheck(jniEnv)) + { + jo = NULL; + break; + } + j = j1; } } } diff --git a/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java b/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java index 2b9467b68..22e33a9de 100644 --- a/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java +++ b/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java @@ -173,6 +173,15 @@ public class MacOSXAddrBookContactQuery kABYahooInstantProperty }; + /** + * 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"); @@ -201,6 +210,52 @@ private static native Object[] ABRecord_valuesForProperties( long record, long[] properties); + /** + * 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 + * @return a new ContactDetail instance which represents the + * specified contactAddress + */ + private ContactDetail createContactDetail( + int property, + String contactAddress, + Object label) + { + String p, l; + + switch (property) + { + case kABEmailProperty: + p = ContactDetail.LABEL_EMAIL; + break; + case kABPhoneProperty: + p = ContactDetail.LABEL_PHONE; + break; + default: + p = null; + break; + } + + if (label == null) + l = null; + else + { + l = LABEL_PATTERN.matcher((String) label).replaceAll("").trim(); + if (l.length() < 1) + l = null; + } + + return new ContactDetail(contactAddress, new String[] { p, l }); + } + /** * Calls back to a specific PtrCallback for each ABPerson * found in the Address Book of Mac OS X which matches a specific @@ -245,14 +300,23 @@ private List getContactDetails(Object[] values) contactDetails.add( setCapabilities( - new ContactDetail(stringValue), + createContactDetail( + property, + stringValue, + null), property)); } } else if (value instanceof Object[]) { - for (Object subValue : (Object[]) value) + 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; @@ -267,7 +331,10 @@ else if (value instanceof Object[]) contactDetails.add( setCapabilities( - new ContactDetail(stringSubValue), + createContactDetail( + property, + stringSubValue, + multiValue[multiValueIndex + 1]), property)); } } @@ -366,8 +433,14 @@ private String getDisplayName(Object[] values) } else if (value instanceof Object[]) { - for (Object subValue : (Object[]) value) + 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; @@ -538,8 +611,13 @@ private boolean matches(Object[] values) } else if (value instanceof Object[]) { - for (Object subValue : (Object[]) value) + 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; diff --git a/src/net/java/sip/communicator/service/contactsource/ContactDetail.java b/src/net/java/sip/communicator/service/contactsource/ContactDetail.java index 1dcaa3865..92b47a72f 100644 --- a/src/net/java/sip/communicator/service/contactsource/ContactDetail.java +++ b/src/net/java/sip/communicator/service/contactsource/ContactDetail.java @@ -117,7 +117,11 @@ public ContactDetail(String contactAddress) * @param labels the set of labels with which the new ContactDetail * instance is to be labeled. The labels may be arbitrary and may include * any of the standard/well-known labels defined by the LABEL_XXX - * constants of the ContactDetail class. + * constants of the ContactDetail class. For the sake of + * convenience, null and duplicate values in the specified + * String[] labels will be ignored i.e. will not appear in + * the set of labels reported by the new ContactDetail instance + * later on. */ public ContactDetail(String contactAddress, String[] labels) { @@ -126,14 +130,10 @@ public ContactDetail(String contactAddress, String[] labels) // labels if (labels != null) { - System.err.println(this.contactAddress); for (String label : labels) { - if (!this.labels.contains(label)) - { + if ((label != null) && !this.labels.contains(label)) this.labels.add(label); - System.err.println("\t" + label); - } } } }