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.PacketExtension; 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 PacketExtension { 057 058 public static final String OFFLINE = "offline"; 059 public static final String COMPOSING = "composing"; 060 public static final String DISPLAYED = "displayed"; 061 public static final String DELIVERED = "delivered"; 062 public static final String CANCELLED = "cancelled"; 063 064 private boolean offline = false; 065 private boolean delivered = false; 066 private boolean displayed = false; 067 private boolean composing = false; 068 private boolean cancelled = true; 069 070 private String packetID = null; 071 072 /** 073 * Returns the XML element name of the extension sub-packet root element. 074 * Always returns "x" 075 * 076 * @return the XML element name of the packet extension. 077 */ 078 public String getElementName() { 079 return "x"; 080 } 081 082 /** 083 * Returns the XML namespace of the extension sub-packet root element. 084 * According the specification the namespace is always "jabber:x:event" 085 * 086 * @return the XML namespace of the packet extension. 087 */ 088 public String getNamespace() { 089 return "jabber:x:event"; 090 } 091 092 /** 093 * When the message is a request returns if the sender of the message requests to be notified 094 * when the receiver is composing a reply. 095 * When the message is a notification returns if the receiver of the message is composing a 096 * reply. 097 * 098 * @return true if the sender is requesting to be notified when composing or when notifying 099 * that the receiver of the message is composing a reply 100 */ 101 public boolean isComposing() { 102 return composing; 103 } 104 105 /** 106 * When the message is a request returns if the sender of the message requests to be notified 107 * when the message is delivered. 108 * When the message is a notification returns if the message was delivered or not. 109 * 110 * @return true if the sender is requesting to be notified when delivered or when notifying 111 * that the message was delivered 112 */ 113 public boolean isDelivered() { 114 return delivered; 115 } 116 117 /** 118 * When the message is a request returns if the sender of the message requests to be notified 119 * when the message is displayed. 120 * When the message is a notification returns if the message was displayed or not. 121 * 122 * @return true if the sender is requesting to be notified when displayed or when notifying 123 * that the message was displayed 124 */ 125 public boolean isDisplayed() { 126 return displayed; 127 } 128 129 /** 130 * When the message is a request returns if the sender of the message requests to be notified 131 * when the receiver of the message is offline. 132 * When the message is a notification returns if the receiver of the message was offline. 133 * 134 * @return true if the sender is requesting to be notified when offline or when notifying 135 * that the receiver of the message is offline 136 */ 137 public boolean isOffline() { 138 return offline; 139 } 140 141 /** 142 * When the message is a notification returns if the receiver of the message cancelled 143 * composing a reply. 144 * 145 * @return true if the receiver of the message cancelled composing a reply 146 */ 147 public boolean isCancelled() { 148 return cancelled; 149 } 150 151 /** 152 * Returns the unique ID of the message that requested to be notified of the event. 153 * The packet id is not used when the message is a request for notifications 154 * 155 * @return the message id that requested to be notified of the event. 156 */ 157 public String getPacketID() { 158 return packetID; 159 } 160 161 /** 162 * Returns the types of events. The type of event could be: 163 * "offline", "composing","delivered","displayed", "offline" 164 * 165 * @return a List of all the types of events of the MessageEvent. 166 */ 167 public List<String> getEventTypes() { 168 ArrayList<String> allEvents = new ArrayList<String>(); 169 if (isDelivered()) { 170 allEvents.add(MessageEvent.DELIVERED); 171 } 172 if (!isMessageEventRequest() && isCancelled()) { 173 allEvents.add(MessageEvent.CANCELLED); 174 } 175 if (isComposing()) { 176 allEvents.add(MessageEvent.COMPOSING); 177 } 178 if (isDisplayed()) { 179 allEvents.add(MessageEvent.DISPLAYED); 180 } 181 if (isOffline()) { 182 allEvents.add(MessageEvent.OFFLINE); 183 } 184 return allEvents; 185 } 186 187 /** 188 * When the message is a request sets if the sender of the message requests to be notified 189 * when the receiver is composing a reply. 190 * When the message is a notification sets if the receiver of the message is composing a 191 * reply. 192 * 193 * @param composing sets if the sender is requesting to be notified when composing or when 194 * notifying that the receiver of the message is composing a reply 195 */ 196 public void setComposing(boolean composing) { 197 this.composing = composing; 198 setCancelled(false); 199 } 200 201 /** 202 * When the message is a request sets if the sender of the message requests to be notified 203 * when the message is delivered. 204 * When the message is a notification sets if the message was delivered or not. 205 * 206 * @param delivered sets if the sender is requesting to be notified when delivered or when 207 * notifying that the message was delivered 208 */ 209 public void setDelivered(boolean delivered) { 210 this.delivered = delivered; 211 setCancelled(false); 212 } 213 214 /** 215 * When the message is a request sets if the sender of the message requests to be notified 216 * when the message is displayed. 217 * When the message is a notification sets if the message was displayed or not. 218 * 219 * @param displayed sets if the sender is requesting to be notified when displayed or when 220 * notifying that the message was displayed 221 */ 222 public void setDisplayed(boolean displayed) { 223 this.displayed = displayed; 224 setCancelled(false); 225 } 226 227 /** 228 * When the message is a request sets if the sender of the message requests to be notified 229 * when the receiver of the message is offline. 230 * When the message is a notification sets if the receiver of the message was offline. 231 * 232 * @param offline sets if the sender is requesting to be notified when offline or when 233 * notifying that the receiver of the message is offline 234 */ 235 public void setOffline(boolean offline) { 236 this.offline = offline; 237 setCancelled(false); 238 } 239 240 /** 241 * When the message is a notification sets if the receiver of the message cancelled 242 * composing a reply. 243 * The Cancelled event is never requested explicitly. It is requested implicitly when 244 * requesting to be notified of the Composing event. 245 * 246 * @param cancelled sets if the receiver of the message cancelled composing a reply 247 */ 248 public void setCancelled(boolean cancelled) { 249 this.cancelled = cancelled; 250 } 251 252 /** 253 * Sets the unique ID of the message that requested to be notified of the event. 254 * The packet id is not used when the message is a request for notifications 255 * 256 * @param packetID the message id that requested to be notified of the event. 257 */ 258 public void setPacketID(String packetID) { 259 this.packetID = packetID; 260 } 261 262 /** 263 * Returns true if this MessageEvent is a request for notifications. 264 * Returns false if this MessageEvent is a notification of an event. 265 * 266 * @return true if this message is a request for notifications. 267 */ 268 public boolean isMessageEventRequest() { 269 return this.packetID == null; 270 } 271 272 /** 273 * Returns the XML representation of a Message Event according the specification. 274 * 275 * Usually the XML representation will be inside of a Message XML representation like 276 * in the following examples:<p> 277 * 278 * Request to be notified when displayed: 279 * <pre> 280 * <message 281 * to='romeo@montague.net/orchard' 282 * from='juliet@capulet.com/balcony' 283 * id='message22'> 284 * <x xmlns='jabber:x:event'> 285 * <displayed/> 286 * </x> 287 * </message> 288 * </pre> 289 * 290 * Notification of displayed: 291 * <pre> 292 * <message 293 * from='romeo@montague.net/orchard' 294 * to='juliet@capulet.com/balcony'> 295 * <x xmlns='jabber:x:event'> 296 * <displayed/> 297 * <id>message22</id> 298 * </x> 299 * </message> 300 * </pre> 301 * 302 */ 303 public String toXML() { 304 StringBuilder buf = new StringBuilder(); 305 buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append( 306 "\">"); 307 // Note: Cancellation events don't specify any tag. They just send the packetID 308 309 // Add the offline tag if the sender requests to be notified of offline events or if 310 // the target is offline 311 if (isOffline()) 312 buf.append("<").append(MessageEvent.OFFLINE).append("/>"); 313 // Add the delivered tag if the sender requests to be notified when the message is 314 // delivered or if the target notifies that the message has been delivered 315 if (isDelivered()) 316 buf.append("<").append(MessageEvent.DELIVERED).append("/>"); 317 // Add the displayed tag if the sender requests to be notified when the message is 318 // displayed or if the target notifies that the message has been displayed 319 if (isDisplayed()) 320 buf.append("<").append(MessageEvent.DISPLAYED).append("/>"); 321 // Add the composing tag if the sender requests to be notified when the target is 322 // composing a reply or if the target notifies that he/she is composing a reply 323 if (isComposing()) 324 buf.append("<").append(MessageEvent.COMPOSING).append("/>"); 325 // Add the id tag only if the MessageEvent is a notification message (not a request) 326 if (getPacketID() != null) 327 buf.append("<id>").append(getPacketID()).append("</id>"); 328 buf.append("</").append(getElementName()).append(">"); 329 return buf.toString(); 330 } 331 332}