RosterGroup.java

  1. /**
  2.  *
  3.  * Copyright 2003-2007 Jive Software.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.jivesoftware.smack.roster;

  18. import java.util.ArrayList;
  19. import java.util.LinkedHashSet;
  20. import java.util.List;
  21. import java.util.Set;

  22. import org.jivesoftware.smack.Manager;
  23. import org.jivesoftware.smack.SmackException.NoResponseException;
  24. import org.jivesoftware.smack.SmackException.NotConnectedException;
  25. import org.jivesoftware.smack.XMPPConnection;
  26. import org.jivesoftware.smack.XMPPException.XMPPErrorException;
  27. import org.jivesoftware.smack.packet.IQ;
  28. import org.jivesoftware.smack.roster.packet.RosterPacket;

  29. import org.jxmpp.jid.Jid;

  30. /**
  31.  * A group of roster entries.
  32.  *
  33.  * @see Roster#getGroup(String)
  34.  * @author Matt Tucker
  35.  */
  36. public class RosterGroup extends Manager {

  37.     private final String name;
  38.     private final Set<RosterEntry> entries;

  39.     /**
  40.      * Creates a new roster group instance.
  41.      *
  42.      * @param name the name of the group.
  43.      * @param connection the connection the group belongs to.
  44.      */
  45.     RosterGroup(String name, XMPPConnection connection) {
  46.         super(connection);
  47.         this.name = name;
  48.         entries = new LinkedHashSet<>();
  49.     }

  50.     /**
  51.      * Returns the name of the group.
  52.      *
  53.      * @return the name of the group.
  54.      */
  55.     public String getName() {
  56.         return name;
  57.     }

  58.     /**
  59.      * Sets the name of the group. Changing the group's name is like moving all the group entries
  60.      * of the group to a new group specified by the new name. Since this group won't have entries
  61.      * it will be removed from the roster. This means that all the references to this object will
  62.      * be invalid and will need to be updated to the new group specified by the new name.
  63.      *
  64.      * @param name the name of the group.
  65.      * @throws NotConnectedException if the XMPP connection is not connected.
  66.      * @throws XMPPErrorException if there was an XMPP error returned.
  67.      * @throws NoResponseException if there was no response from the remote entity.
  68.      * @throws InterruptedException if the calling thread was interrupted.
  69.      */
  70.     public void setName(String name) throws NotConnectedException, NoResponseException, XMPPErrorException, InterruptedException {
  71.         synchronized (entries) {
  72.             for (RosterEntry entry : entries) {
  73.                 RosterPacket packet = new RosterPacket();
  74.                 packet.setType(IQ.Type.set);
  75.                 RosterPacket.Item item = RosterEntry.toRosterItem(entry);
  76.                 item.removeGroupName(this.name);
  77.                 item.addGroupName(name);
  78.                 packet.addRosterItem(item);
  79.                 connection().sendIqRequestAndWaitForResponse(packet);
  80.             }
  81.         }
  82.     }

  83.     /**
  84.      * Returns the number of entries in the group.
  85.      *
  86.      * @return the number of entries in the group.
  87.      */
  88.     public int getEntryCount() {
  89.         synchronized (entries) {
  90.             return entries.size();
  91.         }
  92.     }

  93.     /**
  94.      * Returns an copied list of all entries in the group.
  95.      *
  96.      * @return all entries in the group.
  97.      */
  98.     public List<RosterEntry> getEntries() {
  99.         synchronized (entries) {
  100.             return new ArrayList<>(entries);
  101.         }
  102.     }

  103.     /**
  104.      * Returns the roster entry associated with the given XMPP address or
  105.      * <code>null</code> if the user is not an entry in the group.
  106.      *
  107.      * @param user the XMPP address of the user (e.g."jsmith@example.com").
  108.      * @return the roster entry or <code>null</code> if it does not exist in the group.
  109.      */
  110.     public RosterEntry getEntry(Jid user) {
  111.         if (user == null) {
  112.             return null;
  113.         }
  114.         // Roster entries never include a resource so remove the resource
  115.         // if it's a part of the XMPP address.
  116.         user = user.asBareJid();
  117.         synchronized (entries) {
  118.             for (RosterEntry entry : entries) {
  119.                 if (entry.getJid().equals(user)) {
  120.                     return entry;
  121.                 }
  122.             }
  123.         }
  124.         return null;
  125.     }

  126.     /**
  127.      * Returns true if the specified entry is part of this group.
  128.      *
  129.      * @param entry a roster entry.
  130.      * @return true if the entry is part of this group.
  131.      */
  132.     public boolean contains(RosterEntry entry) {
  133.         synchronized (entries) {
  134.             return entries.contains(entry);
  135.         }
  136.     }

  137.     /**
  138.      * Returns true if the specified XMPP address is an entry in this group.
  139.      *
  140.      * @param user the XMPP address of the user.
  141.      * @return true if the XMPP address is an entry in this group.
  142.      */
  143.     public boolean contains(Jid user) {
  144.         return getEntry(user) != null;
  145.     }

  146.     /**
  147.      * Adds a roster entry to this group. If the entry was unfiled then it will be removed from
  148.      * the unfiled list and will be added to this group.
  149.      * Note that this is a synchronous call -- Smack must wait for the server
  150.      * to receive the updated roster.
  151.      *
  152.      * @param entry a roster entry.
  153.      * @throws XMPPErrorException if an error occurred while trying to add the entry to the group.
  154.      * @throws NoResponseException if there was no response from the server.
  155.      * @throws NotConnectedException if the XMPP connection is not connected.
  156.      * @throws InterruptedException if the calling thread was interrupted.
  157.      */
  158.     public void addEntry(RosterEntry entry) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
  159.         // Only add the entry if it isn't already in the list.
  160.         synchronized (entries) {
  161.             if (!entries.contains(entry)) {
  162.                 RosterPacket packet = new RosterPacket();
  163.                 packet.setType(IQ.Type.set);
  164.                 RosterPacket.Item item = RosterEntry.toRosterItem(entry);
  165.                 item.addGroupName(getName());
  166.                 packet.addRosterItem(item);
  167.                 // Wait up to a certain number of seconds for a reply from the server.
  168.                 connection().sendIqRequestAndWaitForResponse(packet);
  169.             }
  170.         }
  171.     }

  172.     /**
  173.      * Removes a roster entry from this group. If the entry does not belong to any other group
  174.      * then it will be considered as unfiled, therefore it will be added to the list of unfiled
  175.      * entries.
  176.      * Note that this is a synchronous call -- Smack must wait for the server
  177.      * to receive the updated roster.
  178.      *
  179.      * @param entry a roster entry.
  180.      * @throws XMPPErrorException if an error occurred while trying to remove the entry from the group.
  181.      * @throws NoResponseException if there was no response from the server.
  182.      * @throws NotConnectedException if the XMPP connection is not connected.
  183.      * @throws InterruptedException if the calling thread was interrupted.
  184.      */
  185.     public void removeEntry(RosterEntry entry) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
  186.         // Only remove the entry if it's in the entry list.
  187.         // Remove the entry locally, if we wait for RosterPacketListenerProcess>>Packet(Packet)
  188.         // to take place the entry will exist in the group until a packet is received from the
  189.         // server.
  190.         synchronized (entries) {
  191.             if (entries.contains(entry)) {
  192.                 RosterPacket packet = new RosterPacket();
  193.                 packet.setType(IQ.Type.set);
  194.                 RosterPacket.Item item = RosterEntry.toRosterItem(entry);
  195.                 item.removeGroupName(this.getName());
  196.                 packet.addRosterItem(item);
  197.                 // Wait up to a certain number of seconds for a reply from the server.
  198.                 connection().sendIqRequestAndWaitForResponse(packet);
  199.             }
  200.         }
  201.     }

  202.     void addEntryLocal(RosterEntry entry) {
  203.         // Update the entry if it is already in the list
  204.         synchronized (entries) {
  205.             entries.remove(entry);
  206.             entries.add(entry);
  207.         }
  208.     }

  209.     void removeEntryLocal(RosterEntry entry) {
  210.          // Only remove the entry if it's in the entry list.
  211.         synchronized (entries) {
  212.             if (entries.contains(entry)) {
  213.                 entries.remove(entry);
  214.             }
  215.         }
  216.     }
  217. }