001/** 002 * 003 * Copyright 2003-2007 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.jivesoftware.smack; 019 020import org.jivesoftware.smack.SmackException.NotConnectedException; 021import org.jivesoftware.smack.packet.IQ; 022import org.jivesoftware.smack.packet.RosterPacket; 023 024import java.util.*; 025 026/** 027 * Each user in your roster is represented by a roster entry, which contains the user's 028 * JID and a name or nickname you assign. 029 * 030 * @author Matt Tucker 031 */ 032public class RosterEntry { 033 034 private String user; 035 private String name; 036 private RosterPacket.ItemType type; 037 private RosterPacket.ItemStatus status; 038 final private Roster roster; 039 final private XMPPConnection connection; 040 041 /** 042 * Creates a new roster entry. 043 * 044 * @param user the user. 045 * @param name the nickname for the entry. 046 * @param type the subscription type. 047 * @param status the subscription status (related to subscriptions pending to be approbed). 048 * @param connection a connection to the XMPP server. 049 */ 050 RosterEntry(String user, String name, RosterPacket.ItemType type, 051 RosterPacket.ItemStatus status, Roster roster, XMPPConnection connection) { 052 this.user = user; 053 this.name = name; 054 this.type = type; 055 this.status = status; 056 this.roster = roster; 057 this.connection = connection; 058 } 059 060 /** 061 * Returns the JID of the user associated with this entry. 062 * 063 * @return the user associated with this entry. 064 */ 065 public String getUser() { 066 return user; 067 } 068 069 /** 070 * Returns the name associated with this entry. 071 * 072 * @return the name. 073 */ 074 public String getName() { 075 return name; 076 } 077 078 /** 079 * Sets the name associated with this entry. 080 * 081 * @param name the name. 082 * @throws NotConnectedException 083 */ 084 public void setName(String name) throws NotConnectedException { 085 // Do nothing if the name hasn't changed. 086 if (name != null && name.equals(this.name)) { 087 return; 088 } 089 this.name = name; 090 RosterPacket packet = new RosterPacket(); 091 packet.setType(IQ.Type.SET); 092 packet.addRosterItem(toRosterItem(this)); 093 connection.sendPacket(packet); 094 } 095 096 /** 097 * Updates the state of the entry with the new values. 098 * 099 * @param name the nickname for the entry. 100 * @param type the subscription type. 101 * @param status the subscription status (related to subscriptions pending to be approbed). 102 */ 103 void updateState(String name, RosterPacket.ItemType type, RosterPacket.ItemStatus status) { 104 this.name = name; 105 this.type = type; 106 this.status = status; 107 } 108 109 /** 110 * Returns an unmodifiable collection of the roster groups that this entry belongs to. 111 * 112 * @return an iterator for the groups this entry belongs to. 113 */ 114 public Collection<RosterGroup> getGroups() { 115 List<RosterGroup> results = new ArrayList<RosterGroup>(); 116 // Loop through all roster groups and find the ones that contain this 117 // entry. This algorithm should be fine 118 for (RosterGroup group: roster.getGroups()) { 119 if (group.contains(this)) { 120 results.add(group); 121 } 122 } 123 return Collections.unmodifiableCollection(results); 124 } 125 126 /** 127 * Returns the roster subscription type of the entry. When the type is 128 * RosterPacket.ItemType.none or RosterPacket.ItemType.from, 129 * refer to {@link RosterEntry getStatus()} to see if a subscription request 130 * is pending. 131 * 132 * @return the type. 133 */ 134 public RosterPacket.ItemType getType() { 135 return type; 136 } 137 138 /** 139 * Returns the roster subscription status of the entry. When the status is 140 * RosterPacket.ItemStatus.SUBSCRIPTION_PENDING, the contact has to answer the 141 * subscription request. 142 * 143 * @return the status. 144 */ 145 public RosterPacket.ItemStatus getStatus() { 146 return status; 147 } 148 149 public String toString() { 150 StringBuilder buf = new StringBuilder(); 151 if (name != null) { 152 buf.append(name).append(": "); 153 } 154 buf.append(user); 155 Collection<RosterGroup> groups = getGroups(); 156 if (!groups.isEmpty()) { 157 buf.append(" ["); 158 Iterator<RosterGroup> iter = groups.iterator(); 159 RosterGroup group = iter.next(); 160 buf.append(group.getName()); 161 while (iter.hasNext()) { 162 buf.append(", "); 163 group = iter.next(); 164 buf.append(group.getName()); 165 } 166 buf.append("]"); 167 } 168 return buf.toString(); 169 } 170 171 @Override 172 public int hashCode() { 173 return (user == null ? 0 : user.hashCode()); 174 } 175 176 public boolean equals(Object object) { 177 if (this == object) { 178 return true; 179 } 180 if (object != null && object instanceof RosterEntry) { 181 return user.equals(((RosterEntry)object).getUser()); 182 } 183 else { 184 return false; 185 } 186 } 187 188 /** 189 * Indicates whether some other object is "equal to" this by comparing all members. 190 * <p> 191 * The {@link #equals(Object)} method returns <code>true</code> if the user JIDs are equal. 192 * 193 * @param obj the reference object with which to compare. 194 * @return <code>true</code> if this object is the same as the obj argument; <code>false</code> 195 * otherwise. 196 */ 197 public boolean equalsDeep(Object obj) { 198 if (this == obj) 199 return true; 200 if (obj == null) 201 return false; 202 if (getClass() != obj.getClass()) 203 return false; 204 RosterEntry other = (RosterEntry) obj; 205 if (name == null) { 206 if (other.name != null) 207 return false; 208 } 209 else if (!name.equals(other.name)) 210 return false; 211 if (status == null) { 212 if (other.status != null) 213 return false; 214 } 215 else if (!status.equals(other.status)) 216 return false; 217 if (type == null) { 218 if (other.type != null) 219 return false; 220 } 221 else if (!type.equals(other.type)) 222 return false; 223 if (user == null) { 224 if (other.user != null) 225 return false; 226 } 227 else if (!user.equals(other.user)) 228 return false; 229 return true; 230 } 231 232 static RosterPacket.Item toRosterItem(RosterEntry entry) { 233 RosterPacket.Item item = new RosterPacket.Item(entry.getUser(), entry.getName()); 234 item.setItemType(entry.getType()); 235 item.setItemStatus(entry.getStatus()); 236 // Set the correct group names for the item. 237 for (RosterGroup group : entry.getGroups()) { 238 item.addGroupName(group.getName()); 239 } 240 return item; 241 } 242 243}