1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2003-2007 Jive Software.
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License.
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *     http://www.apache.org/licenses/LICENSE-2.0
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS,
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License.
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smack;
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.PacketIDFilter;
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.IQ;
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.RosterPacket;
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.util.StringUtils;
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.ArrayList;
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collection;
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collections;
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.List;
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A group of roster entries.
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Roster#getGroup(String)
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Matt Tucker
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class RosterGroup {
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private String name;
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private Connection connection;
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final List<RosterEntry> entries;
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Creates a new roster group instance.
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param name the name of the group.
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param connection the connection the group belongs to.
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    RosterGroup(String name, Connection connection) {
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.name = name;
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.connection = connection;
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        entries = new ArrayList<RosterEntry>();
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the name of the group.
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the name of the group.
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getName() {
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return name;
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Sets the name of the group. Changing the group's name is like moving all the group entries
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * of the group to a new group specified by the new name. Since this group won't have entries
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * it will be removed from the roster. This means that all the references to this object will
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * be invalid and will need to be updated to the new group specified by the new name.
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param name the name of the group.
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void setName(String name) {
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        synchronized (entries) {
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            for (RosterEntry entry : entries) {
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                RosterPacket packet = new RosterPacket();
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                packet.setType(IQ.Type.SET);
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                RosterPacket.Item item = RosterEntry.toRosterItem(entry);
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                item.removeGroupName(this.name);
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                item.addGroupName(name);
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                packet.addRosterItem(item);
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                connection.sendPacket(packet);
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the number of entries in the group.
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the number of entries in the group.
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public int getEntryCount() {
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        synchronized (entries) {
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return entries.size();
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns an unmodifiable collection of all entries in the group.
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return all entries in the group.
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public Collection<RosterEntry> getEntries() {
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        synchronized (entries) {
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return Collections.unmodifiableList(new ArrayList<RosterEntry>(entries));
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the roster entry associated with the given XMPP address or
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <tt>null</tt> if the user is not an entry in the group.
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param user the XMPP address of the user (eg "jsmith@example.com").
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the roster entry or <tt>null</tt> if it does not exist in the group.
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public RosterEntry getEntry(String user) {
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (user == null) {
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return null;
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Roster entries never include a resource so remove the resource
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // if it's a part of the XMPP address.
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        user = StringUtils.parseBareAddress(user);
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        String userLowerCase = user.toLowerCase();
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        synchronized (entries) {
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            for (RosterEntry entry : entries) {
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                if (entry.getUser().equals(userLowerCase)) {
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    return entry;
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return null;
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns true if the specified entry is part of this group.
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param entry a roster entry.
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return true if the entry is part of this group.
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public boolean contains(RosterEntry entry) {
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        synchronized (entries) {
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return entries.contains(entry);
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns true if the specified XMPP address is an entry in this group.
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param user the XMPP address of the user.
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return true if the XMPP address is an entry in this group.
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public boolean contains(String user) {
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return getEntry(user) != null;
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Adds a roster entry to this group. If the entry was unfiled then it will be removed from
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the unfiled list and will be added to this group.
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Note that this is an asynchronous call -- Smack must wait for the server
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * to receive the updated roster.
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param entry a roster entry.
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException if an error occured while trying to add the entry to the group.
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void addEntry(RosterEntry entry) throws XMPPException {
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketCollector collector = null;
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Only add the entry if it isn't already in the list.
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        synchronized (entries) {
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (!entries.contains(entry)) {
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                RosterPacket packet = new RosterPacket();
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                packet.setType(IQ.Type.SET);
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                RosterPacket.Item item = RosterEntry.toRosterItem(entry);
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                item.addGroupName(getName());
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                packet.addRosterItem(item);
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // Wait up to a certain number of seconds for a reply from the server.
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                collector = connection
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        .createPacketCollector(new PacketIDFilter(packet.getPacketID()));
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                connection.sendPacket(packet);
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (collector != null) {
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            collector.cancel();
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (response == null) {
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                throw new XMPPException("No response from the server.");
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            // If the server replied with an error, throw an exception.
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            else if (response.getType() == IQ.Type.ERROR) {
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                throw new XMPPException(response.getError());
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Removes a roster entry from this group. If the entry does not belong to any other group
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * then it will be considered as unfiled, therefore it will be added to the list of unfiled
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * entries.
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Note that this is an asynchronous call -- Smack must wait for the server
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * to receive the updated roster.
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param entry a roster entry.
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException if an error occured while trying to remove the entry from the group.
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void removeEntry(RosterEntry entry) throws XMPPException {
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketCollector collector = null;
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Only remove the entry if it's in the entry list.
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Remove the entry locally, if we wait for RosterPacketListenerprocess>>Packet(Packet)
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // to take place the entry will exist in the group until a packet is received from the
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // server.
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        synchronized (entries) {
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (entries.contains(entry)) {
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                RosterPacket packet = new RosterPacket();
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                packet.setType(IQ.Type.SET);
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                RosterPacket.Item item = RosterEntry.toRosterItem(entry);
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                item.removeGroupName(this.getName());
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                packet.addRosterItem(item);
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // Wait up to a certain number of seconds for a reply from the server.
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                collector = connection
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        .createPacketCollector(new PacketIDFilter(packet.getPacketID()));
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                connection.sendPacket(packet);
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (collector != null) {
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            collector.cancel();
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (response == null) {
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                throw new XMPPException("No response from the server.");
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            // If the server replied with an error, throw an exception.
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            else if (response.getType() == IQ.Type.ERROR) {
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                throw new XMPPException(response.getError());
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void addEntryLocal(RosterEntry entry) {
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Only add the entry if it isn't already in the list.
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        synchronized (entries) {
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            entries.remove(entry);
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            entries.add(entry);
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    void removeEntryLocal(RosterEntry entry) {
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         // Only remove the entry if it's in the entry list.
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        synchronized (entries) {
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (entries.contains(entry)) {
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                entries.remove(entry);
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}