MessageEvent.java

  1. /**
  2.  *
  3.  * Copyright 2003-2007 Jive Software.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.jivesoftware.smackx.xevent.packet;

  18. import org.jivesoftware.smack.packet.ExtensionElement;

  19. import java.util.ArrayList;
  20. import java.util.List;

  21. /**
  22.  * Represents message events relating to the delivery, display, composition and cancellation of
  23.  * messages.<p>
  24.  *
  25.  * There are four message events currently defined in this namespace:
  26.  * <ol>
  27.  * <li>Offline<br>
  28.  * Indicates that the message has been stored offline by the intended recipient's server. This
  29.  * event is triggered only if the intended recipient's server supports offline storage, has that
  30.  * support enabled, and the recipient is offline when the server receives the message for delivery.</li>
  31.  *
  32.  * <li>Delivered<br>
  33.  * Indicates that the message has been delivered to the recipient. This signifies that the message
  34.  * has reached the recipient's XMPP client, but does not necessarily mean that the message has
  35.  * been displayed. This event is to be raised by the XMPP client.</li>
  36.  *
  37.  * <li>Displayed<br>
  38.  * Once the message has been received by the recipient's XMPP client, it may be displayed to the
  39.  * user. This event indicates that the message has been displayed, and is to be raised by the
  40.  * XMPP client. Even if a message is displayed multiple times, this event should be raised only
  41.  * once.</li>
  42.  *
  43.  * <li>Composing<br>
  44.  * In threaded chat conversations, this indicates that the recipient is composing a reply to a
  45.  * message. The event is to be raised by the recipient's XMPP client. A XMPP client is allowed
  46.  * to raise this event multiple times in response to the same request, providing the original
  47.  * event is cancelled first.</li>
  48.  * </ol>
  49.  *
  50.  * @author Gaston Dombiak
  51.  */
  52. public class MessageEvent implements ExtensionElement {

  53.     public static final String NAMESPACE = "jabber:x:event";
  54.     public static final String ELEMENT = "x";

  55.     public static final String OFFLINE = "offline";
  56.     public static final String COMPOSING = "composing";
  57.     public static final String DISPLAYED = "displayed";
  58.     public static final String DELIVERED = "delivered";
  59.     public static final String CANCELLED = "cancelled";

  60.     private boolean offline = false;
  61.     private boolean delivered = false;
  62.     private boolean displayed = false;
  63.     private boolean composing = false;
  64.     private boolean cancelled = true;

  65.     private String packetID = null;

  66.     /**
  67.     * Returns the XML element name of the extension sub-packet root element.
  68.     * Always returns "x"
  69.     *
  70.     * @return the XML element name of the packet extension.
  71.     */
  72.     public String getElementName() {
  73.         return ELEMENT;
  74.     }

  75.     /**
  76.      * Returns the XML namespace of the extension sub-packet root element.
  77.      * According the specification the namespace is always "jabber:x:event"
  78.      *
  79.      * @return the XML namespace of the packet extension.
  80.      */
  81.     public String getNamespace() {
  82.         return NAMESPACE;
  83.     }

  84.     /**
  85.      * When the message is a request returns if the sender of the message requests to be notified
  86.      * when the receiver is composing a reply.
  87.      * When the message is a notification returns if the receiver of the message is composing a
  88.      * reply.
  89.      *
  90.      * @return true if the sender is requesting to be notified when composing or when notifying
  91.      * that the receiver of the message is composing a reply
  92.      */
  93.     public boolean isComposing() {
  94.         return composing;
  95.     }

  96.     /**
  97.      * When the message is a request returns if the sender of the message requests to be notified
  98.      * when the message is delivered.
  99.      * When the message is a notification returns if the message was delivered or not.
  100.      *
  101.      * @return true if the sender is requesting to be notified when delivered or when notifying
  102.      * that the message was delivered
  103.      */
  104.     public boolean isDelivered() {
  105.         return delivered;
  106.     }

  107.     /**
  108.      * When the message is a request returns if the sender of the message requests to be notified
  109.      * when the message is displayed.
  110.      * When the message is a notification returns if the message was displayed or not.
  111.      *
  112.      * @return true if the sender is requesting to be notified when displayed or when notifying
  113.      * that the message was displayed
  114.      */
  115.     public boolean isDisplayed() {
  116.         return displayed;
  117.     }

  118.     /**
  119.      * When the message is a request returns if the sender of the message requests to be notified
  120.      * when the receiver of the message is offline.
  121.      * When the message is a notification returns if the receiver of the message was offline.
  122.      *
  123.      * @return true if the sender is requesting to be notified when offline or when notifying
  124.      * that the receiver of the message is offline
  125.      */
  126.     public boolean isOffline() {
  127.         return offline;
  128.     }

  129.     /**
  130.      * When the message is a notification returns if the receiver of the message cancelled
  131.      * composing a reply.
  132.      *
  133.      * @return true if the receiver of the message cancelled composing a reply
  134.      */
  135.     public boolean isCancelled() {
  136.         return cancelled;
  137.     }

  138.     /**
  139.      * Returns the unique ID of the message that requested to be notified of the event.
  140.      * The packet id is not used when the message is a request for notifications
  141.      *
  142.      * @return the message id that requested to be notified of the event.
  143.      */
  144.     public String getStanzaId() {
  145.         return packetID;
  146.     }

  147.     /**
  148.      * Returns the types of events. The type of event could be:
  149.      * "offline", "composing","delivered","displayed", "offline"
  150.      *
  151.      * @return a List of all the types of events of the MessageEvent.
  152.      */
  153.     public List<String> getEventTypes() {
  154.         ArrayList<String> allEvents = new ArrayList<String>();
  155.         if (isDelivered()) {
  156.             allEvents.add(MessageEvent.DELIVERED);
  157.         }
  158.         if (!isMessageEventRequest() && isCancelled()) {
  159.             allEvents.add(MessageEvent.CANCELLED);
  160.         }
  161.         if (isComposing()) {
  162.             allEvents.add(MessageEvent.COMPOSING);
  163.         }
  164.         if (isDisplayed()) {
  165.             allEvents.add(MessageEvent.DISPLAYED);
  166.         }
  167.         if (isOffline()) {
  168.             allEvents.add(MessageEvent.OFFLINE);
  169.         }
  170.         return allEvents;
  171.     }

  172.     /**
  173.      * When the message is a request sets if the sender of the message requests to be notified
  174.      * when the receiver is composing a reply.
  175.      * When the message is a notification sets if the receiver of the message is composing a
  176.      * reply.
  177.      *
  178.      * @param composing sets if the sender is requesting to be notified when composing or when
  179.      * notifying that the receiver of the message is composing a reply
  180.      */
  181.     public void setComposing(boolean composing) {
  182.         this.composing = composing;
  183.         setCancelled(false);
  184.     }

  185.     /**
  186.      * When the message is a request sets if the sender of the message requests to be notified
  187.      * when the message is delivered.
  188.      * When the message is a notification sets if the message was delivered or not.
  189.      *
  190.      * @param delivered sets if the sender is requesting to be notified when delivered or when
  191.      * notifying that the message was delivered
  192.      */
  193.     public void setDelivered(boolean delivered) {
  194.         this.delivered = delivered;
  195.         setCancelled(false);
  196.     }

  197.     /**
  198.      * When the message is a request sets if the sender of the message requests to be notified
  199.      * when the message is displayed.
  200.      * When the message is a notification sets if the message was displayed or not.
  201.      *
  202.      * @param displayed sets if the sender is requesting to be notified when displayed or when
  203.      * notifying that the message was displayed
  204.      */
  205.     public void setDisplayed(boolean displayed) {
  206.         this.displayed = displayed;
  207.         setCancelled(false);
  208.     }

  209.     /**
  210.      * When the message is a request sets if the sender of the message requests to be notified
  211.      * when the receiver of the message is offline.
  212.      * When the message is a notification sets if the receiver of the message was offline.
  213.      *
  214.      * @param offline sets if the sender is requesting to be notified when offline or when
  215.      * notifying that the receiver of the message is offline
  216.      */
  217.     public void setOffline(boolean offline) {
  218.         this.offline = offline;
  219.         setCancelled(false);
  220.     }

  221.     /**
  222.      * When the message is a notification sets if the receiver of the message cancelled
  223.      * composing a reply.
  224.      * The Cancelled event is never requested explicitly. It is requested implicitly when
  225.      * requesting to be notified of the Composing event.
  226.      *
  227.      * @param cancelled sets if the receiver of the message cancelled composing a reply
  228.      */
  229.     public void setCancelled(boolean cancelled) {
  230.         this.cancelled = cancelled;
  231.     }

  232.     /**
  233.      * Sets the unique ID of the message that requested to be notified of the event.
  234.      * The packet id is not used when the message is a request for notifications
  235.      *
  236.      * @param packetID the message id that requested to be notified of the event.
  237.      */
  238.     public void setStanzaId(String packetID) {
  239.         this.packetID = packetID;
  240.     }

  241.     /**
  242.      * Returns true if this MessageEvent is a request for notifications.
  243.      * Returns false if this MessageEvent is a notification of an event.
  244.      *
  245.     * @return true if this message is a request for notifications.
  246.      */
  247.     public boolean isMessageEventRequest() {
  248.         return this.packetID == null;
  249.     }

  250.     /**
  251.      * Returns the XML representation of a Message Event according the specification.
  252.      *
  253.      * Usually the XML representation will be inside of a Message XML representation like
  254.      * in the following examples:<p>
  255.      *
  256.      * Request to be notified when displayed:
  257.      * <pre>
  258.      * &lt;message
  259.      *    to='romeo@montague.net/orchard'
  260.      *    from='juliet@capulet.com/balcony'
  261.      *    id='message22'&gt;
  262.      * &lt;x xmlns='jabber:x:event'&gt;
  263.      *   &lt;displayed/&gt;
  264.      * &lt;/x&gt;
  265.      * &lt;/message&gt;
  266.      * </pre>
  267.      *
  268.      * Notification of displayed:
  269.      * <pre>
  270.      * &lt;message
  271.      *    from='romeo@montague.net/orchard'
  272.      *    to='juliet@capulet.com/balcony'&gt;
  273.      * &lt;x xmlns='jabber:x:event'&gt;
  274.      *   &lt;displayed/&gt;
  275.      *   &lt;id&gt;message22&lt;/id&gt;
  276.      * &lt;/x&gt;
  277.      * &lt;/message&gt;
  278.      * </pre>
  279.      *
  280.      */
  281.     public String toXML() {
  282.         StringBuilder buf = new StringBuilder();
  283.         buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
  284.             "\">");
  285.         // Note: Cancellation events don't specify any tag. They just send the packetID

  286.         // Add the offline tag if the sender requests to be notified of offline events or if
  287.         // the target is offline
  288.         if (isOffline())
  289.             buf.append("<").append(MessageEvent.OFFLINE).append("/>");
  290.         // Add the delivered tag if the sender requests to be notified when the message is
  291.         // delivered or if the target notifies that the message has been delivered
  292.         if (isDelivered())
  293.             buf.append("<").append(MessageEvent.DELIVERED).append("/>");
  294.         // Add the displayed tag if the sender requests to be notified when the message is
  295.         // displayed or if the target notifies that the message has been displayed
  296.         if (isDisplayed())
  297.             buf.append("<").append(MessageEvent.DISPLAYED).append("/>");
  298.         // Add the composing tag if the sender requests to be notified when the target is
  299.         // composing a reply or if the target notifies that he/she is composing a reply
  300.         if (isComposing())
  301.             buf.append("<").append(MessageEvent.COMPOSING).append("/>");
  302.         // Add the id tag only if the MessageEvent is a notification message (not a request)
  303.         if (getStanzaId() != null)
  304.             buf.append("<id>").append(getStanzaId()).append("</id>");
  305.         buf.append("</").append(getElementName()).append(">");
  306.         return buf.toString();
  307.     }

  308. }