/**
* $RCSfile$
* $Revision: 7071 $
* $Date: 2007-02-11 18:59:05 -0600 (Sun, 11 Feb 2007) $
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.ArrayList;
import java.util.Iterator;
import org.jivesoftware.smack.packet.PacketExtension;
/**
* Represents message events relating to the delivery, display, composition and
* cancellation of messages.
* <p>
*
* There are four message events currently defined in this namespace:
* <ol>
* <li>Offline<br>
* Indicates that the message has been stored offline by the intended
* recipient's server. This event is triggered only if the intended recipient's
* server supports offline storage, has that support enabled, and the recipient
* is offline when the server receives the message for delivery.</li>
*
* <li>Delivered<br>
* Indicates that the message has been delivered to the recipient. This
* signifies that the message has reached the recipient's XMPP client, but does
* not necessarily mean that the message has been displayed. This event is to be
* raised by the XMPP client.</li>
*
* <li>Displayed<br>
* Once the message has been received by the recipient's XMPP client, it may be
* displayed to the user. This event indicates that the message has been
* displayed, and is to be raised by the XMPP client. Even if a message is
* displayed multiple times, this event should be raised only once.</li>
*
* <li>Composing<br>
* In threaded chat conversations, this indicates that the recipient is
* composing a reply to a message. The event is to be raised by the recipient's
* XMPP client. A XMPP client is allowed to raise this event multiple times in
* response to the same request, providing the original event is cancelled
* first.</li>
* </ol>
*
* @author Gaston Dombiak
*/
public class MessageEvent implements PacketExtension {
public static final String OFFLINE = "offline";
public static final String COMPOSING = "composing";
public static final String DISPLAYED = "displayed";
public static final String DELIVERED = "delivered";
public static final String CANCELLED = "cancelled";
private boolean offline = false;
private boolean delivered = false;
private boolean displayed = false;
private boolean composing = false;
private boolean cancelled = true;
private String packetID = null;
/**
* Returns the XML element name of the extension sub-packet root element.
* Always returns "x"
*
* @return the XML element name of the packet extension.
*/
@Override
public String getElementName() {
return "x";
}
/**
* Returns the types of events. The type of event could be: "offline",
* "composing","delivered","displayed", "offline"
*
* @return an iterator over all the types of events of the MessageEvent.
*/
public Iterator<String> getEventTypes() {
final ArrayList<String> allEvents = new ArrayList<String>();
if (isDelivered()) {
allEvents.add(MessageEvent.DELIVERED);
}
if (!isMessageEventRequest() && isCancelled()) {
allEvents.add(MessageEvent.CANCELLED);
}
if (isComposing()) {
allEvents.add(MessageEvent.COMPOSING);
}
if (isDisplayed()) {
allEvents.add(MessageEvent.DISPLAYED);
}
if (isOffline()) {
allEvents.add(MessageEvent.OFFLINE);
}
return allEvents.iterator();
}
/**
* Returns the XML namespace of the extension sub-packet root element.
* According the specification the namespace is always "jabber:x:event"
*
* @return the XML namespace of the packet extension.
*/
@Override
public String getNamespace() {
return "jabber:x:event";
}
/**
* Returns the unique ID of the message that requested to be notified of the
* event. The packet id is not used when the message is a request for
* notifications
*
* @return the message id that requested to be notified of the event.
*/
public String getPacketID() {
return packetID;
}
/**
* When the message is a notification returns if the receiver of the message
* cancelled composing a reply.
*
* @return true if the receiver of the message cancelled composing a reply
*/
public boolean isCancelled() {
return cancelled;
}
/**
* When the message is a request returns if the sender of the message
* requests to be notified when the receiver is composing a reply. When the
* message is a notification returns if the receiver of the message is
* composing a reply.
*
* @return true if the sender is requesting to be notified when composing or
* when notifying that the receiver of the message is composing a
* reply
*/
public boolean isComposing() {
return composing;
}
/**
* When the message is a request returns if the sender of the message
* requests to be notified when the message is delivered. When the message
* is a notification returns if the message was delivered or not.
*
* @return true if the sender is requesting to be notified when delivered or
* when notifying that the message was delivered
*/
public boolean isDelivered() {
return delivered;
}
/**
* When the message is a request returns if the sender of the message
* requests to be notified when the message is displayed. When the message
* is a notification returns if the message was displayed or not.
*
* @return true if the sender is requesting to be notified when displayed or
* when notifying that the message was displayed
*/
public boolean isDisplayed() {
return displayed;
}
/**
* Returns true if this MessageEvent is a request for notifications. Returns
* false if this MessageEvent is a notification of an event.
*
* @return true if this message is a request for notifications.
*/
public boolean isMessageEventRequest() {
return packetID == null;
}
/**
* When the message is a request returns if the sender of the message
* requests to be notified when the receiver of the message is offline. When
* the message is a notification returns if the receiver of the message was
* offline.
*
* @return true if the sender is requesting to be notified when offline or
* when notifying that the receiver of the message is offline
*/
public boolean isOffline() {
return offline;
}
/**
* When the message is a notification sets if the receiver of the message
* cancelled composing a reply. The Cancelled event is never requested
* explicitly. It is requested implicitly when requesting to be notified of
* the Composing event.
*
* @param cancelled
* sets if the receiver of the message cancelled composing a
* reply
*/
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
/**
* When the message is a request sets if the sender of the message requests
* to be notified when the receiver is composing a reply. When the message
* is a notification sets if the receiver of the message is composing a
* reply.
*
* @param composing
* sets if the sender is requesting to be notified when composing
* or when notifying that the receiver of the message is
* composing a reply
*/
public void setComposing(boolean composing) {
this.composing = composing;
setCancelled(false);
}
/**
* When the message is a request sets if the sender of the message requests
* to be notified when the message is delivered. When the message is a
* notification sets if the message was delivered or not.
*
* @param delivered
* sets if the sender is requesting to be notified when delivered
* or when notifying that the message was delivered
*/
public void setDelivered(boolean delivered) {
this.delivered = delivered;
setCancelled(false);
}
/**
* When the message is a request sets if the sender of the message requests
* to be notified when the message is displayed. When the message is a
* notification sets if the message was displayed or not.
*
* @param displayed
* sets if the sender is requesting to be notified when displayed
* or when notifying that the message was displayed
*/
public void setDisplayed(boolean displayed) {
this.displayed = displayed;
setCancelled(false);
}
/**
* When the message is a request sets if the sender of the message requests
* to be notified when the receiver of the message is offline. When the
* message is a notification sets if the receiver of the message was
* offline.
*
* @param offline
* sets if the sender is requesting to be notified when offline
* or when notifying that the receiver of the message is offline
*/
public void setOffline(boolean offline) {
this.offline = offline;
setCancelled(false);
}
/**
* Sets the unique ID of the message that requested to be notified of the
* event. The packet id is not used when the message is a request for
* notifications
*
* @param packetID
* the message id that requested to be notified of the event.
*/
public void setPacketID(String packetID) {
this.packetID = packetID;
}
/**
* Returns the XML representation of a Message Event according the
* specification.
*
* Usually the XML representation will be inside of a Message XML
* representation like in the following examples:
* <p>
*
* Request to be notified when displayed:
*
* <pre>
* <message
* to='romeo@montague.net/orchard'
* from='juliet@capulet.com/balcony'
* id='message22'>
* <x xmlns='jabber:x:event'>
* <displayed/>
* </x>
* </message>
* </pre>
*
* Notification of displayed:
*
* <pre>
* <message
* from='romeo@montague.net/orchard'
* to='juliet@capulet.com/balcony'>
* <x xmlns='jabber:x:event'>
* <displayed/>
* <id>message22</id>
* </x>
* </message>
* </pre>
*
*/
@Override
public String toXML() {
final StringBuilder buf = new StringBuilder();
buf.append("<").append(getElementName()).append(" xmlns=\"")
.append(getNamespace()).append("\">");
// Note: Cancellation events don't specify any tag. They just send the
// packetID
// Add the offline tag if the sender requests to be notified of offline
// events or if
// the target is offline
if (isOffline()) {
buf.append("<").append(MessageEvent.OFFLINE).append("/>");
}
// Add the delivered tag if the sender requests to be notified when the
// message is
// delivered or if the target notifies that the message has been
// delivered
if (isDelivered()) {
buf.append("<").append(MessageEvent.DELIVERED).append("/>");
}
// Add the displayed tag if the sender requests to be notified when the
// message is
// displayed or if the target notifies that the message has been
// displayed
if (isDisplayed()) {
buf.append("<").append(MessageEvent.DISPLAYED).append("/>");
}
// Add the composing tag if the sender requests to be notified when the
// target is
// composing a reply or if the target notifies that he/she is composing
// a reply
if (isComposing()) {
buf.append("<").append(MessageEvent.COMPOSING).append("/>");
}
// Add the id tag only if the MessageEvent is a notification message
// (not a request)
if (getPacketID() != null) {
buf.append("<id>").append(getPacketID()).append("</id>");
}
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
}