Work on the meta contact list (read support).

cusax-fix
Emil Ivov 21 years ago
parent 084ce0357c
commit 88184fac97

@ -1,42 +1,53 @@
/*
* SIP Communicator, 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.contactlist;
import java.util.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* A Default implementation of a MetaContactGroup. Note that this implementation
* is only meant to be used for non-root contact groups and can only contain
* contacts. All subgroup retrieving methods would returns null/0 values.
* Root contact groups are to be represented by the RootMetaContactGroupImpl.
* <p>
* A straightforward implementation of the meta contact group.
*
* @author Emil Ivov
*/
public class MetaContactGroupImpl
implements MetaContactGroup
{
private static final Logger logger =
Logger.getLogger(MetaContactGroupImpl.class);
/**
* All child contacts for this group.
* All the subgroups that this group contains.
*/
private Vector childContacts = new Vector();
private Vector subgroups = new Vector();
/**
* An empty list that we'll be using in order to return an empty iterator
* of the (non-existing) sub groups.
* A list containing all child contacts.
*/
private final List dummySubgroupsList = new LinkedList();
private Vector childContacts = new Vector();
/**
* All protocol specific contact groups encapsulated by this
* <tt>MetaContactGoup</tt>.
* A list of the contact groups encapsulated by this MetaContactGroup
*/
private Hashtable protoGroups = new Hashtable();
private Vector protoGroups = new Vector();
/**
* The name of the group (fixed for root groups since it won't show).
*/
private String groupName = null;
protected MetaContactGroupImpl(String groupName)
/**
* Creates an instance of the root meta contact group.
*
* @param groupName the name of the group to create
*/
MetaContactGroupImpl(String groupName)
{
this.groupName = groupName;
}
@ -44,8 +55,8 @@ protected MetaContactGroupImpl(String groupName)
/**
* Determines whether or not this group can contain subgroups.
*
* @return Always false since only the root contact group may contain sub
* groups in our implementation.
* @return always <tt>true</tt> since this is the root contact group
* and in our imple it can only contain groups.
*/
public boolean canContainSubgroups()
{
@ -53,22 +64,31 @@ public boolean canContainSubgroups()
}
/**
* Returns the number of <tt>MetaContact</tt>s that this group contains
* Returns the number of <tt>MetaContact</tt>s that this group contains.
* <p>
* @return an int indicating the number of MetaContact-s that this group
* contains.
* @return the number of <tt>MetaContact</tt>s that this group contains.
*/
public int countChildContacts()
{
return childContacts.size();
}
/**
* Returns the number of subgroups that this <tt>MetaContactGroup</tt>
* contains.
*
* @return an int indicating the number of subgroups in this group.
*/
public int countSubgroups()
{
return subgroups.size();
}
/**
* Returns a <tt>java.util.Iterator</tt> over the <tt>MetaContact</tt>s
* contained in this <tt>MetaContactGroup</tt>.
*
* @return a <tt>java.util.Iterator</tt> over the <tt>MetaContacts</tt>
* in this group.
* @return a <tt>java.util.Iterator</tt> over an empty contacts list.
*/
public Iterator getChildContacts()
{
@ -96,6 +116,191 @@ public MetaContact getMetaContact(String metaContactID)
return null;
}
/**
* Returns a meta contact, a child of this group or its subgroups, that
* has the specified metaUID. If no such meta contact exists, the method
* would return null.
*
* @param metaUID the Meta UID of the contact we're looking for.
* @return the MetaContact with the specified UID or null if no such
* contact exists.
*/
public MetaContactImpl findMetaContactByMetaUID(String metaUID)
{
//first go through the contacts that are direct children of this method.
Iterator contactsIter = getChildContacts();
while(contactsIter.hasNext())
{
MetaContactImpl mContact = (MetaContactImpl)contactsIter.next();
if( mContact.getMetaUID().equals(metaUID) )
return mContact;
}
//if we didn't find it here, let's try in the subougroups
Iterator groupsIter = getSubgroups();
while( groupsIter.hasNext() )
{
MetaContactGroupImpl mGroup = (MetaContactGroupImpl)groupsIter.next();
MetaContactImpl mContact = mGroup.findMetaContactByMetaUID(metaUID);
if (mContact != null)
return mContact;
}
return null;
}
/**
* Returns an iterator over all the protocol specific groups that this
* contact group represents.
* @return an Iterator over the protocol specific groups that this group
* represents.
*/
public Iterator getContactGroups()
{
return this.protoGroups.iterator();
}
/**
* Returns a contact group encapsulated by this meta contact group, having
* the specified groupName and coming from the indicated ownerProvider.
*
* @param groupName the name of the contact group who we're looking for.
* @param ownerProvider a reference to the ProtocolProviderService that
* the contact we're looking for belongs to.
* @return a reference to a <tt>ContactGroup</tt>, encapsulated by this
* MetaContactGroup, carrying the specified name and originating from the
* specified ownerProvider or null if no such contact group was found.
*/
public ContactGroup getContactGroup(String groupName,
ProtocolProviderService ownerProvider)
{
Iterator encapsulatedGroups = getContactGroups();
while (encapsulatedGroups.hasNext())
{
ContactGroup group = (ContactGroup)encapsulatedGroups.next();
if (group.getGroupName().equals(groupName)
&& group.getProtocolProvider() == ownerProvider)
{
return group;
}
}
return null;
}
/**
* Returns all protocol specific ContactGroups, encapsulated by this
* MetaContactGroup and coming from the indicated ProtocolProviderService.
* If none of the contacts encapsulated by this MetaContact is originating
* from the specified provider then an empty iterator is returned.
* <p>
* @param provider a reference to the <tt>ProtocolProviderService</tt>
* whose ContactGroups we'd like to get.
* @return an <tt>Iterator</tt> over all contacts encapsulated in this
* <tt>MetaContact</tt> and originating from the specified provider.
*/
public Iterator getContactGroupsForProvider(
ProtocolProviderService provider)
{
Iterator encapsulatedGroups = getContactGroups();
LinkedList protoGroups = new LinkedList();
while(encapsulatedGroups.hasNext())
{
ContactGroup group = (ContactGroup)encapsulatedGroups.next();
if(group.getProtocolProvider() == provider)
protoGroups.add(group);
}
return protoGroups.iterator();
}
/**
* Returns a meta contact, a child of this group or its subgroups, that
* has the specified protocol specific contact. If no such meta contact
* exists, the method would return null.
*
* @param protoContact the protocol specific contact whos meta contact we're
* looking for.
* @return the MetaContactImpl that contains the specified protocol specific
* contact.
*/
public MetaContactImpl findMetaContactByContact(Contact protoContact)
{
//first go through the contacts that are direct children of this method.
Iterator contactsIter = getChildContacts();
while(contactsIter.hasNext())
{
MetaContactImpl mContact = (MetaContactImpl)contactsIter.next();
Contact storedProtoContact = mContact.getContact(
protoContact.getAddress(), protoContact.getProtocolProvider());
if( storedProtoContact != null)
return mContact;
}
//if we didn't find it here, let's try in the subougroups
Iterator groupsIter = getSubgroups();
while( groupsIter.hasNext() )
{
MetaContactGroupImpl mGroup = (MetaContactGroupImpl)groupsIter.next();
MetaContactImpl mContact = mGroup.findMetaContactByContact(
protoContact);
if (mContact != null)
return mContact;
}
return null;
}
/**
* Returns a meta contact group, encapsulated by this group or its
* subgroups, that has the specified protocol specific contact. If no such
* meta contact group exists, the method would return null.
*
* @param protoContactGroup the protocol specific contact group whose meta
* contact group we're looking for.
* @return the MetaContactImpl that contains the specified protocol specific
* contact.
*/
public MetaContactGroupImpl findMetaContactGroupByContactGroup(
ContactGroup protoContactGroup)
{
//first check here, in this meta group
if(protoGroups.contains(protoContactGroup))
return this;
//if we didn't find it here, let's try in the subougroups
Iterator groupsIter = getSubgroups();
while( groupsIter.hasNext() )
{
MetaContactGroupImpl mGroup = (MetaContactGroupImpl)groupsIter.next();
MetaContactGroupImpl foundMetaContactGroup = mGroup
.findMetaContactGroupByContactGroup( protoContactGroup );
if (foundMetaContactGroup != null)
return foundMetaContactGroup;
}
return null;
}
/**
* Returns the meta contact on the specified index.
*
@ -111,76 +316,79 @@ public MetaContact getMetaContact(int index) throws
}
/**
* Returns the <tt>MetaContactGroup</tt> with the specified index.
*
* @param index the index of the group to return.
* @return always null since only the root contact group may contain sub
* gorups in our implementation.
* @throws IndexOutOfBoundsException if <tt>index</tt> is not a valid
* index.
* Adds the specified <tt>metaContact</tt> to ths local list of child
* contacts.
* @param metaContact the <tt>MetaContact</tt> to add in the local vector.
*/
public MetaContactGroup getMetaContactSubgroup(int index) throws
IndexOutOfBoundsException
void addMetaContact(MetaContact metaContact)
{
return null;
this.childContacts.add(metaContact);
}
/**
* Returns the name of this group.
* @return a String containing the name of this group.
* Removes the specified <tt>metaContact</tt> from the local list of
* contacts.
* @param metaContact the <tt>MetaContact</tt>
*/
public String getGroupName()
void removeMetaContact(MetaContact metaContact)
{
return groupName;
this.childContacts.remove( metaContact );
}
/**
* Returns the <tt>MetaContactGroup</tt> with the specified name.
*
* @param groupName the name of the group to return.
* @return always null since only the root contact group may contain
* subgroups in our implementation.
* Returns the <tt>MetaContactGroup</tt> with the specified index.
* <p>
* @param index the index of the group to return.
* @return the <tt>MetaContactGroup</tt> with the specified index. <p>
* @throws IndexOutOfBoundsException if <tt>index</tt> is not a valid
* index.
*/
public MetaContactGroup getMetaContactSubgroup(String groupName)
public MetaContactGroup getMetaContactSubgroup(int index) throws
IndexOutOfBoundsException
{
return null;
return (MetaContactGroup)subgroups.get(index);
}
/**
* Returns the number of subgroups that this <tt>MetaContactGroup</tt>
* contains.
* Returns the <tt>MetaContactGroup</tt> with the specified name.
*
* @return always 0 since only the root contact group may contain subgroups
* in our implementation.
* @param groupName the name of the group to return.
* @return the <tt>MetaContactGroup</tt> with the specified name or null
* if no such group exists.
*/
public int countSubgroups()
public MetaContactGroup getMetaContactSubgroup(String groupName)
{
return 0;
Iterator groupsIter = getSubgroups();
while(groupsIter.hasNext())
{
MetaContactGroup mcGroup = (MetaContactGroup)groupsIter.next();
if(mcGroup.getGroupName().equals(groupName))
return mcGroup;
}
return null;
}
/**
* Returns an <tt>java.util.Iterator</tt> over the sub groups that this
* <tt>MetaContactGroup</tt> contains.
*
* @return an Iterator over the empty subgroups list.
* <p>
* @return a <tt>java.util.Iterator</tt> containing all subgroups.
*/
public Iterator getSubgroups()
{
return dummySubgroupsList.iterator();
return subgroups.iterator();
}
/**
* Adds the specified <tt>group</tt> to the list of protocol specific
* groups merged by this MetaContactGroup.
* @param owner the ProtocolProviderService where the specified group came
* from.
* @param group the <tt>ContactGroup</tt> to add merge into this
* MetaContactGroup.
* Returns the name of this group.
* @return a String containing the name of this group.
*/
public void addProtoGroup(ProtocolProviderService owner,
ContactGroup group)
public String getGroupName()
{
this.protoGroups.put(owner, group);
return groupName;
}
/**
@ -188,12 +396,22 @@ public void addProtoGroup(ProtocolProviderService owner,
* contains (may turn out to be a relatively long string).
* @return a String representing this group and its child contacts.
*/
public String toString()
{
StringBuffer buff = new StringBuffer("MetaContactGroup.");
public String toString()
{
StringBuffer buff = new StringBuffer(getGroupName());
buff.append(".subGroups=" + countSubgroups() + ":\n");
Iterator subGroups = getSubgroups();
while (subGroups.hasNext())
{
MetaContactGroupImpl group = (MetaContactGroupImpl)subGroups.next();
buff.append(group.toString());
if (subGroups.hasNext())
buff.append("\n");
}
buff.append(getGroupName());
buff.append(", childContacts="+countChildContacts()+":[");
buff.append("\nRootChildContacts="+countChildContacts()+":[");
Iterator contacts = getChildContacts();
while (contacts.hasNext())
@ -207,38 +425,57 @@ public String toString()
}
/**
* Verifies whether a protocol specific ContactGroup with the specified
* name and originating from the specified provider is encapsulated by this
* MetaContactGroup and if so returns it.
* <p>
* <p>
* @return the <tt>ContactGroup</tt> with the specified name and provider
* or null if no such group exists.
* Addes the specified group to the list of protocol specific groups
* that we're encapsulating in this meta contact group.
* @param protoGroup the root to add to the groups merged in this meta contact
* group.
*/
// ContactGroup findContactGroup(String groupName, )
// {
// /** @todo implement findContactGroup() */
// }
void addProtoGroup( ContactGroup protoGroup)
{
protoGroups.add(protoGroup);
}
/**
* Adds the specified <tt>metaContact</tt> to ths local list of child
* contacts.
* @param metaContact the <tt>MetaContact</tt> to add in the local vector.
* Removes the specified group from the list of protocol specific groups
* that we're encapsulating in this meta contact group.
* @param protoGroup the group to remove from the groups merged in this meta
* contact group.
*/
void addMetaContact(MetaContact metaContact)
void removeProtoGroup( ContactGroup protoGroup)
{
this.childContacts.add(metaContact);
protoGroups.remove(protoGroup);
}
/**
* Removes the specified <tt>metaContact</tt> from the local list of
* contacts.
* @param metaContact the <tt>MetaContact</tt>
* Adds the specified meta group to the subgroups of this one.
* @param subgroup the MetaContactGroup to register as a subgroup to this
* root meta contact group.
*/
void removeMetaContact(MetaContact metaContact)
void addSubgroup(MetaContactGroup subgroup)
{
this.childContacts.remove( metaContact );
logger.trace("Adding subgroup " + subgroup.getGroupName()
+ " to" + getGroupName());
this.subgroups.add(subgroup);
}
/**
* Removes the meta contact group with the specified index.
* @param index the index of the group to remove.
* @return the <tt>MetaContactGroup</tt> that has just been removed.
*/
MetaContactGroupImpl removeSubgroup(int index)
{
return (MetaContactGroupImpl)subgroups.remove(index);
}
/**
* Removes the specified group from the list of groups in this list.
* @param group the <tt>MetaContactGroup</tt> to remove.
* @return true if the group has been successfully removed and false
* otherwise.
*/
boolean removeSubgroup(MetaContactGroup group)
{
return subgroups.remove(group);
}
}

@ -1,3 +1,9 @@
/*
* SIP Communicator, 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.contactlist;
import java.util.*;
@ -57,19 +63,48 @@ public int getContactCount()
* @return a <tt>Contact</tt> encapsulated in this <tt>MetaContact</tt>
* and originating from the specified provider.
*/
public Contact getContactForProvider(ProtocolProviderService provider)
public Iterator getContactsForProvider(ProtocolProviderService provider)
{
Iterator contactsIter = protoContacts.iterator();
LinkedList providerContacts = new LinkedList();
while (contactsIter.hasNext())
{
Contact contact = (Contact)contactsIter.next();
if(contact.getProtocolProvider() == provider)
providerContacts.add( contact );
}
return providerContacts.iterator();
}
/**
* Returns a contact encapsulated by this meta contact, having the specified
* contactAddress and coming from the indicated ownerProvider.
* @param contactAddress the address of the contact who we're looking for.
* @param ownerProvider a reference to the ProtocolProviderService that
* the contact we're looking for belongs to.
* @return a reference to a <tt>Contact</tt>, encapsulated by this
* MetaContact, carrying the specified address and originating from the
* specified ownerProvider or null if no such contact exists..
*/
public Contact getContact(String contactAddress,
ProtocolProviderService ownerProvider)
{
Iterator contactsIter = protoContacts.iterator();
while (contactsIter.hasNext())
{
Contact contact = (Contact)contactsIter.next();
if( contact.getProtocolProvider() == ownerProvider
&& contact.getAddress().equals(contactAddress))
return contact;
}
return null;
}
/**
@ -171,4 +206,33 @@ boolean removeProtoContact(Contact contact)
}
/**
* Removes all proto contacts that belong to the specified provider.
*
* @param contact the contact to remove
*
* @return true if this <tt>MetaContact</tt> was modified and false
* otherwise.
*/
boolean removeContactsForProvider(ProtocolProviderService provider)
{
boolean modified = false;
Iterator contactsIter = protoContacts.iterator();
while(contactsIter.hasNext())
{
Contact contact = (Contact)contactsIter.next();
if (contact.getProtocolProvider() == provider)
{
contactsIter.remove();
modified = true;
}
}
return modified;
}
}

