All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jivesoftware.smack.RosterGroup Maven / Gradle / Ivy

The newest version!
/**
 *
 * Copyright 2003-2007 Jive Software.
 *
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jivesoftware.smack;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.util.StringUtils;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Roster;

/**
 * A group of roster entries.
 * 
 * @see UserRoster#getGroup(String)
 * @author Matt Tucker
 */
public class RosterGroup {

    private String name;
    private Connection connection;
    private final Set entries;

    /**
     * Creates a new roster group instance.
     * 
     * @param name
     *            the name of the group.
     * @param connection
     *            the connection the group belongs to.
     */
    RosterGroup(String name, Connection connection) {
        this.name = name;
        this.connection = connection;
        entries = new LinkedHashSet();
    }

    /**
     * Returns the name of the group.
     * 
     * @return the name of the group.
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the name of the group. Changing the group's name is like moving all
     * the group entries of the group to a new group specified by the new name.
     * Since this group won't have entries it will be removed from the roster.
     * This means that all the references to this object will be invalid and
     * will need to be updated to the new group specified by the new name.
     * 
     * @param name
     *            the name of the group.
     */
    public void setName(String name) {
        synchronized (entries) {
            for (RosterEntry entry : entries) {
                Roster packet = new Roster();
                packet.setType(IQ.Type.set);
                List groupNames = new LinkedList(
                        entry.getGroupNames());
                groupNames.remove(this.name);
                groupNames.add(name);
                packet.addItem(new JID(entry.getUser()), entry.getName(),
                        entry.getAsk(), entry.getSubscription(), groupNames);
                connection.sendPacket(packet);
            }
        }
    }

    /**
     * Returns the number of entries in the group.
     * 
     * @return the number of entries in the group.
     */
    public int getEntryCount() {
        synchronized (entries) {
            return entries.size();
        }
    }

    /**
     * Returns an unmodifiable collection of all entries in the group.
     * 
     * @return all entries in the group.
     */
    public Collection getEntries() {
        synchronized (entries) {
            return Collections.unmodifiableList(new ArrayList(
                    entries));
        }
    }

    /**
     * Returns the roster entry associated with the given XMPP address or
     * null if the user is not an entry in the group.
     * 
     * @param user
     *            the XMPP address of the user (eg "[email protected]").
     * @return the roster entry or null if it does not exist in the
     *         group.
     */
    public RosterEntry getEntry(String user) {
        if (user == null) {
            return null;
        }
        // Roster entries never include a resource so remove the resource
        // if it's a part of the XMPP address.
        user = StringUtils.parseBareAddress(user);
        String userLowerCase = user.toLowerCase();
        synchronized (entries) {
            for (RosterEntry entry : entries) {
                if (entry.getUser().equals(userLowerCase)) {
                    return entry;
                }
            }
        }
        return null;
    }

    /**
     * Returns true if the specified entry is part of this group.
     * 
     * @param entry
     *            a roster entry.
     * @return true if the entry is part of this group.
     */
    public boolean contains(RosterEntry entry) {
        synchronized (entries) {
            return entries.contains(entry);
        }
    }

    /**
     * Returns true if the specified XMPP address is an entry in this group.
     * 
     * @param user
     *            the XMPP address of the user.
     * @return true if the XMPP address is an entry in this group.
     */
    public boolean contains(String user) {
        return getEntry(user) != null;
    }

    /**
     * Adds a roster entry to this group. If the entry was unfiled then it will
     * be removed from the unfiled list and will be added to this group. Note
     * that this is an asynchronous call -- Smack must wait for the server to
     * receive the updated roster.
     * 
     * @param entry
     *            a roster entry.
     * @throws XMPPException
     *             if an error occured while trying to add the entry to the
     *             group.
     */
    public void addEntry(RosterEntry entry) throws XMPPException {
        PacketCollector collector = null;
        // Only add the entry if it isn't already in the list.
        synchronized (entries) {
            if (!entries.contains(entry)) {
                Roster packet = new Roster();
                packet.setType(IQ.Type.set);
                List groupNames = new LinkedList(
                        entry.getGroupNames());
                groupNames.add(getName());
                packet.addItem(new JID(entry.getUser()), entry.getName(),
                        entry.getAsk(), entry.getSubscription(), groupNames);
                // Wait up to a certain number of seconds for a reply from the
                // server.
                collector = connection
                        .createPacketCollector(new PacketIDFilter(packet
                                .getID()));
                connection.sendPacket(packet);
            }
        }
        if (collector != null) {
            IQ response = (IQ) collector.nextResult(SmackConfiguration
                    .getPacketReplyTimeout());
            collector.cancel();
            if (response == null) {
                throw new XMPPException("No response from the server.");
            }
            // If the server replied with an error, throw an exception.
            else if (response.getType() == IQ.Type.error) {
                throw new XMPPException(response.getError());
            }
        }
    }

    /**
     * Removes a roster entry from this group. If the entry does not belong to
     * any other group then it will be considered as unfiled, therefore it will
     * be added to the list of unfiled entries. Note that this is an
     * asynchronous call -- Smack must wait for the server to receive the
     * updated roster.
     * 
     * @param entry
     *            a roster entry.
     * @throws XMPPException
     *             if an error occured while trying to remove the entry from the
     *             group.
     */
    public void removeEntry(RosterEntry entry) throws XMPPException {
        PacketCollector collector = null;
        // Only remove the entry if it's in the entry list.
        // Remove the entry locally, if we wait for
        // RosterPacketListenerprocess>>Packet(Packet)
        // to take place the entry will exist in the group until a packet is
        // received from the
        // server.
        synchronized (entries) {
            if (entries.contains(entry)) {
                Roster packet = new Roster();
                packet.setType(IQ.Type.set);
                List groupNames = new LinkedList(
                        entry.getGroupNames());
                groupNames.remove(this.getName());
                packet.addItem(new JID(entry.getUser()), entry.getName(),
                        entry.getAsk(), entry.getSubscription(), groupNames);
                // Wait up to a certain number of seconds for a reply from the
                // server.
                collector = connection
                        .createPacketCollector(new PacketIDFilter(packet
                                .getID()));
                connection.sendPacket(packet);
            }
        }
        if (collector != null) {
            IQ response = (IQ) collector.nextResult(SmackConfiguration
                    .getPacketReplyTimeout());
            collector.cancel();
            if (response == null) {
                throw new XMPPException("No response from the server.");
            }
            // If the server replied with an error, throw an exception.
            else if (response.getType() == IQ.Type.error) {
                throw new XMPPException(response.getError());
            }
        }
    }

    void addEntryLocal(RosterEntry entry) {
        // Update the entry if it is already in the list
        synchronized (entries) {
            entries.remove(entry);
            entries.add(entry);
        }
    }

    void removeEntryLocal(RosterEntry entry) {
        // Only remove the entry if it's in the entry list.
        synchronized (entries) {
            if (entries.contains(entry)) {
                entries.remove(entry);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy