aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/plugin/thunderbird
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/sip/communicator/plugin/thunderbird')
-rw-r--r--src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdActivator.java336
-rw-r--r--src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdContactQuery.java530
2 files changed, 433 insertions, 433 deletions
diff --git a/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdActivator.java b/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdActivator.java
index 2a1bbe3..00c204e 100644
--- a/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdActivator.java
+++ b/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdActivator.java
@@ -1,4 +1,4 @@
-/*
+/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
@@ -15,170 +15,170 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package net.java.sip.communicator.plugin.thunderbird;
-
-import java.util.*;
-
-import net.java.sip.communicator.service.contactsource.*;
-import net.java.sip.communicator.service.gui.*;
-import net.java.sip.communicator.service.protocol.*;
-import net.java.sip.communicator.util.*;
-
-import org.jitsi.service.configuration.*;
-import org.jitsi.service.resources.*;
-import org.osgi.framework.*;
-
-/**
- * Bundle-Activator for the Thunderbird address book contact source plug-in.
- *
- * @author Ingo Bauersachs
- */
-public class ThunderbirdActivator
- implements BundleActivator
-{
- /** OSGi context. */
- private static BundleContext bundleContext;
-
- /** Active address book registrations. */
- private static Map<ThunderbirdContactSourceService, ServiceRegistration>
- registrations;
-
- /**
- * The registered PhoneNumberI18nService.
- */
- private static PhoneNumberI18nService phoneNumberI18nService;
-
- /**
- * Gets the configuration service.
- * @return the configuration service.
- */
- static ConfigurationService getConfigService()
- {
- return ServiceUtils.getService(bundleContext,
- ConfigurationService.class);
- }
-
- /**
- * Gets the resource service.
- * @return the resource service.
- */
- static ResourceManagementService getResources()
- {
- return ServiceUtils.getService(bundleContext,
- ResourceManagementService.class);
- }
-
- /**
- * Gets all registered Thunderbird address book services.
- * @return all registered Thunderbird address book services.
- */
- static List<ThunderbirdContactSourceService> getActiveServices()
- {
- return new LinkedList<ThunderbirdContactSourceService>(
- registrations.keySet());
- }
-
- /**
- * Loads and registers an address book service.
- * @param config the name of the base property of the service to load.
- */
- static void add(String config)
- {
- ThunderbirdContactSourceService service
- = new ThunderbirdContactSourceService(config);
- registrations.put(service,
- bundleContext.registerService(
- ContactSourceService.class.getName(), service, null));
- }
-
- /**
- * Stops an address book service and deletes the corresponding configuration
- * data.
- *
- * @param service the address book instance to remove.
- */
- static void remove(ThunderbirdContactSourceService service)
- {
- registrations.get(service).unregister();
- registrations.remove(service);
- ConfigurationService config = getConfigService();
- config.removeProperty(service.getBaseConfigProperty());
- for (String prop : config.getPropertyNamesByPrefix(
- service.getBaseConfigProperty(), false))
- {
- config.removeProperty(prop);
- }
- }
-
- /**
- * Searches the configuration for Thunderbird address books and registers a
- * {@link ContactSourceService} for each found config.
- */
- public void start(BundleContext bundleContext) throws Exception
- {
- ThunderbirdActivator.bundleContext = bundleContext;
-
- ConfigurationService config = getConfigService();
- List<String> configs =
- config.getPropertyNamesByPrefix(
- ThunderbirdContactSourceService.PNAME_BASE_THUNDERBIRD_CONFIG,
- false);
-
- registrations = new HashMap
- <ThunderbirdContactSourceService, ServiceRegistration>();
- for (String cfg : configs)
- {
- String value = config.getString(cfg);
- if (value != null && cfg.endsWith(value))
- {
- add(cfg);
- }
- }
-
- /* registers the configuration form */
- Dictionary<String, String> properties
- = new Hashtable<String, String>();
- properties.put(
- ConfigurationForm.FORM_TYPE,
- ConfigurationForm.CONTACT_SOURCE_TYPE);
-
- bundleContext.registerService(
- ConfigurationForm.class.getName(),
- new LazyConfigurationForm(
- ThunderbirdConfigForm.class.getName(),
- getClass().getClassLoader(),
- null,
- "plugin.thunderbird.CONFIG_FORM_TITLE"),
- properties);
- }
-
- /**
- * Unregisters all {@link ContactSourceService}s that were registered by
- * this activator.
- */
- public void stop(BundleContext bundleContext) throws Exception
- {
- for (ServiceRegistration sr : registrations.values())
- {
- sr.unregister();
- }
-
- registrations = null;
- }
-
- /**
- * Returns the PhoneNumberI18nService.
- * @return returns the PhoneNumberI18nService.
- */
- public static PhoneNumberI18nService getPhoneNumberI18nService()
- {
- if(phoneNumberI18nService == null)
- {
- phoneNumberI18nService = ServiceUtils.getService(
- bundleContext,
- PhoneNumberI18nService.class);
- }
-
- return phoneNumberI18nService;
- }
-}
+package net.java.sip.communicator.plugin.thunderbird;
+
+import java.util.*;
+
+import net.java.sip.communicator.service.contactsource.*;
+import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.util.*;
+
+import org.jitsi.service.configuration.*;
+import org.jitsi.service.resources.*;
+import org.osgi.framework.*;
+
+/**
+ * Bundle-Activator for the Thunderbird address book contact source plug-in.
+ *
+ * @author Ingo Bauersachs
+ */
+public class ThunderbirdActivator
+ implements BundleActivator
+{
+ /** OSGi context. */
+ private static BundleContext bundleContext;
+
+ /** Active address book registrations. */
+ private static Map<ThunderbirdContactSourceService, ServiceRegistration>
+ registrations;
+
+ /**
+ * The registered PhoneNumberI18nService.
+ */
+ private static PhoneNumberI18nService phoneNumberI18nService;
+
+ /**
+ * Gets the configuration service.
+ * @return the configuration service.
+ */
+ static ConfigurationService getConfigService()
+ {
+ return ServiceUtils.getService(bundleContext,
+ ConfigurationService.class);
+ }
+
+ /**
+ * Gets the resource service.
+ * @return the resource service.
+ */
+ static ResourceManagementService getResources()
+ {
+ return ServiceUtils.getService(bundleContext,
+ ResourceManagementService.class);
+ }
+
+ /**
+ * Gets all registered Thunderbird address book services.
+ * @return all registered Thunderbird address book services.
+ */
+ static List<ThunderbirdContactSourceService> getActiveServices()
+ {
+ return new LinkedList<ThunderbirdContactSourceService>(
+ registrations.keySet());
+ }
+
+ /**
+ * Loads and registers an address book service.
+ * @param config the name of the base property of the service to load.
+ */
+ static void add(String config)
+ {
+ ThunderbirdContactSourceService service
+ = new ThunderbirdContactSourceService(config);
+ registrations.put(service,
+ bundleContext.registerService(
+ ContactSourceService.class.getName(), service, null));
+ }
+
+ /**
+ * Stops an address book service and deletes the corresponding configuration
+ * data.
+ *
+ * @param service the address book instance to remove.
+ */
+ static void remove(ThunderbirdContactSourceService service)
+ {
+ registrations.get(service).unregister();
+ registrations.remove(service);
+ ConfigurationService config = getConfigService();
+ config.removeProperty(service.getBaseConfigProperty());
+ for (String prop : config.getPropertyNamesByPrefix(
+ service.getBaseConfigProperty(), false))
+ {
+ config.removeProperty(prop);
+ }
+ }
+
+ /**
+ * Searches the configuration for Thunderbird address books and registers a
+ * {@link ContactSourceService} for each found config.
+ */
+ public void start(BundleContext bundleContext) throws Exception
+ {
+ ThunderbirdActivator.bundleContext = bundleContext;
+
+ ConfigurationService config = getConfigService();
+ List<String> configs =
+ config.getPropertyNamesByPrefix(
+ ThunderbirdContactSourceService.PNAME_BASE_THUNDERBIRD_CONFIG,
+ false);
+
+ registrations = new HashMap
+ <ThunderbirdContactSourceService, ServiceRegistration>();
+ for (String cfg : configs)
+ {
+ String value = config.getString(cfg);
+ if (value != null && cfg.endsWith(value))
+ {
+ add(cfg);
+ }
+ }
+
+ /* registers the configuration form */
+ Dictionary<String, String> properties
+ = new Hashtable<String, String>();
+ properties.put(
+ ConfigurationForm.FORM_TYPE,
+ ConfigurationForm.CONTACT_SOURCE_TYPE);
+
+ bundleContext.registerService(
+ ConfigurationForm.class.getName(),
+ new LazyConfigurationForm(
+ ThunderbirdConfigForm.class.getName(),
+ getClass().getClassLoader(),
+ null,
+ "plugin.thunderbird.CONFIG_FORM_TITLE"),
+ properties);
+ }
+
+ /**
+ * Unregisters all {@link ContactSourceService}s that were registered by
+ * this activator.
+ */
+ public void stop(BundleContext bundleContext) throws Exception
+ {
+ for (ServiceRegistration sr : registrations.values())
+ {
+ sr.unregister();
+ }
+
+ registrations = null;
+ }
+
+ /**
+ * Returns the PhoneNumberI18nService.
+ * @return returns the PhoneNumberI18nService.
+ */
+ public static PhoneNumberI18nService getPhoneNumberI18nService()
+ {
+ if(phoneNumberI18nService == null)
+ {
+ phoneNumberI18nService = ServiceUtils.getService(
+ bundleContext,
+ PhoneNumberI18nService.class);
+ }
+
+ return phoneNumberI18nService;
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdContactQuery.java b/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdContactQuery.java
index 429ff6c..00488f9 100644
--- a/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdContactQuery.java
+++ b/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdContactQuery.java
@@ -1,4 +1,4 @@
-/*
+/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
@@ -15,267 +15,267 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package net.java.sip.communicator.plugin.thunderbird;
-
-import java.io.*;
-import java.util.*;
-import java.util.Map.Entry;
-import java.util.regex.*;
-
-import org.jitsi.util.StringUtils;
-
-import mork.*;
-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.*;
-
-/**
- * Queries a Thunderbird address book for contacts matching the given pattern.
- *
- * @author Ingo Bauersachs
- */
-public class ThunderbirdContactQuery
- extends AsyncContactQuery<ThunderbirdContactSourceService>
-{
- /** Class logger */
- private final static Logger logger = Logger
- .getLogger(ThunderbirdContactQuery.class);
-
- /**
- * Creates a new instance of this class.
- *
- * @param owner The contact source that created this query.
- * @param query The pattern to match against the contacts database.
- */
- public ThunderbirdContactQuery(ThunderbirdContactSourceService owner,
- Pattern query)
- {
- super(owner, query);
- }
-
- /**
- * Starts the query against the address book database.
- */
- @Override
- protected void run()
- {
- String filename = super.getContactSource().getFilename();
- File file = new File(filename);
- try
- {
- if (file.lastModified() > getContactSource().lastDatabaseFileChange)
- {
- // parse the Thunderbird Mork database
- InputStreamReader sr =
- new InputStreamReader(new FileInputStream(filename));
- MorkDocument md = new MorkDocument(sr);
- sr.close();
-
- // We now have rows in their tables and additional rows at
- // transaction level. Put the to a better format:
- // DB -> Tables -> Rows
- Map<String, Map<String, Row>> db =
- new HashMap<String, Map<String, Row>>();
- for (Table t : md.getTables())
- {
- String tableId = t.getTableId() + "/" + t.getScopeName();
- Map<String, Row> table = db.get(tableId);
- if (table == null)
- {
- table = new HashMap<String, Row>();
- db.put(tableId, table);
- }
-
- for (Row r : t.getRows())
- {
- String scope = r.getScopeName();
- if (scope == null)
- {
- scope = t.getScopeName();
- }
-
- table.put(r.getRowId() + "/" + scope, r);
- }
- }
-
- // The additional rows at the root-level update/replace the ones
- // in the tables. There's usually neither a table nor a scope
- // defined, so lets just use the default.
- String defaultScope = md.getDicts().get(0).dereference("^80");
- for (Row r : md.getRows())
- {
- String scope = r.getScopeName();
- if (scope == null)
- {
- scope = defaultScope;
- }
-
- String tableId = "1/" + scope;
- Map<String, Row> table = db.get(tableId);
- if (table == null)
- {
- table = new HashMap<String, Row>();
- db.put(tableId, table);
- }
-
- String rowId = r.getRowId() + "/" + scope;
- if (rowId.startsWith("-"))
- {
- rowId = rowId.substring(1);
- }
-
- table.put(rowId, r);
- }
-
- super.getContactSource().database = db;
- super.getContactSource().defaultScope = defaultScope;
- super.getContactSource().lastDatabaseFileChange =
- file.lastModified();
- }
-
- // okay, "transactions" are applied, now perform the search
- for (Entry<String, Map<String, Row>> table
- : super.getContactSource().database.entrySet())
- {
- for (Map.Entry<String, Row> e : table.getValue().entrySet())
- {
- if (e.getKey().endsWith(getContactSource().defaultScope))
- {
- readEntry(e.getValue());
- }
- }
- }
-
- super.stopped(true);
- }
- catch (FileNotFoundException e)
- {
- logger.warn("Could not open address book", e);
- }
- catch (Exception e)
- {
- logger.warn("Could not parse " + file, e);
- }
- }
-
- /**
- * Processes a database row by matching it against the query and adding it
- * to the result set if it matched.
- *
- * @param r The database row representing a contact.
- */
- private void readEntry(Row r)
- {
- // match the pattern against this contact
- boolean hadMatch = false;
- for (Alias value : r.getAliases().values())
- {
- if (value != null
- && (super.query.matcher(value.getValue()).find() || super
- .phoneNumberMatches(value.getValue())))
- {
- hadMatch = true;
- break;
- }
- }
-
- // nope, didn't match, ignore
- if (!hadMatch)
- {
- return;
- }
-
- List<ContactDetail> details = new LinkedList<ContactDetail>();
-
- // e-mail(s)
- for (String email : getPropertySet(r, "PrimaryEmail", "SecondEmail",
- "DefaultEmail"))
- {
- ContactDetail detail = new ContactDetail(email, Category.Email);
- detail.addSupportedOpSet(OperationSetPersistentPresence.class);
- details.add(detail);
- }
-
- // phone number(s)
- this.addPhoneDetail(details, r, "HomePhone", SubCategory.Home);
- this.addPhoneDetail(details, r, "WorkPhone", SubCategory.Work);
- this.addPhoneDetail(details, r, "CellularNumber", SubCategory.Mobile);
-
- // and the dispaly name
- String displayName = r.getValue("DisplayName");
- if (StringUtils.isNullOrEmpty(displayName, true))
- {
- displayName = r.getValue("LastName");
- if (displayName != null)
- {
- displayName = displayName.trim();
- }
-
- String firstName = r.getValue("FirstName");
- if (!StringUtils.isNullOrEmpty(firstName, true))
- {
- displayName = firstName + " " + displayName;
- }
- }
-
- // create the contact and add it to the results
- GenericSourceContact sc =
- new GenericSourceContact(super.getContactSource(), displayName,
- details);
- addQueryResult(sc);
- }
-
- /**
- * Adds a "Phone" {@link ContactDetail} to a query contact.
- *
- * @param details The {@link List} of {@link ContactDetail}s to which the
- * details is added.
- * @param r The source database row of the contact.
- * @param property The source database property name to add as a detail.
- * @param category The Phone-{@link SubCategory} for the phone number to
- * add.
- */
- private void addPhoneDetail(List<ContactDetail> details, Row r,
- String property, SubCategory category)
- {
- String phone = r.getValue(property);
- if (StringUtils.isNullOrEmpty(phone, true))
- {
- return;
- }
-
- phone
- = ThunderbirdActivator.getPhoneNumberI18nService().normalize(phone);
- ContactDetail detail =
- new ContactDetail(phone, ContactDetail.Category.Phone,
- new ContactDetail.SubCategory[]
- { category });
-
- detail.addSupportedOpSet(OperationSetBasicTelephony.class);
- detail.addSupportedOpSet(OperationSetPersistentPresence.class);
- details.add(detail);
- }
-
- /**
- * Gets a set of non-empty properties from the source database row.
- *
- * @param r The source database row to process.
- * @param properties The property-names to extract.
- * @return A set of non-empty properties from the source database row.
- */
- private Set<String> getPropertySet(Row r, String... properties)
- {
- Set<String> validValues = new HashSet<String>(properties.length);
- for (String prop : properties)
- {
- String value = r.getValue(prop);
- if (!StringUtils.isNullOrEmpty(value, true))
- {
- validValues.add(value);
- }
- }
-
- return validValues;
- }
-}
+package net.java.sip.communicator.plugin.thunderbird;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.regex.*;
+
+import org.jitsi.util.StringUtils;
+
+import mork.*;
+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.*;
+
+/**
+ * Queries a Thunderbird address book for contacts matching the given pattern.
+ *
+ * @author Ingo Bauersachs
+ */
+public class ThunderbirdContactQuery
+ extends AsyncContactQuery<ThunderbirdContactSourceService>
+{
+ /** Class logger */
+ private final static Logger logger = Logger
+ .getLogger(ThunderbirdContactQuery.class);
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param owner The contact source that created this query.
+ * @param query The pattern to match against the contacts database.
+ */
+ public ThunderbirdContactQuery(ThunderbirdContactSourceService owner,
+ Pattern query)
+ {
+ super(owner, query);
+ }
+
+ /**
+ * Starts the query against the address book database.
+ */
+ @Override
+ protected void run()
+ {
+ String filename = super.getContactSource().getFilename();
+ File file = new File(filename);
+ try
+ {
+ if (file.lastModified() > getContactSource().lastDatabaseFileChange)
+ {
+ // parse the Thunderbird Mork database
+ InputStreamReader sr =
+ new InputStreamReader(new FileInputStream(filename));
+ MorkDocument md = new MorkDocument(sr);
+ sr.close();
+
+ // We now have rows in their tables and additional rows at
+ // transaction level. Put the to a better format:
+ // DB -> Tables -> Rows
+ Map<String, Map<String, Row>> db =
+ new HashMap<String, Map<String, Row>>();
+ for (Table t : md.getTables())
+ {
+ String tableId = t.getTableId() + "/" + t.getScopeName();
+ Map<String, Row> table = db.get(tableId);
+ if (table == null)
+ {
+ table = new HashMap<String, Row>();
+ db.put(tableId, table);
+ }
+
+ for (Row r : t.getRows())
+ {
+ String scope = r.getScopeName();
+ if (scope == null)
+ {
+ scope = t.getScopeName();
+ }
+
+ table.put(r.getRowId() + "/" + scope, r);
+ }
+ }
+
+ // The additional rows at the root-level update/replace the ones
+ // in the tables. There's usually neither a table nor a scope
+ // defined, so lets just use the default.
+ String defaultScope = md.getDicts().get(0).dereference("^80");
+ for (Row r : md.getRows())
+ {
+ String scope = r.getScopeName();
+ if (scope == null)
+ {
+ scope = defaultScope;
+ }
+
+ String tableId = "1/" + scope;
+ Map<String, Row> table = db.get(tableId);
+ if (table == null)
+ {
+ table = new HashMap<String, Row>();
+ db.put(tableId, table);
+ }
+
+ String rowId = r.getRowId() + "/" + scope;
+ if (rowId.startsWith("-"))
+ {
+ rowId = rowId.substring(1);
+ }
+
+ table.put(rowId, r);
+ }
+
+ super.getContactSource().database = db;
+ super.getContactSource().defaultScope = defaultScope;
+ super.getContactSource().lastDatabaseFileChange =
+ file.lastModified();
+ }
+
+ // okay, "transactions" are applied, now perform the search
+ for (Entry<String, Map<String, Row>> table
+ : super.getContactSource().database.entrySet())
+ {
+ for (Map.Entry<String, Row> e : table.getValue().entrySet())
+ {
+ if (e.getKey().endsWith(getContactSource().defaultScope))
+ {
+ readEntry(e.getValue());
+ }
+ }
+ }
+
+ super.stopped(true);
+ }
+ catch (FileNotFoundException e)
+ {
+ logger.warn("Could not open address book", e);
+ }
+ catch (Exception e)
+ {
+ logger.warn("Could not parse " + file, e);
+ }
+ }
+
+ /**
+ * Processes a database row by matching it against the query and adding it
+ * to the result set if it matched.
+ *
+ * @param r The database row representing a contact.
+ */
+ private void readEntry(Row r)
+ {
+ // match the pattern against this contact
+ boolean hadMatch = false;
+ for (Alias value : r.getAliases().values())
+ {
+ if (value != null
+ && (super.query.matcher(value.getValue()).find() || super
+ .phoneNumberMatches(value.getValue())))
+ {
+ hadMatch = true;
+ break;
+ }
+ }
+
+ // nope, didn't match, ignore
+ if (!hadMatch)
+ {
+ return;
+ }
+
+ List<ContactDetail> details = new LinkedList<ContactDetail>();
+
+ // e-mail(s)
+ for (String email : getPropertySet(r, "PrimaryEmail", "SecondEmail",
+ "DefaultEmail"))
+ {
+ ContactDetail detail = new ContactDetail(email, Category.Email);
+ detail.addSupportedOpSet(OperationSetPersistentPresence.class);
+ details.add(detail);
+ }
+
+ // phone number(s)
+ this.addPhoneDetail(details, r, "HomePhone", SubCategory.Home);
+ this.addPhoneDetail(details, r, "WorkPhone", SubCategory.Work);
+ this.addPhoneDetail(details, r, "CellularNumber", SubCategory.Mobile);
+
+ // and the dispaly name
+ String displayName = r.getValue("DisplayName");
+ if (StringUtils.isNullOrEmpty(displayName, true))
+ {
+ displayName = r.getValue("LastName");
+ if (displayName != null)
+ {
+ displayName = displayName.trim();
+ }
+
+ String firstName = r.getValue("FirstName");
+ if (!StringUtils.isNullOrEmpty(firstName, true))
+ {
+ displayName = firstName + " " + displayName;
+ }
+ }
+
+ // create the contact and add it to the results
+ GenericSourceContact sc =
+ new GenericSourceContact(super.getContactSource(), displayName,
+ details);
+ addQueryResult(sc);
+ }
+
+ /**
+ * Adds a "Phone" {@link ContactDetail} to a query contact.
+ *
+ * @param details The {@link List} of {@link ContactDetail}s to which the
+ * details is added.
+ * @param r The source database row of the contact.
+ * @param property The source database property name to add as a detail.
+ * @param category The Phone-{@link SubCategory} for the phone number to
+ * add.
+ */
+ private void addPhoneDetail(List<ContactDetail> details, Row r,
+ String property, SubCategory category)
+ {
+ String phone = r.getValue(property);
+ if (StringUtils.isNullOrEmpty(phone, true))
+ {
+ return;
+ }
+
+ phone
+ = ThunderbirdActivator.getPhoneNumberI18nService().normalize(phone);
+ ContactDetail detail =
+ new ContactDetail(phone, ContactDetail.Category.Phone,
+ new ContactDetail.SubCategory[]
+ { category });
+
+ detail.addSupportedOpSet(OperationSetBasicTelephony.class);
+ detail.addSupportedOpSet(OperationSetPersistentPresence.class);
+ details.add(detail);
+ }
+
+ /**
+ * Gets a set of non-empty properties from the source database row.
+ *
+ * @param r The source database row to process.
+ * @param properties The property-names to extract.
+ * @return A set of non-empty properties from the source database row.
+ */
+ private Set<String> getPropertySet(Row r, String... properties)
+ {
+ Set<String> validValues = new HashSet<String>(properties.length);
+ for (String prop : properties)
+ {
+ String value = r.getValue(prop);
+ if (!StringUtils.isNullOrEmpty(value, true))
+ {
+ validValues.add(value);
+ }
+ }
+
+ return validValues;
+ }
+}