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.xevent.packet; 019 020import org.jivesoftware.smack.packet.ExtensionElement; 021 022import java.util.ArrayList; 023import java.util.List; 024 025/** 026 * Represents message events relating to the delivery, display, composition and cancellation of 027 * messages.<p> 028 * 029 * There are four message events currently defined in this namespace: 030 * <ol> 031 * <li>Offline<br> 032 * Indicates that the message has been stored offline by the intended recipient's server. This 033 * event is triggered only if the intended recipient's server supports offline storage, has that 034 * support enabled, and the recipient is offline when the server receives the message for delivery.</li> 035 * 036 * <li>Delivered<br> 037 * Indicates that the message has been delivered to the recipient. This signifies that the message 038 * has reached the recipient's XMPP client, but does not necessarily mean that the message has 039 * been displayed. This event is to be raised by the XMPP client.</li> 040 * 041 * <li>Displayed<br> 042 * Once the message has been received by the recipient's XMPP client, it may be displayed to the 043 * user. This event indicates that the message has been displayed, and is to be raised by the 044 * XMPP client. Even if a message is displayed multiple times, this event should be raised only 045 * once.</li> 046 * 047 * <li>Composing<br> 048 * In threaded chat conversations, this indicates that the recipient is composing a reply to a 049 * message. The event is to be raised by the recipient's XMPP client. A XMPP client is allowed 050 * to raise this event multiple times in response to the same request, providing the original 051 * event is cancelled first.</li> 052 * </ol> 053 * 054 * @author Gaston Dombiak 055 */ 056public class MessageEvent implements ExtensionElement { 057 058 public static final String NAMESPACE = "jabber:x:event"; 059 public static final String ELEMENT = "x"; 060 061 public static final String OFFLINE = "offline"; 062 public static final String COMPOSING = "composing"; 063 public static final String DISPLAYED = "displayed"; 064 public static final String DELIVERED = "delivered"; 065 public static final String CANCELLED = "cancelled"; 066 067 private boolean offline = false; 068 private boolean delivered = false; 069 private boolean displayed = false; 070 private boolean composing = false; 071 private boolean cancelled = true; 072 073 private String packetID = null; 074 075 /** 076 * Returns the XML element name of the extension sub-packet root element. 077 * Always returns "x" 078 * 079 * @return the XML element name of the stanza(/packet) extension. 080 */ 081 public String getElementName() { 082 return ELEMENT; 083 } 084 085 /** 086 * Returns the XML namespace of the extension sub-packet root element. 087 * According the specification the namespace is always "jabber:x:event" 088 * 089 * @return the XML namespace of the stanza(/packet) extension. 090 */ 091 public String getNamespace() { 092 return NAMESPACE; 093 } 094 095 /** 096 * When the message is a request returns if the sender of the message requests to be notified 097 * when the receiver is composing a reply. 098 * When the message is a notification returns if the receiver of the message is composing a 099 * 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 stanza(/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 getStanzaId() { 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 a List of all the types of events of the MessageEvent. 169 */ 170 public List<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; 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 stanza(/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 setStanzaId(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 * <message 284 * to='romeo@montague.net/orchard' 285 * from='juliet@capulet.com/balcony' 286 * id='message22'> 287 * <x xmlns='jabber:x:event'> 288 * <displayed/> 289 * </x> 290 * </message> 291 * </pre> 292 * 293 * Notification of displayed: 294 * <pre> 295 * <message 296 * from='romeo@montague.net/orchard' 297 * to='juliet@capulet.com/balcony'> 298 * <x xmlns='jabber:x:event'> 299 * <displayed/> 300 * <id>message22</id> 301 * </x> 302 * </message> 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 (getStanzaId() != null) 330 buf.append("<id>").append(getStanzaId()).append("</id>"); 331 buf.append("</").append(getElementName()).append(">"); 332 return buf.toString(); 333 } 334 335}