Package net.java.sip.communicator.impl.gui.main.contactlist.contactsource

Source Code of net.java.sip.communicator.impl.gui.main.contactlist.contactsource.MetaUIContact$MetaContactDetail

/*
* 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.impl.gui.main.contactlist.contactsource;

import java.util.*;

import javax.swing.*;

import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.gui.*;

import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.OperationSetExtendedAuthorizations.SubscriptionStatus;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.FaxDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenericDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.MobilePhoneDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.PagerDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.PhoneNumberDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.WorkPhoneDetail;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;

/**
* The <tt>MetaUIContact</tt> is the implementation of the UIContact interface
* for the <tt>MetaContactListService</tt>. This implementation is based on the
* <tt>MetaContact</tt>.
*
* @author Yana Stamcheva
*/
public class MetaUIContact
    extends UIContactImpl
{
    /**
     * The key of the user data in <tt>MetaContact</tt> which specifies
     * the avatar cached from previous invocations.
     */
    private static final String AVATAR_DATA_KEY
        = MetaUIContact.class.getName() + ".avatar";

    /**
     * A list of all search strings available for the underlying
     * <tt>MetaContact</tt>.
     */
    private final List<String> searchStrings = new LinkedList<String>();

    /**
     * The <tt>MetaContact</tt>, on which this implementation is based.
     */
    private MetaContact metaContact;

    /**
     * The corresponding <tt>ContactNode</tt> in the contact list component
     * data model.
     */
    private ContactNode contactNode;

    /**
     * The parent <tt>UIGroup</tt> of this contact.
     */
    private UIGroup parentUIGroup;

    /**
     * The subscription status of this meta contact. It will be turned to true
     * when all the contact details are checked.
     */
    boolean subscribed = false;

    /**
     * Creates an instance of <tt>MetaUIContact</tt> by specifying the
     * underlying <tt>MetaContact</tt>, on which it's based.
     * @param metaContact the <tt>MetaContact</tt>, on which this implementation
     * is based
     */
    public MetaUIContact(MetaContact metaContact)
    {
        this.metaContact = metaContact;

        initSearchStrings();
    }

    /**
     * Returns the underlying <tt>MetaContact</tt>.
     * @return the underlying <tt>MetaContact</tt>
     */
    public Object getDescriptor()
    {
        return metaContact;
    }

    /**
     * Returns the display name of this <tt>MetaUIContact</tt>.
     * @return the display name of this <tt>MetaUIContact</tt>
     */
    public String getDisplayName()
    {
        String displayName = metaContact.getDisplayName();

        /*
         * If the MetaContact doesn't tell us a display name, make up a display
         * name so that we don't end up with "Unknown user".
         */
        if ((displayName == null) || (displayName.trim().length() == 0))
        {
            /*
             * Try to get a display name from one of the Contacts of the
             * MetaContact. If that doesn't cut it, use the address of a
             * Contact. Because it's not really clear which address to display
             * when there are multiple Contacts, use the address only when
             * there's a single Contact in the MetaContact.
             */
            Iterator<Contact> contactIter = metaContact.getContacts();
            int contactCount = 0;
            String address = null;

            while (contactIter.hasNext())
            {
                Contact contact = contactIter.next();

                contactCount++;

                displayName = contact.getDisplayName();
                if ((displayName == null) || (displayName.trim().length() == 0))
                {
                    /*
                     * As said earlier, only use an address if there's a single
                     * Contact in the MetaContact.
                     */
                    address = (contactCount == 1) ? contact.getAddress() : null;
                }
                else
                    break;
            }
            if ((address != null)
                    && (address.trim().length() != 0)
                    && ((displayName == null)
                            || (displayName.trim().length() == 0)))
                displayName = address;
        }
        return displayName;
    }

    /**
     * Returns the index of the underlying <tt>MetaContact</tt> in its
     * <tt>MetaContactListService</tt> parent group.
     * @return the source index of the underlying <tt>MetaContact</tt>
     */
    public int getSourceIndex()
    {
        MetaContactGroup parentMetaContactGroup =
                metaContact.getParentMetaContactGroup();
        if (parentMetaContactGroup == null)
            return -1;
        return parentMetaContactGroup.indexOf(metaContact);
    }

    /**
     * Returns an <tt>Iterator</tt> over a list of strings, which can be used
     * to find this contact.
     * @return an <tt>Iterator</tt> over a list of search strings
     */
    public Iterator<String> getSearchStrings()
    {
        return searchStrings.iterator();
    }

    /**
     * Returns the general status icon of the given MetaContact. Detects the
     * status using the priority status table. The priority is defined on
     * the "availability" factor and here the most "available" status is
     * returned.
     *
     * @return PresenceStatus The most "available" status from all
     * sub-contact statuses.
     */
    public ImageIcon getStatusIcon()
    {
        PresenceStatus status = null;
        Iterator<Contact> i = metaContact.getContacts();
        while (i.hasNext()) {
            Contact protoContact = i.next();
            PresenceStatus contactStatus = protoContact.getPresenceStatus();

            if (status == null)
                status = contactStatus;
            else
                status = (contactStatus.compareTo(status) > 0)
                        ? contactStatus
                        : status;
        }

        if (status != null)
            return new ImageIcon(Constants.getStatusIcon(status));

        return null;
    }

    /**
     * Returns the parent <tt>UIGroup</tt>.
     * @return the parent <tt>UIGroup</tt>
     */
    public UIGroup getParentGroup()
    {
        return parentUIGroup;
    }

    /**
     * Sets the given <tt>parentGroup</tt> to be the parent <tt>UIGroup</tt>
     * of this <tt>MetaUIContact</tt>.
     * @param parentGroup the parent <tt>UIGroup</tt> to set
     */
    public void setParentGroup(UIGroup parentGroup)
    {
        parentUIGroup = parentGroup;
    }

    /**
     * Returns the default <tt>ContactDetail</tt> to use for any operations
     * depending to the given <tt>OperationSet</tt> class.
     * @param opSetClass the <tt>OperationSet</tt> class we're interested in
     * @return the default <tt>ContactDetail</tt> to use for any operations
     * depending to the given <tt>OperationSet</tt> class
     */
    public UIContactDetail getDefaultContactDetail(
        Class<? extends OperationSet> opSetClass)
    {
        List<UIContactDetail> details
            = getContactDetailsForOperationSet(opSetClass);

        return (details != null && !details.isEmpty()) ? details.get(0) : null;
    }

    /**
     * Returns a list of <tt>UIContactDetail</tt>s supporting the given
     * <tt>OperationSet</tt> class.
     * @param opSetClass the <tt>OperationSet</tt> class we're interested in
     * @return a list of <tt>UIContactDetail</tt>s supporting the given
     * <tt>OperationSet</tt> class
     */
    public List<UIContactDetail> getContactDetailsForOperationSet(
        Class<? extends OperationSet> opSetClass)
    {
        List<UIContactDetail> resultList
            = new LinkedList<UIContactDetail>();

        Iterator<Contact> contacts
            = metaContact.getContactsForOperationSet(opSetClass).iterator();

        while (contacts.hasNext())
        {
            resultList.add(new MetaContactDetail(contacts.next()));
        }
        return resultList;
    }

    /**
     * Returns a list of all <tt>UIContactDetail</tt>s within this
     * <tt>UIContact</tt>.
     *
     * @return a list of all <tt>UIContactDetail</tt>s within this
     * <tt>UIContact</tt>
     */
    public List<UIContactDetail> getContactDetails()
    {
        List<UIContactDetail> resultList
            = new LinkedList<UIContactDetail>();

        Iterator<Contact> contacts = metaContact.getContacts();

        while (contacts.hasNext())
        {
            resultList.add(new MetaContactDetail(contacts.next()));
        }
        return resultList;
    }

    /**
     * Gets the avatar of a specific <tt>MetaContact</tt> in the form of an
     * <tt>ImageIcon</tt> value.
     *
     * @param isSelected indicates if the contact is selected
     * @param width the desired icon width
     * @param height the desired icon height
     * @return an <tt>ImageIcon</tt> which represents the avatar of the
     * specified <tt>MetaContact</tt>
     */
    public ImageIcon getAvatar(
        boolean isSelected, int width, int height)
    {
        byte[] avatarBytes = metaContact.getAvatar(true);

        // If there's no avatar we have nothing more to do here.
        if((avatarBytes == null) || (avatarBytes.length <= 0))
        {
            if (!subscribed)
            {
                return ImageUtils.getScaledRoundedIcon(
                    ImageLoader.getImage(ImageLoader.UNAUTHORIZED_CONTACT_PHOTO),
                    width, height);
            }

            return null;
        }

        // If the cell is selected we return a zoomed version of the avatar
        // image.
        if (isSelected)
            return ImageUtils.getScaledRoundedIcon(avatarBytes, width, height);

        // In any other case try to get the avatar from the cache.
        Object[] avatarCache
            = (Object[]) metaContact.getData(AVATAR_DATA_KEY);
        ImageIcon avatar = null;

        if ((avatarCache != null) && (avatarCache[0] == avatarBytes))
            avatar = (ImageIcon) avatarCache[1];

        // If the avatar isn't available or it's not up-to-date, create it.
        if (avatar == null)
        {
            avatar = ImageUtils.getScaledRoundedIcon(avatarBytes, width, height);
        }

        // Cache the avatar in case it has changed.
        if (avatarCache == null)
        {
            if (avatar != null)
                metaContact.setData(
                    AVATAR_DATA_KEY,
                    new Object[] { avatarBytes, avatar });
        }
        else
        {
            avatarCache[0] = avatarBytes;
            avatarCache[1] = avatar;
        }

        return avatar;
    }

    /**
     * Returns the display details for the underlying <tt>MetaContact</tt>.
     * @return the display details for the underlying <tt>MetaContact</tt>
     */
    public String getDisplayDetails()
    {
        String displayDetails = null;

        Iterator<Contact> protoContacts = metaContact.getContacts();

        String subscriptionDetails = null;

        while (protoContacts.hasNext())
        {
            Contact protoContact = protoContacts.next();

            OperationSetExtendedAuthorizations authOpSet
                = protoContact.getProtocolProvider()
                    .getOperationSet(OperationSetExtendedAuthorizations.class);

            if (authOpSet != null
                && authOpSet.getSubscriptionStatus(protoContact) != null
                && !authOpSet.getSubscriptionStatus(protoContact)
                    .equals(SubscriptionStatus.Subscribed))
            {
                SubscriptionStatus status
                    = authOpSet.getSubscriptionStatus(protoContact);

                if (status.equals(SubscriptionStatus.SubscriptionPending))
                    subscriptionDetails = GuiActivator.getResources()
                        .getI18NString("service.gui.WAITING_AUTHORIZATION");
                else if (status.equals(SubscriptionStatus.NotSubscribed))
                    subscriptionDetails = GuiActivator.getResources()
                        .getI18NString("service.gui.NOT_AUTHORIZED");
            }
            else if (protoContact.getStatusMessage() != null
                && protoContact.getStatusMessage().length() > 0)
            {
                subscribed = true;
                displayDetails = protoContact.getStatusMessage();
                break;
            }
            else
            {
                subscribed = true;
            }
        }

        if ((displayDetails == null
            || displayDetails.length() <= 0)
            && !subscribed
            && subscriptionDetails != null
            && subscriptionDetails.length() > 0)
            displayDetails = subscriptionDetails;

        return displayDetails;
    }

    /**
     * Returns the tool tip opened on mouse over.
     * @return the tool tip opened on mouse over
     */
    public ExtendedTooltip getToolTip()
    {
        ExtendedTooltip tip = new ExtendedTooltip(true);

        byte[] avatarImage = metaContact.getAvatar();

        if (avatarImage != null && avatarImage.length > 0)
            tip.setImage(new ImageIcon(avatarImage));

        tip.setTitle(metaContact.getDisplayName());

        loadTooltip(tip);

        return tip;
    }

    /**
     * Loads the tooltip with the data for current metacontact.
     * @param tip the tooltip to fill.
     */
    private void loadTooltip(final ExtendedTooltip tip)
    {
        Iterator<Contact> i = metaContact.getContacts();

        String statusMessage = null;
        Contact protocolContact;
        boolean isLoading = false;
        while (i.hasNext())
        {
            protocolContact = i.next();

            // Set the first found status message.
            if (statusMessage == null
                && protocolContact.getStatusMessage() != null
                && protocolContact.getStatusMessage().length() > 0)
                statusMessage = protocolContact.getStatusMessage();

            if(ConfigurationManager.isHideAccountStatusSelectorsEnabled())
                break;

            ImageIcon protocolStatusIcon
                = ImageLoader.getIndexedProtocolIcon(
                        ImageUtils.getBytesInImage(
                            protocolContact.getPresenceStatus().getStatusIcon()),
                        protocolContact.getProtocolProvider());

            String contactAddress = protocolContact.getAddress();
            //String statusMessage = protocolContact.getStatusMessage();

            tip.addLine(protocolStatusIcon, contactAddress);

            OperationSetServerStoredContactInfo infoOpSet =
                protocolContact.getProtocolProvider().getOperationSet(
                    OperationSetServerStoredContactInfo.class);

            if(infoOpSet != null
                && protocolContact.getProtocolProvider().isRegistered())
            {
                Iterator<GenericDetail> details =
                    infoOpSet.requestAllDetailsForContact(protocolContact,
                        new OperationSetServerStoredContactInfo
                                .DetailsResponseListener()
                        {
                            public void detailsRetrieved(
                                Iterator<GenericDetail> details)
                            {
                                // remove previously shown information
                                // as it contains "Loading..." text
                                tip.removeAllLines();

                                // load it again
                                loadTooltip(tip);
                            }
                        });

                if(details != null)
                    fillTooltipLines(tip, details);
                else
                    isLoading = true;
            }
        }

        if(isLoading)
            tip.addLine(null,
                        GuiActivator.getResources()
                            .getI18NString("service.gui.LOADING"));

        if (statusMessage != null)
            tip.setBottomText(statusMessage);
    }

    /**
     * Fills the tooltip with details.
     * @param tip the tooltip to fill
     * @param details the available details.
     */
    private void fillTooltipLines(ExtendedTooltip tip,
                                  Iterator<GenericDetail> details)
    {
        while(details.hasNext())
        {
            GenericDetail d = details.next();
            if(d instanceof PhoneNumberDetail &&
                !(d instanceof FaxDetail) &&
                !(d instanceof PagerDetail))
            {
                PhoneNumberDetail pnd = (PhoneNumberDetail)d;
                if(pnd.getNumber() != null &&
                    pnd.getNumber().length() > 0)
                {
                    String localizedType = null;

                    if(d instanceof WorkPhoneDetail)
                    {
                        localizedType =
                            GuiActivator.getResources().
                                getI18NString(
                                    "service.gui.WORK_PHONE");
                    }
                    else if(d instanceof MobilePhoneDetail)
                    {
                        localizedType =
                            GuiActivator.getResources().
                                getI18NString(
                                    "service.gui.MOBILE_PHONE");
                    }
                    else
                    {
                        localizedType =
                            GuiActivator.getResources().
                                getI18NString(
                                    "service.gui.PHONE");
                    }

                    tip.addLine(null, (pnd.getNumber() +
                        " (" + localizedType + ")"));
                }
             }
        }

        tip.revalidate();
        tip.repaint();
    }

    /**
     * Returns the corresponding <tt>ContactNode</tt> in the contact list
     * component data model.
     * @return the corresponding <tt>ContactNode</tt>
     */
    public ContactNode getContactNode()
    {
        return contactNode;
    }

    /**
     * Sets the corresponding <tt>ContactNode</tt>.
     * @param contactNode the corresponding <tt>ContactNode</tt> in the contact
     * list component data model
     */
    public void setContactNode(ContactNode contactNode)
    {
        this.contactNode = contactNode;
        if (contactNode == null)
            MetaContactListSource.removeUIContact(metaContact);
    }

    /**
     * Initializes all search strings for this <tt>MetaUIGroup</tt>.
     */
    private void initSearchStrings()
    {
        searchStrings.add(metaContact.getDisplayName());

        Iterator<Contact> contacts = metaContact.getContacts();
        while (contacts.hasNext())
        {
            Contact contact = contacts.next();

            searchStrings.add(contact.getDisplayName());
            searchStrings.add(contact.getAddress());
        }
    }

    /**
     * The implementation of the <tt>UIContactDetail</tt> interface for the
     * <tt>MetaContactListService</tt>.
     */
    private class MetaContactDetail
        extends UIContactDetailImpl
    {
        /**
         * The underlying protocol contact.
         */
        private Contact contact;

        /**
         * Creates an instance of <tt>MetaContactDetail</tt> by specifying the
         * underlying protocol <tt>Contact</tt>.
         *
         * @param contact the protocol contact, on which this implementation
         * is based
         */
        public MetaContactDetail(Contact contact)
        {
            supercontact.getAddress(),
                    contact.getDisplayName(),
                    new ImageIcon(contact.getPresenceStatus().getStatusIcon()),
                    contact);

            this.contact = contact;

            ProtocolProviderService parentProvider
                = contact.getProtocolProvider();

            Iterator<Class<? extends OperationSet>> opSetClasses
                = parentProvider.getSupportedOperationSetClasses().iterator();

            while (opSetClasses.hasNext())
            {
                Class<? extends OperationSet> opSetClass = opSetClasses.next();

                addPreferredProtocolProvider(opSetClass, parentProvider);
                addPreferredProtocol(opSetClass,
                                    parentProvider.getProtocolName());
            }
        }

        /**
         * Returns the presence status of the underlying protocol
         * <tt>Contact</tt>.
         * @return the presence status of the underlying protocol
         * <tt>Contact</tt>
         */
        public PresenceStatus getPresenceStatus()
        {
            return contact.getPresenceStatus();
        }
    }

    /**
     * Returns the right button menu component.
     * @return the right button menu component
     */
    public JPopupMenu getRightButtonMenu()
    {
        return new MetaContactRightButtonMenu(metaContact);
    }

    /**
     * Returns all custom action buttons for this meta contact.
     *
     * @return a list of all custom action buttons for this meta contact
     */
    public Collection<SIPCommButton> getContactCustomActionButtons()
    {
        return MetaContactListSource.getContactCustomActionButtons(this);
    }
}
TOP

Related Classes of net.java.sip.communicator.impl.gui.main.contactlist.contactsource.MetaUIContact$MetaContactDetail

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.