Home | History | Annotate | Download | only in packet
      1 /**
      2  * $RCSfile$
      3  * $Revision$
      4  * $Date$
      5  *
      6  * Copyright 2003-2007 Jive Software.
      7  *
      8  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
      9  * you may not use this file except in compliance with the License.
     10  * You may obtain a copy of the License at
     11  *
     12  *     http://www.apache.org/licenses/LICENSE-2.0
     13  *
     14  * Unless required by applicable law or agreed to in writing, software
     15  * distributed under the License is distributed on an "AS IS" BASIS,
     16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17  * See the License for the specific language governing permissions and
     18  * limitations under the License.
     19  */
     20 
     21 package org.jivesoftware.smack.packet;
     22 
     23 import org.jivesoftware.smack.util.StringUtils;
     24 
     25 /**
     26  * Represents XMPP presence packets. Every presence packet has a type, which is one of
     27  * the following values:
     28  * <ul>
     29  *      <li>{@link Presence.Type#available available} -- (Default) indicates the user is available to
     30  *          receive messages.
     31  *      <li>{@link Presence.Type#unavailable unavailable} -- the user is unavailable to receive messages.
     32  *      <li>{@link Presence.Type#subscribe subscribe} -- request subscription to recipient's presence.
     33  *      <li>{@link Presence.Type#subscribed subscribed} -- grant subscription to sender's presence.
     34  *      <li>{@link Presence.Type#unsubscribe unsubscribe} -- request removal of subscription to
     35  *          sender's presence.
     36  *      <li>{@link Presence.Type#unsubscribed unsubscribed} -- grant removal of subscription to
     37  *          sender's presence.
     38  *      <li>{@link Presence.Type#error error} -- the presence packet contains an error message.
     39  * </ul><p>
     40  *
     41  * A number of attributes are optional:
     42  * <ul>
     43  *      <li>Status -- free-form text describing a user's presence (i.e., gone to lunch).
     44  *      <li>Priority -- non-negative numerical priority of a sender's resource. The
     45  *          highest resource priority is the default recipient of packets not addressed
     46  *          to a particular resource.
     47  *      <li>Mode -- one of five presence modes: {@link Mode#available available} (the default),
     48  *          {@link Mode#chat chat}, {@link Mode#away away}, {@link Mode#xa xa} (extended away), and
     49  *          {@link Mode#dnd dnd} (do not disturb).
     50  * </ul><p>
     51  *
     52  * Presence packets are used for two purposes. First, to notify the server of our
     53  * the clients current presence status. Second, they are used to subscribe and
     54  * unsubscribe users from the roster.
     55  *
     56  * @see RosterPacket
     57  * @author Matt Tucker
     58  */
     59 public class Presence extends Packet {
     60 
     61     private Type type = Type.available;
     62     private String status = null;
     63     private int priority = Integer.MIN_VALUE;
     64     private Mode mode = null;
     65     private String language;
     66 
     67     /**
     68      * Creates a new presence update. Status, priority, and mode are left un-set.
     69      *
     70      * @param type the type.
     71      */
     72     public Presence(Type type) {
     73         setType(type);
     74     }
     75 
     76     /**
     77      * Creates a new presence update with a specified status, priority, and mode.
     78      *
     79      * @param type the type.
     80      * @param status a text message describing the presence update.
     81      * @param priority the priority of this presence update.
     82      * @param mode the mode type for this presence update.
     83      */
     84     public Presence(Type type, String status, int priority, Mode mode) {
     85         setType(type);
     86         setStatus(status);
     87         setPriority(priority);
     88         setMode(mode);
     89     }
     90 
     91     /**
     92      * Returns true if the {@link Type presence type} is available (online) and
     93      * false if the user is unavailable (offline), or if this is a presence packet
     94      * involved in a subscription operation. This is a convenience method
     95      * equivalent to <tt>getType() == Presence.Type.available</tt>. Note that even
     96      * when the user is available, their presence mode may be {@link Mode#away away},
     97      * {@link Mode#xa extended away} or {@link Mode#dnd do not disturb}. Use
     98      * {@link #isAway()} to determine if the user is away.
     99      *
    100      * @return true if the presence type is available.
    101      */
    102     public boolean isAvailable() {
    103         return type == Type.available;
    104     }
    105 
    106     /**
    107      * Returns true if the presence type is {@link Type#available available} and the presence
    108      * mode is {@link Mode#away away}, {@link Mode#xa extended away}, or
    109      * {@link Mode#dnd do not disturb}. False will be returned when the type or mode
    110      * is any other value, including when the presence type is unavailable (offline).
    111      * This is a convenience method equivalent to
    112      * <tt>type == Type.available && (mode == Mode.away || mode == Mode.xa || mode == Mode.dnd)</tt>.
    113      *
    114      * @return true if the presence type is available and the presence mode is away, xa, or dnd.
    115      */
    116     public boolean isAway() {
    117         return type == Type.available && (mode == Mode.away || mode == Mode.xa || mode == Mode.dnd);
    118     }
    119 
    120     /**
    121      * Returns the type of this presence packet.
    122      *
    123      * @return the type of the presence packet.
    124      */
    125     public Type getType() {
    126         return type;
    127     }
    128 
    129     /**
    130      * Sets the type of the presence packet.
    131      *
    132      * @param type the type of the presence packet.
    133      */
    134     public void setType(Type type) {
    135         if(type == null) {
    136             throw new NullPointerException("Type cannot be null");
    137         }
    138         this.type = type;
    139     }
    140 
    141     /**
    142      * Returns the status message of the presence update, or <tt>null</tt> if there
    143      * is not a status. The status is free-form text describing a user's presence
    144      * (i.e., "gone to lunch").
    145      *
    146      * @return the status message.
    147      */
    148     public String getStatus() {
    149         return status;
    150     }
    151 
    152     /**
    153      * Sets the status message of the presence update. The status is free-form text
    154      * describing a user's presence (i.e., "gone to lunch").
    155      *
    156      * @param status the status message.
    157      */
    158     public void setStatus(String status) {
    159         this.status = status;
    160     }
    161 
    162     /**
    163      * Returns the priority of the presence, or Integer.MIN_VALUE if no priority has been set.
    164      *
    165      * @return the priority.
    166      */
    167     public int getPriority() {
    168         return priority;
    169     }
    170 
    171     /**
    172      * Sets the priority of the presence. The valid range is -128 through 128.
    173      *
    174      * @param priority the priority of the presence.
    175      * @throws IllegalArgumentException if the priority is outside the valid range.
    176      */
    177     public void setPriority(int priority) {
    178         if (priority < -128 || priority > 128) {
    179             throw new IllegalArgumentException("Priority value " + priority +
    180                     " is not valid. Valid range is -128 through 128.");
    181         }
    182         this.priority = priority;
    183     }
    184 
    185     /**
    186      * Returns the mode of the presence update, or <tt>null</tt> if the mode is not set.
    187      * A null presence mode value is interpreted to be the same thing as
    188      * {@link Presence.Mode#available}.
    189      *
    190      * @return the mode.
    191      */
    192     public Mode getMode() {
    193         return mode;
    194     }
    195 
    196     /**
    197      * Sets the mode of the presence update. A null presence mode value is interpreted
    198      * to be the same thing as {@link Presence.Mode#available}.
    199      *
    200      * @param mode the mode.
    201      */
    202     public void setMode(Mode mode) {
    203         this.mode = mode;
    204     }
    205 
    206     /**
    207      * Returns the xml:lang of this Presence, or null if one has not been set.
    208      *
    209      * @return the xml:lang of this Presence, or null if one has not been set.
    210      * @since 3.0.2
    211      */
    212     public String getLanguage() {
    213         return language;
    214     }
    215 
    216     /**
    217      * Sets the xml:lang of this Presence.
    218      *
    219      * @param language the xml:lang of this Presence.
    220      * @since 3.0.2
    221      */
    222     public void setLanguage(String language) {
    223         this.language = language;
    224     }
    225 
    226     public String toXML() {
    227         StringBuilder buf = new StringBuilder();
    228         buf.append("<presence");
    229         if(getXmlns() != null) {
    230             buf.append(" xmlns=\"").append(getXmlns()).append("\"");
    231         }
    232         if (language != null) {
    233             buf.append(" xml:lang=\"").append(getLanguage()).append("\"");
    234         }
    235         if (getPacketID() != null) {
    236             buf.append(" id=\"").append(getPacketID()).append("\"");
    237         }
    238         if (getTo() != null) {
    239             buf.append(" to=\"").append(StringUtils.escapeForXML(getTo())).append("\"");
    240         }
    241         if (getFrom() != null) {
    242             buf.append(" from=\"").append(StringUtils.escapeForXML(getFrom())).append("\"");
    243         }
    244         if (type != Type.available) {
    245             buf.append(" type=\"").append(type).append("\"");
    246         }
    247         buf.append(">");
    248         if (status != null) {
    249             buf.append("<status>").append(StringUtils.escapeForXML(status)).append("</status>");
    250         }
    251         if (priority != Integer.MIN_VALUE) {
    252             buf.append("<priority>").append(priority).append("</priority>");
    253         }
    254         if (mode != null && mode != Mode.available) {
    255             buf.append("<show>").append(mode).append("</show>");
    256         }
    257 
    258         buf.append(this.getExtensionsXML());
    259 
    260         // Add the error sub-packet, if there is one.
    261         XMPPError error = getError();
    262         if (error != null) {
    263             buf.append(error.toXML());
    264         }
    265 
    266         buf.append("</presence>");
    267 
    268         return buf.toString();
    269     }
    270 
    271     public String toString() {
    272         StringBuilder buf = new StringBuilder();
    273         buf.append(type);
    274         if (mode != null) {
    275             buf.append(": ").append(mode);
    276         }
    277         if (getStatus() != null) {
    278             buf.append(" (").append(getStatus()).append(")");
    279         }
    280         return buf.toString();
    281     }
    282 
    283     /**
    284      * A enum to represent the presecence type. Not that presence type is often confused
    285      * with presence mode. Generally, if a user is signed into a server, they have a presence
    286      * type of {@link #available available}, even if the mode is {@link Mode#away away},
    287      * {@link Mode#dnd dnd}, etc. The presence type is only {@link #unavailable unavailable} when
    288      * the user is signing out of the server.
    289      */
    290     public enum Type {
    291 
    292        /**
    293         * The user is available to receive messages (default).
    294         */
    295         available,
    296 
    297         /**
    298          * The user is unavailable to receive messages.
    299          */
    300         unavailable,
    301 
    302         /**
    303          * Request subscription to recipient's presence.
    304          */
    305         subscribe,
    306 
    307         /**
    308          * Grant subscription to sender's presence.
    309          */
    310         subscribed,
    311 
    312         /**
    313          * Request removal of subscription to sender's presence.
    314          */
    315         unsubscribe,
    316 
    317         /**
    318          * Grant removal of subscription to sender's presence.
    319          */
    320         unsubscribed,
    321 
    322         /**
    323          * The presence packet contains an error message.
    324          */
    325         error
    326     }
    327 
    328     /**
    329      * An enum to represent the presence mode.
    330      */
    331     public enum Mode {
    332 
    333         /**
    334          * Free to chat.
    335          */
    336         chat,
    337 
    338         /**
    339          * Available (the default).
    340          */
    341         available,
    342 
    343         /**
    344          * Away.
    345          */
    346         away,
    347 
    348         /**
    349          * Away for an extended period of time.
    350          */
    351         xa,
    352 
    353         /**
    354          * Do not disturb.
    355          */
    356         dnd
    357     }
    358 }