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.smackx.muc.packet; 019 020import org.jivesoftware.smack.packet.NamedElement; 021import org.jivesoftware.smack.packet.Stanza; 022 023import java.util.HashMap; 024import java.util.HashSet; 025import java.util.Map; 026import java.util.Set; 027 028import org.jivesoftware.smack.packet.ExtensionElement; 029import org.jivesoftware.smack.util.XmlStringBuilder; 030 031/** 032 * Represents extended presence information about roles, affiliations, full JIDs, 033 * or status codes scoped by the 'http://jabber.org/protocol/muc#user' namespace. 034 * 035 * @author Gaston Dombiak 036 */ 037public class MUCUser implements ExtensionElement { 038 039 public static final String ELEMENT = "x"; 040 public static final String NAMESPACE = MUCInitialPresence.NAMESPACE + "#user"; 041 042 private final Set<Status> statusCodes = new HashSet<Status>(4); 043 044 private Invite invite; 045 private Decline decline; 046 private MUCItem item; 047 private String password; 048 private Destroy destroy; 049 050 public String getElementName() { 051 return ELEMENT; 052 } 053 054 public String getNamespace() { 055 return NAMESPACE; 056 } 057 058 @Override 059 public XmlStringBuilder toXML() { 060 XmlStringBuilder xml = new XmlStringBuilder(this); 061 xml.rightAngleBracket(); 062 xml.optElement(getInvite()); 063 xml.optElement(getDecline()); 064 xml.optElement(getItem()); 065 xml.optElement("password", getPassword()); 066 xml.append(statusCodes); 067 xml.optElement(getDestroy()); 068 xml.closeElement(this); 069 return xml; 070 } 071 072 /** 073 * Returns the invitation for another user to a room. The sender of the invitation 074 * must be an occupant of the room. The invitation will be sent to the room which in turn 075 * will forward the invitation to the invitee. 076 * 077 * @return an invitation for another user to a room. 078 */ 079 public Invite getInvite() { 080 return invite; 081 } 082 083 /** 084 * Returns the rejection to an invitation from another user to a room. The rejection will be 085 * sent to the room which in turn will forward the refusal to the inviter. 086 * 087 * @return a rejection to an invitation from another user to a room. 088 */ 089 public Decline getDecline() { 090 return decline; 091 } 092 093 /** 094 * Returns the item child that holds information about roles, affiliation, jids and nicks. 095 * 096 * @return an item child that holds information about roles, affiliation, jids and nicks. 097 */ 098 public MUCItem getItem() { 099 return item; 100 } 101 102 /** 103 * Returns the password to use to enter Password-Protected Room. A Password-Protected Room is 104 * a room that a user cannot enter without first providing the correct password. 105 * 106 * @return the password to use to enter Password-Protected Room. 107 */ 108 public String getPassword() { 109 return password; 110 } 111 112 /** 113 * Returns a set of status which holds the status code that assist in presenting notification messages. 114 * 115 * @return the set of status which holds the status code that assist in presenting notification messages. 116 */ 117 public Set<Status> getStatus() { 118 return statusCodes; 119 } 120 121 /** 122 * Returns true if this MUCUser instance has also {@link Status} information. 123 * <p> 124 * If <code>true</code> is returned, then {@link #getStatus()} will return a non-empty set. 125 * </p> 126 * 127 * @return true if this MUCUser has status information. 128 * @since 4.1 129 */ 130 public boolean hasStatus() { 131 return !statusCodes.isEmpty(); 132 } 133 134 /** 135 * Returns the notification that the room has been destroyed. After a room has been destroyed, 136 * the room occupants will receive a Presence stanza(/packet) of type 'unavailable' with the reason for 137 * the room destruction if provided by the room owner. 138 * 139 * @return a notification that the room has been destroyed. 140 */ 141 public Destroy getDestroy() { 142 return destroy; 143 } 144 145 /** 146 * Sets the invitation for another user to a room. The sender of the invitation 147 * must be an occupant of the room. The invitation will be sent to the room which in turn 148 * will forward the invitation to the invitee. 149 * 150 * @param invite the invitation for another user to a room. 151 */ 152 public void setInvite(Invite invite) { 153 this.invite = invite; 154 } 155 156 /** 157 * Sets the rejection to an invitation from another user to a room. The rejection will be 158 * sent to the room which in turn will forward the refusal to the inviter. 159 * 160 * @param decline the rejection to an invitation from another user to a room. 161 */ 162 public void setDecline(Decline decline) { 163 this.decline = decline; 164 } 165 166 /** 167 * Sets the item child that holds information about roles, affiliation, jids and nicks. 168 * 169 * @param item the item child that holds information about roles, affiliation, jids and nicks. 170 */ 171 public void setItem(MUCItem item) { 172 this.item = item; 173 } 174 175 /** 176 * Sets the password to use to enter Password-Protected Room. A Password-Protected Room is 177 * a room that a user cannot enter without first providing the correct password. 178 * 179 * @param string the password to use to enter Password-Protected Room. 180 */ 181 public void setPassword(String string) { 182 password = string; 183 } 184 185 /** 186 * Add the status codes which holds the codes that assists in presenting notification messages. 187 * 188 * @param statusCodes the status codes which hold the codes that assists in presenting notification 189 * messages. 190 */ 191 public void addStatusCodes(Set<Status> statusCodes) { 192 this.statusCodes.addAll(statusCodes); 193 } 194 195 /** 196 * Add a status code which hold a code that assists in presenting notification messages. 197 * 198 * @param status the status code which olds a code that assists in presenting notification messages. 199 */ 200 public void addStatusCode(Status status) { 201 this.statusCodes.add(status); 202 } 203 204 /** 205 * Sets the notification that the room has been destroyed. After a room has been destroyed, 206 * the room occupants will receive a Presence stanza(/packet) of type 'unavailable' with the reason for 207 * the room destruction if provided by the room owner. 208 * 209 * @param destroy the notification that the room has been destroyed. 210 */ 211 public void setDestroy(Destroy destroy) { 212 this.destroy = destroy; 213 } 214 215 /** 216 * Retrieve the MUCUser PacketExtension from packet, if any. 217 * 218 * @param packet 219 * @return the MUCUser PacketExtension or {@code null} 220 * @deprecated use {@link #from(Stanza)} instead 221 */ 222 @Deprecated 223 public static MUCUser getFrom(Stanza packet) { 224 return from(packet); 225 } 226 227 /** 228 * Retrieve the MUCUser PacketExtension from packet, if any. 229 * 230 * @param packet 231 * @return the MUCUser PacketExtension or {@code null} 232 */ 233 public static MUCUser from(Stanza packet) { 234 return packet.getExtension(ELEMENT, NAMESPACE); 235 } 236 237 /** 238 * Represents an invitation for another user to a room. The sender of the invitation 239 * must be an occupant of the room. The invitation will be sent to the room which in turn 240 * will forward the invitation to the invitee. 241 * 242 * @author Gaston Dombiak 243 */ 244 public static class Invite implements NamedElement { 245 public static final String ELEMENT ="invite"; 246 247 private String reason; 248 private String from; 249 private String to; 250 251 /** 252 * Returns the bare JID of the inviter or, optionally, the room JID. (e.g. 253 * 'crone1@shakespeare.lit/desktop'). 254 * 255 * @return the room's occupant that sent the invitation. 256 */ 257 public String getFrom() { 258 return from; 259 } 260 261 /** 262 * Returns the message explaining the invitation. 263 * 264 * @return the message explaining the invitation. 265 */ 266 public String getReason() { 267 return reason; 268 } 269 270 /** 271 * Returns the bare JID of the invitee. (e.g. 'hecate@shakespeare.lit') 272 * 273 * @return the bare JID of the invitee. 274 */ 275 public String getTo() { 276 return to; 277 } 278 279 /** 280 * Sets the bare JID of the inviter or, optionally, the room JID. (e.g. 281 * 'crone1@shakespeare.lit/desktop') 282 * 283 * @param from the bare JID of the inviter or, optionally, the room JID. 284 */ 285 public void setFrom(String from) { 286 this.from = from; 287 } 288 289 /** 290 * Sets the message explaining the invitation. 291 * 292 * @param reason the message explaining the invitation. 293 */ 294 public void setReason(String reason) { 295 this.reason = reason; 296 } 297 298 /** 299 * Sets the bare JID of the invitee. (e.g. 'hecate@shakespeare.lit') 300 * 301 * @param to the bare JID of the invitee. 302 */ 303 public void setTo(String to) { 304 this.to = to; 305 } 306 307 @Override 308 public XmlStringBuilder toXML() { 309 XmlStringBuilder xml = new XmlStringBuilder(this); 310 xml.optAttribute("to", getTo()); 311 xml.optAttribute("from", getFrom()); 312 xml.rightAngleBracket(); 313 xml.optElement("reason", getReason()); 314 xml.closeElement(this); 315 return xml; 316 } 317 318 @Override 319 public String getElementName() { 320 return ELEMENT; 321 } 322 } 323 324 /** 325 * Represents a rejection to an invitation from another user to a room. The rejection will be 326 * sent to the room which in turn will forward the refusal to the inviter. 327 * 328 * @author Gaston Dombiak 329 */ 330 public static class Decline implements NamedElement { 331 public static final String ELEMENT = "decline"; 332 333 private String reason; 334 private String from; 335 private String to; 336 337 /** 338 * Returns the bare JID of the invitee that rejected the invitation. (e.g. 339 * 'crone1@shakespeare.lit/desktop'). 340 * 341 * @return the bare JID of the invitee that rejected the invitation. 342 */ 343 public String getFrom() { 344 return from; 345 } 346 347 /** 348 * Returns the message explaining why the invitation was rejected. 349 * 350 * @return the message explaining the reason for the rejection. 351 */ 352 public String getReason() { 353 return reason; 354 } 355 356 /** 357 * Returns the bare JID of the inviter. (e.g. 'hecate@shakespeare.lit') 358 * 359 * @return the bare JID of the inviter. 360 */ 361 public String getTo() { 362 return to; 363 } 364 365 /** 366 * Sets the bare JID of the invitee that rejected the invitation. (e.g. 367 * 'crone1@shakespeare.lit/desktop'). 368 * 369 * @param from the bare JID of the invitee that rejected the invitation. 370 */ 371 public void setFrom(String from) { 372 this.from = from; 373 } 374 375 /** 376 * Sets the message explaining why the invitation was rejected. 377 * 378 * @param reason the message explaining the reason for the rejection. 379 */ 380 public void setReason(String reason) { 381 this.reason = reason; 382 } 383 384 /** 385 * Sets the bare JID of the inviter. (e.g. 'hecate@shakespeare.lit') 386 * 387 * @param to the bare JID of the inviter. 388 */ 389 public void setTo(String to) { 390 this.to = to; 391 } 392 393 @Override 394 public XmlStringBuilder toXML() { 395 XmlStringBuilder xml = new XmlStringBuilder(this); 396 xml.optAttribute("to", getTo()); 397 xml.optAttribute("from", getFrom()); 398 xml.rightAngleBracket(); 399 xml.optElement("reason", getReason()); 400 xml.closeElement(this); 401 return xml; 402 } 403 404 @Override 405 public String getElementName() { 406 return ELEMENT; 407 } 408 } 409 410 /** 411 * Status code assists in presenting notification messages. The following link provides the 412 * list of existing error codes <a href="http://xmpp.org/registrar/mucstatus.html">Multi-User Chat Status Codes</a>. 413 * 414 * @author Gaston Dombiak 415 */ 416 public static class Status implements NamedElement { 417 public static final String ELEMENT = "status"; 418 419 private static final Map<Integer, Status> statusMap = new HashMap<Integer, Status>(8); 420 421 public static final Status ROOM_CREATED_201 = Status.create(201); 422 public static final Status BANNED_301 = Status.create(301); 423 public static final Status NEW_NICKNAME_303 = Status.create(303); 424 public static final Status KICKED_307 = Status.create(307); 425 public static final Status REMOVED_AFFIL_CHANGE_321 = Status.create(321); 426 427 private final Integer code; 428 429 public static Status create(String string) { 430 Integer integer = Integer.valueOf(string); 431 return create(integer); 432 } 433 434 public static Status create(Integer i) { 435 Status status = statusMap.get(i); 436 if (status == null) { 437 status = new Status(i); 438 statusMap.put(i, status); 439 } 440 return status; 441 } 442 443 /** 444 * Creates a new instance of Status with the specified code. 445 * 446 * @param code the code that uniquely identifies the reason of the error. 447 */ 448 private Status(int code) { 449 this.code = code; 450 } 451 452 /** 453 * Returns the code that uniquely identifies the reason of the error. The code 454 * assists in presenting notification messages. 455 * 456 * @return the code that uniquely identifies the reason of the error. 457 */ 458 public int getCode() { 459 return code; 460 } 461 462 @Override 463 public XmlStringBuilder toXML() { 464 XmlStringBuilder xml = new XmlStringBuilder(this); 465 xml.attribute("code", getCode()); 466 xml.closeEmptyElement(); 467 return xml; 468 } 469 470 @Override 471 public boolean equals(Object other) { 472 if (other == null) { 473 return false; 474 } 475 if (other instanceof Status) { 476 Status otherStatus = (Status) other; 477 return code.equals(otherStatus.getCode()); 478 } 479 return false; 480 } 481 482 @Override 483 public int hashCode() { 484 return code; 485 } 486 487 @Override 488 public String getElementName() { 489 return ELEMENT; 490 } 491 } 492}