@ -6,47 +6,21 @@
*/
package net.java.sip.communicator.impl.contactlist;
import java.util.Iterator;
import java.util.Vector;
import net.java.sip.communicator.service.contactlist.MetaContact;
import net.java.sip.communicator.service.contactlist.MetaContactGroup;
import net.java.sip.communicator.service.contactlist.MetaContactListException;
import net.java.sip.communicator.service.contactlist.MetaContactListService;
import net.java.sip.communicator.service.contactlist.event.MetaContactEvent;
import net.java.sip.communicator.service.contactlist.event.MetaContactGroupEvent;
import net.java.sip.communicator.service.contactlist.event.MetaContactListListener;
import net.java.sip.communicator.service.protocol.Contact;
import net.java.sip.communicator.service.protocol.ContactGroup;
import net.java.sip.communicator.service.protocol.OperationSetPersistentPresence;
import net.java.sip.communicator.service.protocol.ProtocolProviderService;
import net.java.sip.communicator.service.protocol.event.ServerStoredGroupEvent;
import net.java.sip.communicator.service.protocol.event.ServerStoredGroupListener;
import net.java.sip.communicator.service.protocol.event.SubscriptionEvent;
import net.java.sip.communicator.service.protocol.event.SubscriptionListener;
import net.java.sip.communicator.util.Logger;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import java.util.*;
import org.osgi.framework.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.contactlist.event.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* An almost dummy implementation of the MetaContactListService that would only
* connect to protocol service providers and build its contact list accordingly
* only basing itself on the contact list stored by the icq service.
* <p>
* In its current form, the purpose of this implementation is to provide a tool
* for retrieving any contact list so that other modules such as the user
* interface may use it.
* An implementation of the MetaContactListService that would connect to
* protocol service providers and build its contact list accordingly
* basing itself on the contact list stored by the various protocol provider
* services and the contact list instance saved on the hard disk.
* <p>
* Because of its experimental-patch nature, the implementa would only function
* properly if the underlying service providers have already been loaded at the
* time this one gets started.
*
* @todo might be a good idea to say that the implementation does not support
* subgroups.
*
* @author Emil Ivov
*/
@ -57,12 +31,6 @@ public class MetaContactListServiceImpl
private static final Logger logger = Logger
.getLogger(MetaContactListServiceImpl.class);
/**
* Listeners interested in events dispatched upond modification of the meta
* contact list.
*/
private Vector contactListListeners = new Vector();
/**
* The BundleContext that we got from the OSGI bus.
*/
@ -76,8 +44,13 @@ public class MetaContactListServiceImpl
/**
* The root of the meta contact list.
*/
RootMetaContactGroupImpl rootMetaGroup = new RootMetaContactGroupImpl();
MetaContactGroupImpl rootMetaGroup
= new MetaContactGroupImpl("RootMetaContactGroup");
/**
* Listeners interested in events dispatched upond modification of the meta
* contact list.
*/
private Vector metaContactListListeners = new Vector();
/**
@ -107,12 +80,11 @@ public MetaContactListServiceImpl() {
* them.
* <p>
*
* @param bc
* the currently valid osgi bundle context.
* @param bc the currently valid osgi bundle context.
*/
public void start(BundleContext bc) {
logger
.debug("Starting the meta contact list implementation.");
public void start(BundleContext bc)
{
logger.debug("Starting the meta contact list implementation.");
this.bundleContext = bc;
// start listening for newly register or removed protocol providers
@ -152,12 +124,12 @@ public void start(BundleContext bc) {
* Adds a listener for <tt>MetaContactListChangeEvent</tt>s posted after
* the tree changes.
*
* @param l
* the listener to add
* @param l the listener to add
*/
public void addContactListListener(
MetaContactListListener l) {
synchronized (metaContactListListeners) {
public void addContactListListener(MetaContactListListener l)
{
synchronized (metaContactListListeners)
{
this.metaContactListListeners.add(l);
}
}
@ -339,10 +311,70 @@ public void removeMetaContact(MetaContact metaContact)
*/
public void removeMetaContactGroup(
MetaContactGroup groupToRemove)
throws MetaContactListException {
/** @todo implement removeMetaContactGroup() */
System.out
.println("@todo implement removeMetaContactGroup()");
throws MetaContactListException
{
/** @todo implement removeMetaContactGroup() */
}
/**
* Removes the protocol specific group from the specified meta contact group
* and removes from meta contacts all proto contacts that belong to the
* same provider as the group which is being removed.
* @param metaContainer the MetaContactGroup that we'd like to remove a
* contact group from.
* @param groupToRemove the ContactGroup that we'd like removed.
* @param sourceProvider the ProtocolProvider that the contact group belongs
* to.
*/
public void removeContactGroupFromMetaContactGroup(
MetaContactGroupImpl metaContainer,
ContactGroup groupToRemove,
ProtocolProviderService sourceProvider)
{
metaContainer.removeProtoGroup(groupToRemove);
//go through all meta contacts and remove all contats that belong to the
//same provider and are therefore children of the group that is being
//removed
removeAllContactsForProvider(metaContainer, sourceProvider);
fireMetaContactGroupEvent( metaContainer, sourceProvider,
MetaContactGroupEvent.CONTACT_GROUP_REMOVED_FROM_META_GROUP);
}
/**
* Goes through the specified group and removes from all meta contacts,
* protocol specific contacts belonging to the specified provider
*
* @param parent the MetaContactGroup whose children we should go through
* @param sourceProvider the ProtocolProviderService whose contacts we'd
* like deleted from <tt>parent</tt>.
*/
private void removeAllContactsForProvider(
MetaContactGroupImpl parent, ProtocolProviderService sourceProvider)
{
Iterator childrenContactsIter = parent.getChildContacts();
//first go through all direct children.
while(childrenContactsIter.hasNext())
{
MetaContactImpl child = (MetaContactImpl)childrenContactsIter.next();
child.removeContactsForProvider(sourceProvider);
//if this was the last proto contact inside this meta contact,
//then remove the meta contact as well.
int eventID = MetaContactEvent.PROTO_CONTACT_REMOVED;
if (child.getContactCount() == 0){
parent.removeMetaContact(child);
eventID = MetaContactEvent.META_CONTACT_REMOVED;
}
fireMetaContactEvent(child, sourceProvider, parent, eventID);
}
}
/**
@ -355,9 +387,9 @@ public void removeMetaContactGroup(
* for.
*/
public MetaContactGroup findMetaContactGroupByContactGroup
(ContactGroup contactGroup) {
/** @todo implement findMetaContactByContact() */
return null;
(ContactGroup contactGroup)
{
return rootMetaGroup.findMetaContactGroupByContactGroup(contactGroup);
}
/**
@ -369,13 +401,11 @@ public void removeMetaContactGroup(
*
* @return the MetaContact containing the speicified contact or null if no
* such contact is present in this contact list.
* @param contact
* the protocol specific <tt>contact</tt> that we're looking
* for.
* @param contact the protocol specific <tt>contact</tt> that we're looking
* for.
*/
public MetaContact findMetaContactByContact(Contact contact) {
/** @todo implement findMetaContactByContact() */
return null;
return rootMetaGroup.findMetaContactByContact(contact);
}
/**
@ -386,9 +416,9 @@ public MetaContact findMetaContactByContact(Contact contact) {
* @return the MetaContact with the speicified string identifier or null if
* no such meta contact was found.
*/
public MetaContact findMetaContactByID(String metaContactID) {
/** @todo implement findMetaContactByID() */
return null;
public MetaContact findMetaContactByMetaUID(String metaContactID) {
return rootMetaGroup.findMetaContactByMetaUID(metaContactID);
}
/**
@ -399,29 +429,49 @@ public MetaContact findMetaContactByID(String metaContactID) {
* @param presenceOpSet
* the presence operation set whose contact list we'd like to
* synchronize with the local contact list.
* @param provider
* the provider that the operation set belongs to.
*/
private void synchronizeOpSetWithLocalContactList(
ProtocolProviderService provider,
OperationSetPersistentPresence presenceOpSet)
{
ContactGroup rootProtoGroup = presenceOpSet
.getServerStoredContactListRoot();
logger.trace("subgroups: "
+ rootProtoGroup.countSubGroups());
+ rootProtoGroup.countSubgroups());
logger.trace("child contacts: "
+ rootProtoGroup.countContacts());
addContactGroupToMetaGroup(rootProtoGroup, rootMetaGroup, true);
presenceOpSet
.addSubsciptionListener(new ContactListSubscriptionListener());
presenceOpSet
.addServerStoredGroupChangeListener(new ContactListGroupListener());
}
/**
* Creates meta contacts and meta contact groups for all childredn of the
* specified <tt>contactGroup</tt> and adds them to <tt>metaGroup</tt>
* @param protoGroup the <tt>ContactGroup</tt> to add.
* <p>
* @param metaGroup the <tt>MetaContactGroup</tt> where <tt>ContactGroup</tt>
* should be added.
* @param fireEvents indicates whether or not events are to be fired upon
* adding subcontacts and subgroups. When this method is called recursively,
* the parameter should will be false in order to generate a minimal number
* of events for the whole addition and not an event per every subgroup
* and child contact.
*/
private void addContactGroupToMetaGroup( ContactGroup protoGroup,
MetaContactGroupImpl metaGroup,
boolean fireEvents)
{
// first register the root group
rootMetaGroup.addProtoGroup(provider, presenceOpSet
.getServerStoredContactListRoot());
metaGroup.addProtoGroup(protoGroup);
// register subgroups and contacts
// this implementation only supports one level of groups apart from
// the root group - so let's keep this simple and do it in a nested loop
Iterator subgroupsIter = rootProtoGroup.subGroups();
Iterator subgroupsIter = protoGroup.subGroups();
while (subgroupsIter.hasNext()) {
ContactGroup group = (ContactGroup) subgroupsIter
@ -433,53 +483,34 @@ private void synchronizeOpSetWithLocalContactList(
MetaContactGroupImpl newMetaGroup = new MetaContactGroupImpl(
group.getGroupName());
newMetaGroup.addProtoGroup(provider, group);
metaGroup.addSubgroup(newMetaGroup);
Iterator contactsIter = group.contacts();
while (contactsIter.hasNext()) {
Contact contact = (Contact) contactsIter
.next();
MetaContactImpl newMetaContact = new MetaContactImpl();
addContactGroupToMetaGroup(group, newMetaGroup, false);
newMetaContact.addProtoContact(contact);
/** @todo this shouldn't be that simple */
newMetaContact.setDisplayName(contact
.getDisplayName());
newMetaGroup.addMetaContact(newMetaContact);
}
rootMetaGroup.addSubgroup(newMetaGroup);
this.fireMetaContactGroupEvent(newMetaGroup,
provider,
MetaContactEvent.METACONTACT_ADDED);
if(fireEvents)
this.fireMetaContactGroupEvent(newMetaGroup,
group.getProtocolProvider(),
MetaContactGroupEvent.META_CONTACT_GROUP_ADDED);
}
// now add all contacts, located in the root group
Iterator contactsIter = rootProtoGroup.contacts();
// now add all contacts, located in this group
Iterator contactsIter = protoGroup.contacts();
while (contactsIter.hasNext()) {
Contact contact = (Contact) contactsIter.next();
MetaContactImpl newMetaContact = new MetaContactImpl();
newMetaContact.addProtoContact(contact);
/** @todo this shouldn't be that simple */
newMetaContact.setDisplayName(contact.getDisplayName());
rootMetaGroup.addMetaContact(newMetaContact);
metaGroup.addMetaContact(newMetaContact);
this.fireMetaContactEvent(newMetaContact,
provider, rootMetaGroup,
MetaContactEvent.METACONTACT_ADDED);
}
presenceOpSet
.addSubsciptionListener(new ContactListSubscriptionListener());
if( fireEvents )
this.fireMetaContactEvent(newMetaContact,
protoGroup.getProtocolProvider(), metaGroup,
MetaContactEvent.META_CONTACT_ADDED);
presenceOpSet
.addServerStoredGroupChangeListener(new ContactListGroupListener());
}
}
/**
@ -506,7 +537,7 @@ private void handleProviderAdded(
//If we have a persistent presence op set - then retrieve its contat
//list and merge it with the local one.
if( opSetPersPresence != null ){
synchronizeOpSetWithLocalContactList(provider, opSetPersPresence);
synchronizeOpSetWithLocalContactList(opSetPersPresence);
}
else
logger.debug("Service did not have a pers. pres. op. set.");
@ -585,18 +616,31 @@ private class ContactListSubscriptionListener
implements
SubscriptionListener {
public void subscriptionCreated(SubscriptionEvent evt) {
/**
* Creates a meta contact for the source contact indicated by the
* specified SubscriptionEvent, or updates an existing one if there
* is one. The method would also generate the corresponding
* <tt>MetaContactEvent</tt>.
*
* @param evt the SubscriptionEvent that we'll be handling.
*/
public void subscriptionCreated(SubscriptionEvent evt)
{
logger.trace("Subscription created: " + evt);
MetaContactGroupImpl parentGroup =
(MetaContactGroupImpl)rootMetaGroup.getMetaContactSubgroup(evt
.getParentGroup().getGroupName());
MetaContactGroupImpl parentGroup = (MetaContactGroupImpl)
findMetaContactGroupByContactGroup( evt.getParentGroup() );
if(parentGroup == null)
{
logger.error("Received a subscription for a group that we "
+"hadn't seen before! " + evt);
return;
}
MetaContactImpl newMetaContact = new MetaContactImpl();
newMetaContact.addProtoContact(evt
.getSourceContact());
newMetaContact.addProtoContact(evt.getSourceContact());
newMetaContact.setDisplayName(evt
.getSourceContact().getDisplayName());
@ -606,11 +650,11 @@ public void subscriptionCreated(SubscriptionEvent evt) {
fireMetaContactEvent(newMetaContact,
evt.getSourceProvider(),
parentGroup,
MetaContactEvent.METACONTACT_ADDED);
MetaContactEvent.META_CONTACT_ADDED);
}
public void subscriptionFailed(SubscriptionEvent evt) {
public void subscriptionFailed(SubscriptionEvent evt) {
logger.trace("Subscription failed: " + evt);
}
@ -618,18 +662,35 @@ public void subscriptionRemoved(SubscriptionEvent evt) {
logger.trace("Subscription removed: " + evt);
MetaContact metaContact
= findMetaContactByContact(evt.getSourceContact());
MetaContactImpl metaContact = (MetaContactImpl)
findMetaContactByContact(evt.getSourceContact());
MetaContactGroup metaContactGroup
= findMetaContactGroupByContactGroup(evt.getParentGroup());
MetaContactGroupImpl metaContactGroup = (MetaContactGroupImpl)
findMetaContactGroupByContactGroup(evt.getParentGroup());
//TODO: remove contact from metacontact
metaContact.removeProtoContact(evt.getSourceContact());
fireMetaContactEvent(metaContact,
evt.getSourceProvider(),
metaContactGroup,
MetaContactEvent.METACONTACT_REMOVED);
//if this was the last protocol specific contact in this meta
//contact then remove the meta contact as well.
if(metaContact.getContactCount() == 0)
{
metaContactGroup.removeMetaContact(metaContact);
fireMetaContactEvent(metaContact,
evt.getSourceProvider(),
metaContactGroup,
MetaContactEvent.META_CONTACT_REMOVED);
}
else
{
//this was not the las proto contact so only generate the
//corresponding event.
fireMetaContactEvent(metaContact,
evt.getSourceProvider(),
metaContactGroup,
MetaContactEvent.PROTO_CONTACT_REMOVED);
}
}
}
@ -648,9 +709,7 @@ public void groupCreated(ServerStoredGroupEvent evt) {
MetaContactGroupImpl newMetaGroup = new MetaContactGroupImpl(
evt.getSrouceGroup().getGroupName());
newMetaGroup.addProtoGroup(
evt.getSourceProvider(), evt
.getSrouceGroup());
newMetaGroup.addProtoGroup(evt.getSrouceGroup());
Iterator contactsIter = evt.getSrouceGroup()
.contacts();
@ -672,26 +731,46 @@ public void groupCreated(ServerStoredGroupEvent evt) {
fireMetaContactGroupEvent(newMetaGroup,
evt.getSourceProvider(),
MetaContactGroupEvent.METACONTACT_GROUP_ADDED);
MetaContactGroupEvent.META_CONTACT_GROUP_ADDED);
}
/**
* Updates the local contact list by removing the meta contact group
* corresponding to the group indicated by the delivered <tt>evt</tt>
* @param evt the ServerStoredGroupEvent contining the group that has
* been removed.
*/
public void groupRemoved(ServerStoredGroupEvent evt) {
logger.trace("ContactGroup removed: " + evt);
MetaContactGroup metaContactGroup
= findMetaContactGroupByContactGroup(evt.getSrouceGroup());
MetaContactGroupImpl metaContactGroup = (MetaContactGroupImpl)
findMetaContactGroupByContactGroup(evt.getSrouceGroup());
if (metaContactGroup != null) {
if (metaContactGroup == null) {
logger.error("Received a RemovedGroup event for an orphan grp: "
+ evt.getSrouceGroup());
return;
}
removeContactGroupFromMetaContactGroup(metaContactGroup,
evt.getSrouceGroup(), evt.getSourceProvider());
//do not remove the meta contact group even if this is the las
//protocol specific contact group. Contrary to contacts, meta
//contact groups are to only be remove upon user indication or
//otherwise it would be difficult for a user to create a new grp.
removeMetaContactGroup(metaContactGroup);
fireMetaContactGroupEvent(metaContactGroup,
evt.getSourceProvider(),
MetaContactGroupEvent.METACONTACT_GROUP_REMOVED);
}
}
/**
* Nothing to do here really. Oh yes .... we should actually trigger
* a MetaContactGroup event indicating the change for interested parties
* but that's all.
* @param evt the ServerStoredGroupEvent containing the source group.
*/
public void groupNameChanged(ServerStoredGroupEvent evt) {
logger.trace("ContactGroup renamed: " + evt);
@ -699,7 +778,8 @@ public void groupNameChanged(ServerStoredGroupEvent evt) {
MetaContactGroup metaContactGroup
= findMetaContactGroupByContactGroup(evt.getSrouceGroup());
//TODO: change the name of the MetaContactGroup
fireMetaContactGroupEvent(metaContactGroup, evt.getSourceProvider(),
MetaContactGroupEvent.CONTACT_GROUP_RENAMED_IN_META_GROUP);
}
}
@ -735,10 +815,18 @@ private void fireMetaContactEvent(MetaContact source,
while (listeners.hasNext()) {
MetaContactListListener l = (MetaContactListListener) listeners
.next();
if (eventID == MetaContactEvent.METACONTACT_ADDED)
l.metaContactAdded(evt);
else if (eventID == MetaContactEvent.METACONTACT_REMOVED)
l.metaContactRemoved(evt);
switch (eventID)
{
case MetaContactEvent.META_CONTACT_ADDED:
l.metaContactAdded(evt);break;
case MetaContactEvent.META_CONTACT_REMOVED:
l.metaContactRemoved(evt);break;
case MetaContactEvent.PROTO_CONTACT_REMOVED:
case MetaContactEvent.PROTO_CONTACT_ADDED:
l.metaContactModified(evt);break;
default:
logger.error("Unknown event type " + eventID);
}
}
}
}
@ -773,10 +861,20 @@ private void fireMetaContactGroupEvent(
while (listeners.hasNext()) {
MetaContactListListener l = (MetaContactListListener) listeners
.next();
if (eventID == MetaContactGroupEvent.METACONTACT_GROUP_ADDED)
l.metaContactGroupAdded(evt);
else if (eventID == MetaContactGroupEvent.METACONTACT_GROUP_REMOVED)
l.metaContactGroupRemoved(evt);
switch (eventID)
{
case MetaContactGroupEvent.META_CONTACT_GROUP_ADDED:
l.metaContactGroupAdded(evt);break;
case MetaContactGroupEvent.META_CONTACT_GROUP_REMOVED:
l.metaContactGroupRemoved(evt);break;
case MetaContactGroupEvent
.CONTACT_GROUP_REMOVED_FROM_META_GROUP:
l.metaContactGroupModified(evt);break;
default:
logger.error("Unknown event type ("+eventID
+") for event: " + evt);
}
}
}
}

@ -38,6 +38,19 @@ public interface MetaContact
*/
public Iterator getContacts();
/**
* Returns a contact encapsulated by this meta contact, having the specified
* contactAddress and coming from the indicated ownerProvider.
* @param contactAddress the address of the contact who we're looking for.
* @param ownerProvider a reference to the ProtocolProviderService that
* the contact we're looking for belongs to.
* @return a reference to a <tt>Contact</tt>, encapsulated by this
* MetaContact, carrying the specified address and originating from the
* specified ownerProvider or null if no such contact exists..
*/
public Contact getContact( String contactAddress,
ProtocolProviderService ownerProvider);
/**
* Returns the number of protocol speciic <tt>Contact</tt>s that this
* <tt>MetaContact</tt> contains.
@ -47,17 +60,17 @@ public interface MetaContact
public int getContactCount();
/**
* Returns a Contact, encapsulated by this MetaContact and coming from the
* specified ProtocolProviderService. If none of the contacts encapsulated
* by this MetaContact is originating from the specified provider then
* <tt>null</tt> is returned.
* Returns all protocol specific Contacts, encapsulated by this MetaContact
* and coming from the indicated ProtocolProviderService. If none of the
* contacts encapsulated by this MetaContact is originating from the
* specified provider then an empty iterator is returned.
* <p>
* @param provider a reference to the <tt>ProtocolProviderService</tt>
* that we'd like to get a <tt>Contact</tt> for.
* @return a <tt>Contact</tt> encapsulated in this
* whose contacts we'd like to get.
* @return an <tt>Iterator</tt> over all contacts encapsulated in this
* <tt>MetaContact</tt> and originating from the specified provider.
*/
public Contact getContactForProvider(ProtocolProviderService provider);
public Iterator getContactsForProvider(ProtocolProviderService provider);
/**
* Returns a String identifier (the actual contents is left to

@ -7,6 +7,7 @@
package net.java.sip.communicator.service.contactlist;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
/**
* <tt>MetaContactGroup</tt>s are used to merge groups (often originating
@ -21,6 +22,42 @@
*/
public interface MetaContactGroup
{
/**
* Returns an iterator over all the protocol specific groups that this
* contact group represents.
* @return an Iterator over the protocol specific groups that this group
* represents.
*/
public Iterator getContactGroups();
/**
* Returns all protocol specific ContactGroups, encapsulated by this
* MetaContactGroup and coming from the indicated ProtocolProviderService.
* If none of the contacts encapsulated by this MetaContact is originating
* from the specified provider then an empty iterator is returned.
* <p>
* @param provider a reference to the <tt>ProtocolProviderService</tt>
* whose ContactGroups we'd like to get.
* @return an <tt>Iterator</tt> over all contacts encapsulated in this
* <tt>MetaContact</tt> and originating from the specified provider.
*/
public Iterator getContactGroupsForProvider(ProtocolProviderService provider);
/**
* Returns a contact group encapsulated by this meta contact group, having
* the specified groupName and coming from the indicated ownerProvider.
*
* @param groupName the name of the contact group who we're looking for.
* @param ownerProvider a reference to the ProtocolProviderService that
* the contact we're looking for belongs to.
* @return a reference to a <tt>ContactGroup</tt>, encapsulated by this
* MetaContactGroup, carrying the specified name and originating from the
* specified ownerProvider.
*/
public ContactGroup getContactGroup(String groupName,
ProtocolProviderService ownerProvider);
/**
* Returns a <tt>java.util.Iterator</tt> over the <tt>MetaContact</tt>s
* contained in this <tt>MetaContactGroup</tt>.
@ -68,12 +105,12 @@ public interface MetaContactGroup
/**
* Returns the contact with the specified identifier
* @param metaContactID a String identifier obtained through the
* @param metaUID a String identifier obtained through the
* <tt>MetaContact.getMetaUID()</tt> method.
* <p>
* @return the <tt>MetaContact</tt> with the specified idnetifier.
*/
public MetaContact getMetaContact(String metaContactID);
public MetaContact getMetaContact(String metaUID);
/**
* Returns the meta contact on the specified index.

@ -49,7 +49,6 @@
* only load their mocking protocol provider implementations during the test
* run.
* <p>
* @todo expections
* @author Emil Ivov
*/
public interface MetaContactListService
@ -80,11 +79,26 @@ public interface MetaContactListService
* we need to find the MetaContact that is the author of an incoming message
* and the corresponding ProtocolProviderService has only provided a
* <tt>Contact</tt> as its author.
*
* @param contact the contact whose encapsulating meta contact we're looking
* for.
* @return the MetaContact containing the speicified contact or null
* if no such contact is present in this contact list.
*/
public MetaContact findMetaContactByContact(Contact contact);
/**
* Returns the MetaContactGroup encapsulating the specified protocol contact
* group or null if no such MetaContactGroup was found.
*
* @param group the group whose encapsulating meta group we're looking for.
* @return the MetaContact containing the speicified contact or null
* if no such contact is present in this contact list.
*/
public MetaContactGroup findMetaContactGroupByContactGroup(
ContactGroup group);
/**
* Returns the MetaContact that corresponds to the specified metaContactID.
*
@ -92,7 +106,7 @@ public interface MetaContactListService
* @return the MetaContact with the speicified string identifier or null
* if no such meta contact was found.
*/
public MetaContact findMetaContactByID(String metaContactID);
public MetaContact findMetaContactByMetaUID(String metaContactID);
/**
* Adds a listener for <tt>MetaContactListChangeEvent</tt>s posted after

Loading…
Cancel
Save