1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-06-14 07:34:53 +02:00
Smack/core/src/main/java/org/jivesoftware/smack/RosterGroup.java
Florian Schmaus 1e57f1c659 Activate checkstyle and add missing license headers
Delete also all "All rights reserved" statements, as they are
unnecessary and conflict with checkstyle's header check. Delete unused
imports.
2014-02-17 20:09:55 +01:00

251 lines
8.8 KiB
Java

/**
*
* Copyright 2003-2007 Jive Software.
*
* 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 org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.RosterPacket;
import org.jivesoftware.smack.util.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* A group of roster entries.
*
* @see Roster#getGroup(String)
* @author Matt Tucker
*/
public class RosterGroup {
private String name;
private Connection connection;
private final Set<RosterEntry> 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<RosterEntry>();
}
/**
* 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) {
RosterPacket packet = new RosterPacket();
packet.setType(IQ.Type.SET);
RosterPacket.Item item = RosterEntry.toRosterItem(entry);
item.removeGroupName(this.name);
item.addGroupName(name);
packet.addRosterItem(item);
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<RosterEntry> getEntries() {
synchronized (entries) {
return Collections.unmodifiableList(new ArrayList<RosterEntry>(entries));
}
}
/**
* Returns the roster entry associated with the given XMPP address or
* <tt>null</tt> if the user is not an entry in the group.
*
* @param user the XMPP address of the user (eg "jsmith@example.com").
* @return the roster entry or <tt>null</tt> 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)) {
RosterPacket packet = new RosterPacket();
packet.setType(IQ.Type.SET);
RosterPacket.Item item = RosterEntry.toRosterItem(entry);
item.addGroupName(getName());
packet.addRosterItem(item);
// Wait up to a certain number of seconds for a reply from the server.
collector = connection
.createPacketCollector(new PacketIDFilter(packet.getPacketID()));
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)) {
RosterPacket packet = new RosterPacket();
packet.setType(IQ.Type.SET);
RosterPacket.Item item = RosterEntry.toRosterItem(entry);
item.removeGroupName(this.getName());
packet.addRosterItem(item);
// Wait up to a certain number of seconds for a reply from the server.
collector = connection
.createPacketCollector(new PacketIDFilter(packet.getPacketID()));
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);
}
}
}
}