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