blob: 5e146dc58359957161f1ad719d236c55d579ca99 [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001/**
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
21package org.jivesoftware.smackx.packet;
22
23import org.jivesoftware.smack.packet.PacketExtension;
24
25import java.util.ArrayList;
26import java.util.Iterator;
27
28/**
29 * Represents message events relating to the delivery, display, composition and cancellation of
30 * messages.<p>
31 *
32 * There are four message events currently defined in this namespace:
33 * <ol>
34 * <li>Offline<br>
35 * Indicates that the message has been stored offline by the intended recipient's server. This
36 * event is triggered only if the intended recipient's server supports offline storage, has that
37 * support enabled, and the recipient is offline when the server receives the message for delivery.</li>
38 *
39 * <li>Delivered<br>
40 * Indicates that the message has been delivered to the recipient. This signifies that the message
41 * has reached the recipient's XMPP client, but does not necessarily mean that the message has
42 * been displayed. This event is to be raised by the XMPP client.</li>
43 *
44 * <li>Displayed<br>
45 * Once the message has been received by the recipient's XMPP client, it may be displayed to the
46 * user. This event indicates that the message has been displayed, and is to be raised by the
47 * XMPP client. Even if a message is displayed multiple times, this event should be raised only
48 * once.</li>
49 *
50 * <li>Composing<br>
51 * In threaded chat conversations, this indicates that the recipient is composing a reply to a
52 * message. The event is to be raised by the recipient's XMPP client. A XMPP client is allowed
53 * to raise this event multiple times in response to the same request, providing the original
54 * event is cancelled first.</li>
55 * </ol>
56 *
57 * @author Gaston Dombiak
58 */
59public class MessageEvent implements PacketExtension {
60
61 public static final String OFFLINE = "offline";
62 public static final String COMPOSING = "composing";
63 public static final String DISPLAYED = "displayed";
64 public static final String DELIVERED = "delivered";
65 public static final String CANCELLED = "cancelled";
66
67 private boolean offline = false;
68 private boolean delivered = false;
69 private boolean displayed = false;
70 private boolean composing = false;
71 private boolean cancelled = true;
72
73 private String packetID = null;
74
75 /**
76 * Returns the XML element name of the extension sub-packet root element.
77 * Always returns "x"
78 *
79 * @return the XML element name of the packet extension.
80 */
81 public String getElementName() {
82 return "x";
83 }
84
85 /**
86 * Returns the XML namespace of the extension sub-packet root element.
87 * According the specification the namespace is always "jabber:x:event"
88 *
89 * @return the XML namespace of the packet extension.
90 */
91 public String getNamespace() {
92 return "jabber:x:event";
93 }
94
95 /**
96 * When the message is a request returns if the sender of the message requests to be notified
97 * when the receiver is composing a reply.
98 * When the message is a notification returns if the receiver of the message is composing a
99 * reply.
100 *
101 * @return true if the sender is requesting to be notified when composing or when notifying
102 * that the receiver of the message is composing a reply
103 */
104 public boolean isComposing() {
105 return composing;
106 }
107
108 /**
109 * When the message is a request returns if the sender of the message requests to be notified
110 * when the message is delivered.
111 * When the message is a notification returns if the message was delivered or not.
112 *
113 * @return true if the sender is requesting to be notified when delivered or when notifying
114 * that the message was delivered
115 */
116 public boolean isDelivered() {
117 return delivered;
118 }
119
120 /**
121 * When the message is a request returns if the sender of the message requests to be notified
122 * when the message is displayed.
123 * When the message is a notification returns if the message was displayed or not.
124 *
125 * @return true if the sender is requesting to be notified when displayed or when notifying
126 * that the message was displayed
127 */
128 public boolean isDisplayed() {
129 return displayed;
130 }
131
132 /**
133 * When the message is a request returns if the sender of the message requests to be notified
134 * when the receiver of the message is offline.
135 * When the message is a notification returns if the receiver of the message was offline.
136 *
137 * @return true if the sender is requesting to be notified when offline or when notifying
138 * that the receiver of the message is offline
139 */
140 public boolean isOffline() {
141 return offline;
142 }
143
144 /**
145 * When the message is a notification returns if the receiver of the message cancelled
146 * composing a reply.
147 *
148 * @return true if the receiver of the message cancelled composing a reply
149 */
150 public boolean isCancelled() {
151 return cancelled;
152 }
153
154 /**
155 * Returns the unique ID of the message that requested to be notified of the event.
156 * The packet id is not used when the message is a request for notifications
157 *
158 * @return the message id that requested to be notified of the event.
159 */
160 public String getPacketID() {
161 return packetID;
162 }
163
164 /**
165 * Returns the types of events. The type of event could be:
166 * "offline", "composing","delivered","displayed", "offline"
167 *
168 * @return an iterator over all the types of events of the MessageEvent.
169 */
170 public Iterator<String> getEventTypes() {
171 ArrayList<String> allEvents = new ArrayList<String>();
172 if (isDelivered()) {
173 allEvents.add(MessageEvent.DELIVERED);
174 }
175 if (!isMessageEventRequest() && isCancelled()) {
176 allEvents.add(MessageEvent.CANCELLED);
177 }
178 if (isComposing()) {
179 allEvents.add(MessageEvent.COMPOSING);
180 }
181 if (isDisplayed()) {
182 allEvents.add(MessageEvent.DISPLAYED);
183 }
184 if (isOffline()) {
185 allEvents.add(MessageEvent.OFFLINE);
186 }
187 return allEvents.iterator();
188 }
189
190 /**
191 * When the message is a request sets if the sender of the message requests to be notified
192 * when the receiver is composing a reply.
193 * When the message is a notification sets if the receiver of the message is composing a
194 * reply.
195 *
196 * @param composing sets if the sender is requesting to be notified when composing or when
197 * notifying that the receiver of the message is composing a reply
198 */
199 public void setComposing(boolean composing) {
200 this.composing = composing;
201 setCancelled(false);
202 }
203
204 /**
205 * When the message is a request sets if the sender of the message requests to be notified
206 * when the message is delivered.
207 * When the message is a notification sets if the message was delivered or not.
208 *
209 * @param delivered sets if the sender is requesting to be notified when delivered or when
210 * notifying that the message was delivered
211 */
212 public void setDelivered(boolean delivered) {
213 this.delivered = delivered;
214 setCancelled(false);
215 }
216
217 /**
218 * When the message is a request sets if the sender of the message requests to be notified
219 * when the message is displayed.
220 * When the message is a notification sets if the message was displayed or not.
221 *
222 * @param displayed sets if the sender is requesting to be notified when displayed or when
223 * notifying that the message was displayed
224 */
225 public void setDisplayed(boolean displayed) {
226 this.displayed = displayed;
227 setCancelled(false);
228 }
229
230 /**
231 * When the message is a request sets if the sender of the message requests to be notified
232 * when the receiver of the message is offline.
233 * When the message is a notification sets if the receiver of the message was offline.
234 *
235 * @param offline sets if the sender is requesting to be notified when offline or when
236 * notifying that the receiver of the message is offline
237 */
238 public void setOffline(boolean offline) {
239 this.offline = offline;
240 setCancelled(false);
241 }
242
243 /**
244 * When the message is a notification sets if the receiver of the message cancelled
245 * composing a reply.
246 * The Cancelled event is never requested explicitly. It is requested implicitly when
247 * requesting to be notified of the Composing event.
248 *
249 * @param cancelled sets if the receiver of the message cancelled composing a reply
250 */
251 public void setCancelled(boolean cancelled) {
252 this.cancelled = cancelled;
253 }
254
255 /**
256 * Sets the unique ID of the message that requested to be notified of the event.
257 * The packet id is not used when the message is a request for notifications
258 *
259 * @param packetID the message id that requested to be notified of the event.
260 */
261 public void setPacketID(String packetID) {
262 this.packetID = packetID;
263 }
264
265 /**
266 * Returns true if this MessageEvent is a request for notifications.
267 * Returns false if this MessageEvent is a notification of an event.
268 *
269 * @return true if this message is a request for notifications.
270 */
271 public boolean isMessageEventRequest() {
272 return this.packetID == null;
273 }
274
275 /**
276 * Returns the XML representation of a Message Event according the specification.
277 *
278 * Usually the XML representation will be inside of a Message XML representation like
279 * in the following examples:<p>
280 *
281 * Request to be notified when displayed:
282 * <pre>
283 * &lt;message
284 * to='romeo@montague.net/orchard'
285 * from='juliet@capulet.com/balcony'
286 * id='message22'&gt;
287 * &lt;x xmlns='jabber:x:event'&gt;
288 * &lt;displayed/&gt;
289 * &lt;/x&gt;
290 * &lt;/message&gt;
291 * </pre>
292 *
293 * Notification of displayed:
294 * <pre>
295 * &lt;message
296 * from='romeo@montague.net/orchard'
297 * to='juliet@capulet.com/balcony'&gt;
298 * &lt;x xmlns='jabber:x:event'&gt;
299 * &lt;displayed/&gt;
300 * &lt;id&gt;message22&lt;/id&gt;
301 * &lt;/x&gt;
302 * &lt;/message&gt;
303 * </pre>
304 *
305 */
306 public String toXML() {
307 StringBuilder buf = new StringBuilder();
308 buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
309 "\">");
310 // Note: Cancellation events don't specify any tag. They just send the packetID
311
312 // Add the offline tag if the sender requests to be notified of offline events or if
313 // the target is offline
314 if (isOffline())
315 buf.append("<").append(MessageEvent.OFFLINE).append("/>");
316 // Add the delivered tag if the sender requests to be notified when the message is
317 // delivered or if the target notifies that the message has been delivered
318 if (isDelivered())
319 buf.append("<").append(MessageEvent.DELIVERED).append("/>");
320 // Add the displayed tag if the sender requests to be notified when the message is
321 // displayed or if the target notifies that the message has been displayed
322 if (isDisplayed())
323 buf.append("<").append(MessageEvent.DISPLAYED).append("/>");
324 // Add the composing tag if the sender requests to be notified when the target is
325 // composing a reply or if the target notifies that he/she is composing a reply
326 if (isComposing())
327 buf.append("<").append(MessageEvent.COMPOSING).append("/>");
328 // Add the id tag only if the MessageEvent is a notification message (not a request)
329 if (getPacketID() != null)
330 buf.append("<id>").append(getPacketID()).append("</id>");
331 buf.append("</").append(getElementName()).append(">");
332 return buf.toString();
333 }
334
335}