diff options
author | Damian Minkov <damencho@jitsi.org> | 2012-08-17 08:43:13 +0000 |
---|---|---|
committer | Damian Minkov <damencho@jitsi.org> | 2012-08-17 08:43:13 +0000 |
commit | d100493139446a9fc27e40932b1bb9dabd1e0a8f (patch) | |
tree | bd4e3daac0c8923d0622967654373f32bf7f43ff /src/net/java/sip/communicator | |
parent | 5012fc910a3cfe22d82ba13125c394e0555e9a5c (diff) | |
download | jitsi-d100493139446a9fc27e40932b1bb9dabd1e0a8f.zip jitsi-d100493139446a9fc27e40932b1bb9dabd1e0a8f.tar.gz jitsi-d100493139446a9fc27e40932b1bb9dabd1e0a8f.tar.bz2 |
Adds get/set data to SourceContacts. Moves custom buttons to ExternalContactSource. Adds listener to refresh contact sources.
Diffstat (limited to 'src/net/java/sip/communicator')
10 files changed, 519 insertions, 348 deletions
diff --git a/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java b/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java index d2ff179..9144727 100644 --- a/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java +++ b/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java @@ -20,7 +20,9 @@ import net.java.sip.communicator.util.*; * * @author Yana Stamcheva */ -public class CallHistorySourceContact implements SourceContact +public class CallHistorySourceContact + extends DataObject + implements SourceContact { /** * The parent <tt>CallHistoryContactSource</tt>, where this contact is diff --git a/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java b/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java index 1397b36..8b1573d 100644 --- a/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java +++ b/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java @@ -23,6 +23,7 @@ import org.jitsi.service.fileaccess.*; * @author Lubomir Marinov */ public class MetaContactImpl + extends DataObject implements MetaContact { /** @@ -121,22 +122,6 @@ public class MetaContactImpl }; /** - * The user-specific key-value associations stored in this instance. - * <p> - * Like the Widget implementation of Eclipse SWT, the storage type takes - * into account that there are likely to be many - * <code>MetaContactImpl</code> instances and <code>Map</code>s are thus - * likely to impose increased memory use. While an array may very well - * perform worse than a <code>Map</code> with respect to search, the - * mechanism of user-defined key-value associations explicitly states that - * it is not guaranteed to be optimized for any particular use and only - * covers the most basic cases and performance-savvy code will likely - * implement a more optimized solution anyway. - * </p> - */ - private Object[] data; - - /** * Creates new meta contact with a newly generated meta contact UID. */ MetaContactImpl() @@ -1251,98 +1236,6 @@ public class MetaContactImpl } /** - * Implements {@link MetaContact#getData(Object)}. Gets the user data - * associated with this instance and a specific key. - * - * @param key the key of the user data associated with this instance to be - * retrieved - * @return an <tt>Object</tt> which represents the value associated with - * this instance and the specified <tt>key</tt>; <tt>null</tt> if no - * association with the specified <tt>key</tt> exists in this instance - * @see MetaContact#getData(Object) - */ - public Object getData(Object key) - { - if (key == null) - throw new NullPointerException("key"); - - int index = dataIndexOf(key); - - return (index == -1) ? null : data[index + 1]; - } - - /** - * Implements {@link MetaContact#setData(Object, Object)}. Sets a - * user-specific association in this instance in the form of a key-value - * pair. If the specified <tt>key</tt> is already associated in this - * instance with a value, the existing value is overwritten with the - * specified <tt>value</tt>. - * <p> - * The user-defined association created by this method and stored in this - * instance is not serialized by this instance and is thus only meant for - * runtime use. - * </p> - * <p> - * The storage of the user data is implementation-specific and is thus not - * guaranteed to be optimized for execution time and memory use. - * </p> - * - * @param key the key to associate in this instance with the specified value - * @param value the value to be associated in this instance with the - * specified <tt>key</tt> - * @see MetaContact#setData(Object, Object) - */ - public void setData(Object key, Object value) - { - if (key == null) - throw new NullPointerException("key"); - - int index = dataIndexOf(key); - - if (index == -1) - { - - /* - * If value is null, remove the association with key (or just don't - * add it). - */ - if (data == null) - { - if (value != null) - data = new Object[] { key, value }; - } - else if (value == null) - { - int length = data.length - 2; - - if (length > 0) - { - Object[] newData = new Object[length]; - - System.arraycopy(data, 0, newData, 0, index); - System.arraycopy( - data, index + 2, newData, index, length - index); - data = newData; - } - else - data = null; - } - else - { - int length = data.length; - Object[] newData = new Object[length + 2]; - - System.arraycopy(data, 0, newData, 0, length); - data = newData; - data[length++] = key; - data[length++] = value; - } - } - else - data[index + 1] = value; - } - - /** * Updates the capabilities for the given contact. * * @param contact the <tt>Contact</tt>, which capabilities have changed @@ -1432,24 +1325,6 @@ public class MetaContactImpl } /** - * Determines the index in <code>#data</code> of a specific key. - * - * @param key - * the key to retrieve the index in <code>#data</code> of - * @return the index in <code>#data</code> of the specified <code>key</code> - * if it is contained; <tt>-1</tt> if <code>key</code> is not - * contained in <code>#data</code> - */ - private int dataIndexOf(Object key) - { - if (data != null) - for (int index = 0; index < data.length; index += 2) - if (key.equals(data[index])) - return index; - return -1; - } - - /** * Gets the sync lock for use when modifying {@link #parentGroup}. * * @return the sync lock for use when modifying {@link #parentGroup} diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java index c66bb8f..aa36661 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java @@ -251,6 +251,8 @@ public class SearchFilter false, true); } + else + ExternalContactSource.removeUIContact(sourceContact); } /** diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java index c7fd377..29c9b71 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java @@ -195,7 +195,10 @@ public class TreeContactList sourceUI.getUIGroup(), false); } else + { + ExternalContactSource.removeUIContact(sourceContact); uiContact = null; + } } /** diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/ExternalContactSource.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/ExternalContactSource.java index afa0ee9..d60a214 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/ExternalContactSource.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/ExternalContactSource.java @@ -8,8 +8,18 @@ package net.java.sip.communicator.impl.gui.main.contactlist.contactsource; import javax.swing.*; +import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.main.contactlist.*; import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.customcontactactions.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.swing.*; +import org.osgi.framework.*; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; /** * The <tt>ExternalContactSource</tt> is the UI abstraction of the @@ -20,6 +30,13 @@ import net.java.sip.communicator.service.contactsource.*; public class ExternalContactSource { /** + * The data key of the SourceContactDescriptor object used to store a + * reference to this object in its corresponding Sourcecontact. + */ + public static final String UI_CONTACT_DATA_KEY + = SourceUIContact.class.getName() + ".uiContactDescriptor"; + + /** * The <tt>SourceUIGroup</tt> containing all contacts from this source. */ private final SourceUIGroup sourceUIGroup; @@ -30,6 +47,17 @@ public class ExternalContactSource private final ContactSourceService contactSource; /** + * The current custom action contact. + */ + private static SourceContact customActionContact; + + /** + * The list of action buttons for this source contact. + */ + private static Map<ContactAction<SourceContact>, SIPCommButton> + customActionButtons; + + /** * Creates an <tt>ExternalContactSource</tt> based on the given * <tt>ContactSourceService</tt>. * @@ -75,7 +103,222 @@ public class ExternalContactSource */ public UIContact createUIContact(SourceContact sourceContact) { - return new SourceUIContact(sourceContact, sourceUIGroup); + SourceUIContact descriptor + = new SourceUIContact(sourceContact, sourceUIGroup); + + sourceContact.setData(UI_CONTACT_DATA_KEY, descriptor); + + return descriptor; + } + + /** + * Removes the <tt>UIContact</tt> from the given <tt>sourceContact</tt>. + * @param sourceContact the <tt>SourceContact</tt>, which corresponding UI + * contact we would like to remove + */ + public static void removeUIContact(SourceContact sourceContact) + { + sourceContact.setData(UI_CONTACT_DATA_KEY, null); + } + + /** + * Returns the <tt>UIContact</tt> corresponding to the given + * <tt>SourceContact</tt>. + * @param sourceContact the <tt>SourceContact</tt>, which corresponding UI + * contact we're looking for + * @return the <tt>UIContact</tt> corresponding to the given + * <tt>MetaContact</tt> + */ + public static UIContact getUIContact(SourceContact sourceContact) + { + return (UIContact) sourceContact.getData(UI_CONTACT_DATA_KEY); + } + + /** + * Returns all custom action buttons for this meta contact. + * + * @return a list of all custom action buttons for this meta contact + */ + public static Collection<SIPCommButton> getContactCustomActionButtons( + final SourceContact sourceContact) + { + customActionContact = sourceContact; + + if (customActionButtons == null) + initCustomActionButtons(); + + Iterator<ContactAction<SourceContact>> customActionsIter + = customActionButtons.keySet().iterator(); + + Collection<SIPCommButton> availableCustomActionButtons + = new LinkedList<SIPCommButton>(); + + while (customActionsIter.hasNext()) + { + ContactAction<SourceContact> contactAction + = customActionsIter.next(); + + SIPCommButton actionButton = customActionButtons.get(contactAction); + + if (isContactActionVisible( contactAction, + sourceContact)) + { + availableCustomActionButtons.add(actionButton); + } + } + + return availableCustomActionButtons; + } + + /** + * Indicates if the given <tt>ContactAction</tt> should be visible for the + * given <tt>SourceContact</tt>. + * + * @param contactAction the <tt>ContactAction</tt> to verify + * if the given action should be visible + * @return <tt>true</tt> if the given <tt>ContactAction</tt> is visible for + * the given <tt>SourceContact</tt>, <tt>false</tt> - otherwise + */ + private static boolean isContactActionVisible( + ContactAction<SourceContact> contactAction, + SourceContact contact) + { + if (contactAction.isVisible(contact)) + return true; + + return false; + } + + /** + * Initializes custom action buttons for this contact source. + */ + private static void initCustomActionButtons() + { + customActionButtons = new LinkedHashMap + <ContactAction<SourceContact>, SIPCommButton>(); + + CustomContactActionsChangeListener changeListener + = new CustomContactActionsChangeListener(); + + for (CustomContactActionsService<SourceContact> ccas + : getContactActionsServices()) + { + ccas.addCustomContactActionsListener(changeListener); + + Iterator<ContactAction<SourceContact>> actionIterator + = ccas.getCustomContactActions(); + + while (actionIterator!= null && actionIterator.hasNext()) + { + final ContactAction<SourceContact> ca = actionIterator.next(); + + SIPCommButton actionButton = customActionButtons.get(ca); + + if (actionButton == null) + { + actionButton = new SIPCommButton( + new ImageIcon(ca.getIcon()).getImage(), + new ImageIcon(ca.getPressedIcon()).getImage(), + null); + + actionButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + List<UIContactDetail> contactDetails + = SourceUIContact.getContactDetails( + customActionContact); + contactDetails.add( + new SourceUIContact.SourceContactDetail( + customActionContact.getDisplayName(), + customActionContact)); + + UIContactDetailCustomAction contactAction + = new UIContactDetailCustomAction(ca); + + if (contactDetails.size() > 1) + { + ChooseUIContactDetailPopupMenu + detailsPopupMenu + = new ChooseUIContactDetailPopupMenu( + (JButton) e.getSource(), + contactDetails, + contactAction); + + detailsPopupMenu.showPopupMenu(); + } + else if (contactDetails.size() == 1) + { + JButton button = (JButton) e.getSource(); + Point location = new Point(button.getX(), + button.getY() + button.getHeight()); + + SwingUtilities.convertPointToScreen( + location, GuiActivator.getContactList()); + + location.y = location.y + + GuiActivator.getContactList() + .getPathBounds( + GuiActivator.getContactList() + .getSelectionPath()).y; + + contactAction.actionPerformed( + contactDetails.get(0), + location.x, + location.y); + } + } + }); + + customActionButtons.put(ca, actionButton); + } + } + } + } + + /** + * Returns a list of all custom contact action services. + * + * @return a list of all custom contact action services. + */ + @SuppressWarnings ("unchecked") + private static List<CustomContactActionsService<SourceContact>> + getContactActionsServices() + { + List<CustomContactActionsService<SourceContact>> + contactActionsServices + = new ArrayList<CustomContactActionsService + <SourceContact>>(); + + ServiceReference[] serRefs = null; + try + { + // get all registered provider factories + serRefs + = GuiActivator.bundleContext.getServiceReferences( + CustomContactActionsService.class.getName(), null); + } + catch (InvalidSyntaxException e) + {} + + if (serRefs != null) + { + for (ServiceReference serRef : serRefs) + { + CustomContactActionsService<?> customActionService + = (CustomContactActionsService<?>) + GuiActivator.bundleContext.getService(serRef); + + if (customActionService.getContactSourceClass() + .equals(SourceContact.class)) + { + contactActionsServices.add( + (CustomContactActionsService<SourceContact>) + customActionService); + } + } + } + return contactActionsServices; } /** @@ -209,4 +452,67 @@ public class ExternalContactSource return null; } } + + /** + * Listens for updates on actions and when received update the source contact. + */ + private static class CustomContactActionsChangeListener + implements CustomContactActionsListener + { + /** + * Update for custom action has occurred. + * @param event the event containing the source which was updated. + */ + public void updated(CustomContactActionsEvent event) + { + if(!(event.getSource() instanceof SourceContact)) + return; + + ContactNode contactNode + = getUIContact((SourceContact)event.getSource()).getContactNode(); + + if (contactNode != null) + GuiActivator.getContactList().nodeChanged(contactNode); + } + } + + /** + * An implementation of <tt>UIContactDetail</tt> for a custom action. + */ + private static class UIContactDetailCustomAction + implements UIContactDetailAction + { + /** + * The contact action. + */ + private final ContactAction<SourceContact> contactAction; + + /** + * Creates an instance of <tt>UIContactDetailCustomAction</tt>. + */ + public UIContactDetailCustomAction( + ContactAction<SourceContact> contactAction) + { + this.contactAction = contactAction; + } + + /** + * Performs the action on button click. + */ + public void actionPerformed(UIContactDetail contactDetail, int x, int y) + { + try + { + contactAction.actionPerformed( + (SourceContact) contactDetail.getDescriptor(), x, y); + } + catch (OperationFailedException e) + { + new ErrorDialog(null, + GuiActivator.getResources() + .getI18NString("service.gui.ERROR"), + e.getMessage()); + } + } + } } diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java index 4d9c6b1..0098beb 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java @@ -7,7 +7,6 @@ package net.java.sip.communicator.impl.gui.main.contactlist.contactsource; import java.awt.*; -import java.awt.event.*; import java.util.*; import java.util.List; @@ -55,12 +54,6 @@ public class SourceUIContact private final List<String> searchStrings = new LinkedList<String>(); /** - * The list of action buttons for this source contact. - */ - private Map<ContactAction<SourceContact>, SIPCommButton> - customActionButtons; - - /** * Creates an instance of <tt>SourceUIContact</tt> by specifying the * <tt>SourceContact</tt>, on which this abstraction is based and the * parent <tt>UIGroup</tt>. @@ -203,6 +196,18 @@ public class SourceUIContact */ public List<UIContactDetail> getContactDetails() { + return getContactDetails(sourceContact); + } + + /** + * Returns a list of all contained <tt>UIContactDetail</tt>s. + * + * @param sourceContact the source contact we get details from. + * @return a list of all contained <tt>UIContactDetail</tt>s + */ + public static List<UIContactDetail> getContactDetails( + SourceContact sourceContact) + { List<UIContactDetail> resultList = new LinkedList<UIContactDetail>(); @@ -213,7 +218,7 @@ public class SourceUIContact { ContactDetail detail = details.next(); - resultList.add(new SourceContactDetail(detail, null)); + resultList.add(new SourceContactDetail(detail, null, sourceContact)); } return resultList; } @@ -244,7 +249,8 @@ public class SourceUIContact if ((supportedOperationSets != null) && supportedOperationSets.contains(opSetClass)) { - resultList.add(new SourceContactDetail(detail, opSetClass)); + resultList.add(new SourceContactDetail( + detail, opSetClass, sourceContact)); } } return resultList; @@ -277,13 +283,15 @@ public class SourceUIContact public void setContactNode(ContactNode contactNode) { this.contactNode = contactNode; + if (contactNode == null) + ExternalContactSource.removeUIContact(sourceContact); } /** * The implementation of the <tt>UIContactDetail</tt> interface for the * external source <tt>ContactDetail</tt>s. */ - private class SourceContactDetail extends UIContactDetail + protected static class SourceContactDetail extends UIContactDetail { /** * Creates an instance of <tt>SourceContactDetail</tt> by specifying @@ -294,7 +302,8 @@ public class SourceUIContact * preferred protocol provider */ public SourceContactDetail( ContactDetail detail, - Class<? extends OperationSet> opSetClass) + Class<? extends OperationSet> opSetClass, + SourceContact sourceContact) { super( detail.getContactAddress(), detail.getContactAddress(), @@ -324,8 +333,10 @@ public class SourceUIContact * for it. * * @param displayName the display name + * @param sourceContact the source contact */ - public SourceContactDetail(String displayName) + public SourceContactDetail(String displayName, + SourceContact sourceContact) { super( displayName, displayName, @@ -461,218 +472,16 @@ public class SourceUIContact } /** - * Returns all custom action buttons for this meta contact. + * Returns all custom action buttons for this notification contact. * - * @return a list of all custom action buttons for this meta contact + * @return a list of all custom action buttons for this notification contact */ public Collection<SIPCommButton> getContactCustomActionButtons() { - if (customActionButtons == null) - initCustomActionButtons(); - - Iterator<ContactAction<SourceContact>> customActionsIter - = customActionButtons.keySet().iterator(); - - Collection<SIPCommButton> availableCustomActionButtons - = new LinkedList<SIPCommButton>(); - - while (customActionsIter.hasNext()) - { - ContactAction<SourceContact> contactAction - = customActionsIter.next(); - - SIPCommButton actionButton = customActionButtons.get(contactAction); - - if (isContactActionVisible( contactAction, - sourceContact)) - { - availableCustomActionButtons.add(actionButton); - } - } - - return availableCustomActionButtons; - } - - /** - * Indicates if the given <tt>ContactAction</tt> should be visible for the - * given <tt>SourceContact</tt>. - * - * @param contactAction the <tt>ContactAction</tt> to verify - * if the given action should be visible - * @return <tt>true</tt> if the given <tt>ContactAction</tt> is visible for - * the given <tt>SourceContact</tt>, <tt>false</tt> - otherwise - */ - private static boolean isContactActionVisible( - ContactAction<SourceContact> contactAction, - SourceContact contact) - { - if (contactAction.isVisible(contact)) - return true; - - return false; - } - - /** - * Initializes custom action buttons for this contact source. - */ - private void initCustomActionButtons() - { - customActionButtons = new LinkedHashMap - <ContactAction<SourceContact>, SIPCommButton>(); - - for (CustomContactActionsService<SourceContact> ccas - : getContactActionsServices()) - { - Iterator<ContactAction<SourceContact>> actionIterator - = ccas.getCustomContactActions(); - - while (actionIterator!= null && actionIterator.hasNext()) - { - final ContactAction<SourceContact> ca = actionIterator.next(); - - SIPCommButton actionButton = customActionButtons.get(ca); - - if (actionButton == null) - { - actionButton = new SIPCommButton( - new ImageIcon(ca.getIcon()).getImage(), - new ImageIcon(ca.getPressedIcon()).getImage(), - null); - - actionButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - List<UIContactDetail> contactDetails - = getContactDetails(); - contactDetails.add(new SourceContactDetail( - sourceContact.getDisplayName())); - - UIContactDetailCustomAction contactAction - = new UIContactDetailCustomAction(ca); - - if (contactDetails.size() > 1) - { - ChooseUIContactDetailPopupMenu - detailsPopupMenu - = new ChooseUIContactDetailPopupMenu( - (JButton) e.getSource(), - contactDetails, - contactAction); - - detailsPopupMenu.showPopupMenu(); - } - else if (contactDetails.size() == 1) - { - JButton button = (JButton) e.getSource(); - Point location = new Point(button.getX(), - button.getY() + button.getHeight()); - - SwingUtilities.convertPointToScreen( - location, GuiActivator.getContactList()); - - location.y = location.y - + GuiActivator.getContactList() - .getPathBounds( - GuiActivator.getContactList() - .getSelectionPath()).y; - - contactAction.actionPerformed( - contactDetails.get(0), - location.x, - location.y); - } - } - }); - - customActionButtons.put(ca, actionButton); - } - } - } - } - - /** - * Returns a list of all custom contact action services. - * - * @return a list of all custom contact action services. - */ - @SuppressWarnings ("unchecked") - private static List<CustomContactActionsService<SourceContact>> - getContactActionsServices() - { - List<CustomContactActionsService<SourceContact>> - contactActionsServices - = new ArrayList<CustomContactActionsService - <SourceContact>>(); - - ServiceReference[] serRefs = null; - try - { - // get all registered provider factories - serRefs - = GuiActivator.bundleContext.getServiceReferences( - CustomContactActionsService.class.getName(), null); - } - catch (InvalidSyntaxException e) - {} - - if (serRefs != null) - { - for (ServiceReference serRef : serRefs) - { - CustomContactActionsService<?> customActionService - = (CustomContactActionsService<?>) - GuiActivator.bundleContext.getService(serRef); - - if (customActionService.getContactSourceClass() - .equals(SourceContact.class)) - { - contactActionsServices.add( - (CustomContactActionsService<SourceContact>) - customActionService); - } - } - } - return contactActionsServices; - } + if (sourceContact != null) + return ExternalContactSource + .getContactCustomActionButtons(sourceContact); - /** - * An implementation of <tt>UIContactDetail</tt> for a custom action. - */ - private static class UIContactDetailCustomAction - implements UIContactDetailAction - { - /** - * The contact action. - */ - private final ContactAction<SourceContact> contactAction; - - /** - * Creates an instance of <tt>UIContactDetailCustomAction</tt>. - */ - public UIContactDetailCustomAction( - ContactAction<SourceContact> contactAction) - { - this.contactAction = contactAction; - } - - /** - * Performs the action on button click. - */ - public void actionPerformed(UIContactDetail contactDetail, int x, int y) - { - try - { - contactAction.actionPerformed( - (SourceContact) contactDetail.getDescriptor(), x, y); - } - catch (OperationFailedException e) - { - new ErrorDialog(null, - GuiActivator.getResources() - .getI18NString("service.gui.ERROR"), - e.getMessage()); - } - } + return null; } } diff --git a/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java b/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java index cf84e06..ab382ee 100644 --- a/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java +++ b/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java @@ -9,6 +9,7 @@ package net.java.sip.communicator.service.contactsource; import java.util.*;
import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.util.*;
/**
* Implements a generic <tt>SourceContact</tt> for the purposes of the support
@@ -17,6 +18,7 @@ import net.java.sip.communicator.service.protocol.*; * @author Lyubomir Marinov
*/
public class GenericSourceContact
+ extends DataObject
implements SourceContact
{
/**
diff --git a/src/net/java/sip/communicator/service/contactsource/SourceContact.java b/src/net/java/sip/communicator/service/contactsource/SourceContact.java index 9d4536e..d013d7f 100644 --- a/src/net/java/sip/communicator/service/contactsource/SourceContact.java +++ b/src/net/java/sip/communicator/service/contactsource/SourceContact.java @@ -91,4 +91,36 @@ public interface SourceContact * @return the byte array of the image or null if no image is available */ public byte[] getImage(); + + /** + * Gets the user data associated with this instance and a specific key. + * + * @param key the key of the user data associated with this instance to be + * retrieved + * @return an <tt>Object</tt> which represents the value associated with + * this instance and the specified <tt>key</tt>; <tt>null</tt> if no + * association with the specified <tt>key</tt> exists in this instance + */ + public Object getData(Object key); + + /** + * Sets a user-specific association in this instance in the form of a + * key-value pair. If the specified <tt>key</tt> is already associated in + * this instance with a value, the existing value is overwritten with the + * specified <tt>value</tt>. + * <p> + * The user-defined association created by this method and stored in this + * instance is not serialized by this instance and is thus only meant for + * runtime use. + * </p> + * <p> + * The storage of the user data is implementation-specific and is thus not + * guaranteed to be optimized for execution time and memory use. + * </p> + * + * @param key the key to associate in this instance with the specified value + * @param value the value to be associated in this instance with the + * specified <tt>key</tt> + */ + public void setData(Object key, Object value); } diff --git a/src/net/java/sip/communicator/service/contactsource/contactsource.manifest.mf b/src/net/java/sip/communicator/service/contactsource/contactsource.manifest.mf index 7b06df7..4ae0097 100644 --- a/src/net/java/sip/communicator/service/contactsource/contactsource.manifest.mf +++ b/src/net/java/sip/communicator/service/contactsource/contactsource.manifest.mf @@ -4,5 +4,6 @@ Bundle-Vendor: jitsi.org Bundle-Version: 0.0.1 System-Bundle: yes Import-Package: org.osgi.framework, + net.java.sip.communicator.util, net.java.sip.communicator.service.protocol Export-Package: net.java.sip.communicator.service.contactsource diff --git a/src/net/java/sip/communicator/util/DataObject.java b/src/net/java/sip/communicator/util/DataObject.java new file mode 100644 index 0000000..21c5903 --- /dev/null +++ b/src/net/java/sip/communicator/util/DataObject.java @@ -0,0 +1,139 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.util; + +/** + * Object which can store user specific key-values. + * + * @author Damian Minkov + */ +public class DataObject +{ + /** + * The user-specific key-value associations stored in this instance. + * <p> + * Like the Widget implementation of Eclipse SWT, the storage type takes + * into account that there are likely to be many + * <code>DataObject</code> instances and <code>Map</code>s are thus + * likely to impose increased memory use. While an array may very well + * perform worse than a <code>Map</code> with respect to search, the + * mechanism of user-defined key-value associations explicitly states that + * it is not guaranteed to be optimized for any particular use and only + * covers the most basic cases and performance-savvy code will likely + * implement a more optimized solution anyway. + * </p> + */ + private Object[] data; + + /** + * Gets the user data + * associated with this instance and a specific key. + * + * @param key the key of the user data associated with this instance to be + * retrieved + * @return an <tt>Object</tt> which represents the value associated with + * this instance and the specified <tt>key</tt>; <tt>null</tt> if no + * association with the specified <tt>key</tt> exists in this instance + */ + public Object getData(Object key) + { + if (key == null) + throw new NullPointerException("key"); + + int index = dataIndexOf(key); + + return (index == -1) ? null : data[index + 1]; + } + + /** + * Determines the index in <code>#data</code> of a specific key. + * + * @param key + * the key to retrieve the index in <code>#data</code> of + * @return the index in <code>#data</code> of the specified <code>key</code> + * if it is contained; <tt>-1</tt> if <code>key</code> is not + * contained in <code>#data</code> + */ + private int dataIndexOf(Object key) + { + if (data != null) + for (int index = 0; index < data.length; index += 2) + if (key.equals(data[index])) + return index; + return -1; + } + + /** + * Sets a + * user-specific association in this instance in the form of a key-value + * pair. If the specified <tt>key</tt> is already associated in this + * instance with a value, the existing value is overwritten with the + * specified <tt>value</tt>. + * <p> + * The user-defined association created by this method and stored in this + * instance is not serialized by this instance and is thus only meant for + * runtime use. + * </p> + * <p> + * The storage of the user data is implementation-specific and is thus not + * guaranteed to be optimized for execution time and memory use. + * </p> + * + * @param key the key to associate in this instance with the specified value + * @param value the value to be associated in this instance with the + * specified <tt>key</tt> + */ + public void setData(Object key, Object value) + { + if (key == null) + throw new NullPointerException("key"); + + int index = dataIndexOf(key); + + if (index == -1) + { + + /* + * If value is null, remove the association with key (or just don't + * add it). + */ + if (data == null) + { + if (value != null) + data = new Object[] { key, value }; + } + else if (value == null) + { + int length = data.length - 2; + + if (length > 0) + { + Object[] newData = new Object[length]; + + System.arraycopy(data, 0, newData, 0, index); + System.arraycopy( + data, index + 2, newData, index, length - index); + data = newData; + } + else + data = null; + } + else + { + int length = data.length; + Object[] newData = new Object[length + 2]; + + System.arraycopy(data, 0, newData, 0, length); + data = newData; + data[length++] = key; + data[length++] = value; + } + } + else + data[index + 1] = value; + } +} |