• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.smackx.packet;
22 
23 import org.jivesoftware.smack.packet.PacketExtension;
24 
25 import java.util.ArrayList;
26 import 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  */
59 public 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     */
getElementName()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      */
getNamespace()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      */
isComposing()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      */
isDelivered()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      */
isDisplayed()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      */
isOffline()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      */
isCancelled()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      */
getPacketID()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      */
getEventTypes()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      */
setComposing(boolean composing)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      */
setDelivered(boolean delivered)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      */
setDisplayed(boolean displayed)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      */
setOffline(boolean offline)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      */
setCancelled(boolean cancelled)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      */
setPacketID(String packetID)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      */
isMessageEventRequest()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      */
toXML()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 }
336