LeafNode.java

  1. /**
  2.  *
  3.  * Copyright the original author or authors
  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.pubsub;

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

  21. import org.jivesoftware.smack.SmackException.NoResponseException;
  22. import org.jivesoftware.smack.SmackException.NotConnectedException;
  23. import org.jivesoftware.smack.XMPPConnection;
  24. import org.jivesoftware.smack.XMPPException.XMPPErrorException;
  25. import org.jivesoftware.smack.packet.IQ.Type;
  26. import org.jivesoftware.smack.packet.ExtensionElement;
  27. import org.jivesoftware.smackx.disco.packet.DiscoverItems;
  28. import org.jivesoftware.smackx.pubsub.packet.PubSub;

  29. /**
  30.  * The main class for the majority of pubsub functionality.  In general
  31.  * almost all pubsub capabilities are related to the concept of a node.
  32.  * All items are published to a node, and typically subscribed to by other
  33.  * users.  These users then retrieve events based on this subscription.
  34.  *
  35.  * @author Robin Collier
  36.  */
  37. public class LeafNode extends Node
  38. {
  39.     LeafNode(XMPPConnection connection, String nodeName)
  40.     {
  41.         super(connection, nodeName);
  42.     }
  43.    
  44.     /**
  45.      * Get information on the items in the node in standard
  46.      * {@link DiscoverItems} format.
  47.      *
  48.      * @return The item details in {@link DiscoverItems} format
  49.      * @throws XMPPErrorException
  50.      * @throws NoResponseException if there was no response from the server.
  51.      * @throws NotConnectedException
  52.      * @throws InterruptedException
  53.      */
  54.     public DiscoverItems discoverItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  55.     {
  56.         DiscoverItems items = new DiscoverItems();
  57.         items.setTo(to);
  58.         items.setNode(getId());
  59.         return (DiscoverItems) con.createPacketCollectorAndSend(items).nextResultOrThrow();
  60.     }

  61.     /**
  62.      * Get the current items stored in the node.
  63.      *
  64.      * @return List of {@link Item} in the node
  65.      * @throws XMPPErrorException
  66.      * @throws NoResponseException if there was no response from the server.
  67.      * @throws NotConnectedException
  68.      * @throws InterruptedException
  69.      */
  70.     public <T extends Item> List<T> getItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  71.     {
  72.         return getItems((List<ExtensionElement>) null, (List<ExtensionElement>) null);
  73.     }
  74.    
  75.     /**
  76.      * Get the current items stored in the node based
  77.      * on the subscription associated with the provided
  78.      * subscription id.
  79.      *
  80.      * @param subscriptionId -  The subscription id for the
  81.      * associated subscription.
  82.      * @return List of {@link Item} in the node
  83.      * @throws XMPPErrorException
  84.      * @throws NoResponseException if there was no response from the server.
  85.      * @throws NotConnectedException
  86.      * @throws InterruptedException
  87.      */
  88.     public <T extends Item> List<T> getItems(String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  89.     {
  90.         PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId(), subscriptionId));
  91.         return getItems(request);
  92.     }

  93.     /**
  94.      * Get the items specified from the node.  This would typically be
  95.      * used when the server does not return the payload due to size
  96.      * constraints.  The user would be required to retrieve the payload
  97.      * after the items have been retrieved via {@link #getItems()} or an
  98.      * event, that did not include the payload.
  99.      *
  100.      * @param ids Item ids of the items to retrieve
  101.      *
  102.      * @return The list of {@link Item} with payload
  103.      * @throws XMPPErrorException
  104.      * @throws NoResponseException if there was no response from the server.
  105.      * @throws NotConnectedException
  106.      * @throws InterruptedException
  107.      */
  108.     public <T extends Item> List<T> getItems(Collection<String> ids) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  109.     {
  110.         List<Item> itemList = new ArrayList<Item>(ids.size());
  111.        
  112.         for (String id : ids)
  113.         {
  114.             itemList.add(new Item(id));
  115.         }
  116.         PubSub request = createPubsubPacket(Type.get, new ItemsExtension(ItemsExtension.ItemsElementType.items, getId(), itemList));
  117.         return getItems(request);
  118.     }

  119.     /**
  120.      * Get items persisted on the node, limited to the specified number.
  121.      *
  122.      * @param maxItems Maximum number of items to return
  123.      *
  124.      * @return List of {@link Item}
  125.      * @throws XMPPErrorException
  126.      * @throws NoResponseException if there was no response from the server.
  127.      * @throws NotConnectedException
  128.      * @throws InterruptedException
  129.      */
  130.     public <T extends Item> List<T> getItems(int maxItems) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  131.     {
  132.         PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId(), maxItems));
  133.         return getItems(request);
  134.     }
  135.    
  136.     /**
  137.      * Get items persisted on the node, limited to the specified number
  138.      * based on the subscription associated with the provided subscriptionId.
  139.      *
  140.      * @param maxItems Maximum number of items to return
  141.      * @param subscriptionId The subscription which the retrieval is based
  142.      * on.
  143.      *
  144.      * @return List of {@link Item}
  145.      * @throws XMPPErrorException
  146.      * @throws NoResponseException if there was no response from the server.
  147.      * @throws NotConnectedException
  148.      * @throws InterruptedException
  149.      */
  150.     public <T extends Item> List<T> getItems(int maxItems, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  151.     {
  152.         PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId(), subscriptionId, maxItems));
  153.         return getItems(request);
  154.     }

  155.     /**
  156.      * Get items persisted on the node.
  157.      * <p>
  158.      * {@code additionalExtensions} can be used e.g. to add a "Result Set Management" extension.
  159.      * {@code returnedExtensions} will be filled with the packet extensions found in the answer.
  160.      * </p>
  161.      *
  162.      * @param additionalExtensions additional {@code PacketExtensions} to be added to the request.
  163.      *        This is an optional argument, if provided as null no extensions will be added.
  164.      * @param returnedExtensions a collection that will be filled with the returned packet
  165.      *        extensions. This is an optional argument, if provided as null it won't be populated.
  166.      * @return List of {@link Item}
  167.      * @throws NoResponseException
  168.      * @throws XMPPErrorException
  169.      * @throws NotConnectedException
  170.      * @throws InterruptedException
  171.      */
  172.     public <T extends Item> List<T> getItems(List<ExtensionElement> additionalExtensions,
  173.                     List<ExtensionElement> returnedExtensions) throws NoResponseException,
  174.                     XMPPErrorException, NotConnectedException, InterruptedException {
  175.         PubSub request = createPubsubPacket(Type.get, new GetItemsRequest(getId()));
  176.         request.addExtensions(additionalExtensions);
  177.         return getItems(request, returnedExtensions);
  178.     }

  179.     private <T extends Item> List<T> getItems(PubSub request) throws NoResponseException,
  180.                     XMPPErrorException, NotConnectedException, InterruptedException {
  181.         return getItems(request, null);
  182.     }

  183.     @SuppressWarnings("unchecked")
  184.     private <T extends Item> List<T> getItems(PubSub request,
  185.                     List<ExtensionElement> returnedExtensions) throws NoResponseException,
  186.                     XMPPErrorException, NotConnectedException, InterruptedException {
  187.         PubSub result = con.createPacketCollectorAndSend(request).nextResultOrThrow();
  188.         ItemsExtension itemsElem = result.getExtension(PubSubElementType.ITEMS);
  189.         if (returnedExtensions != null) {
  190.             returnedExtensions.addAll(result.getExtensions());
  191.         }
  192.         return (List<T>) itemsElem.getItems();
  193.     }

  194.     /**
  195.      * Publishes an event to the node.  This is an empty event
  196.      * with no item.
  197.      *
  198.      * This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false
  199.      * and {@link ConfigureForm#isDeliverPayloads()}=false.
  200.      *
  201.      * This is an asynchronous call which returns as soon as the
  202.      * packet has been sent.
  203.      *
  204.      * For synchronous calls use {@link #send() send()}.
  205.      * @throws NotConnectedException
  206.      * @throws InterruptedException
  207.      */
  208.     public void publish() throws NotConnectedException, InterruptedException
  209.     {
  210.         PubSub packet = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PUBLISH, getId()));
  211.        
  212.         con.sendStanza(packet);
  213.     }
  214.    
  215.     /**
  216.      * Publishes an event to the node.  This is a simple item
  217.      * with no payload.
  218.      *
  219.      * If the id is null, an empty item (one without an id) will be sent.
  220.      * Please note that this is not the same as {@link #send()}, which
  221.      * publishes an event with NO item.
  222.      *
  223.      * This is an asynchronous call which returns as soon as the
  224.      * packet has been sent.
  225.      *
  226.      * For synchronous calls use {@link #send(Item) send(Item))}.
  227.      *
  228.      * @param item - The item being sent
  229.      * @throws NotConnectedException
  230.      * @throws InterruptedException
  231.      */
  232.     @SuppressWarnings("unchecked")
  233.     public <T extends Item> void publish(T item) throws NotConnectedException, InterruptedException
  234.     {
  235.         Collection<T> items = new ArrayList<T>(1);
  236.         items.add((T)(item == null ? new Item() : item));
  237.         publish(items);
  238.     }

  239.     /**
  240.      * Publishes multiple events to the node.  Same rules apply as in {@link #publish(Item)}.
  241.      *
  242.      * In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input
  243.      * list will get stored on the node, assuming it stores the last sent item.
  244.      *
  245.      * This is an asynchronous call which returns as soon as the
  246.      * packet has been sent.
  247.      *
  248.      * For synchronous calls use {@link #send(Collection) send(Collection))}.
  249.      *
  250.      * @param items - The collection of items being sent
  251.      * @throws NotConnectedException
  252.      * @throws InterruptedException
  253.      */
  254.     public <T extends Item> void publish(Collection<T> items) throws NotConnectedException, InterruptedException
  255.     {
  256.         PubSub packet = createPubsubPacket(Type.set, new PublishItem<T>(getId(), items));
  257.        
  258.         con.sendStanza(packet);
  259.     }

  260.     /**
  261.      * Publishes an event to the node.  This is an empty event
  262.      * with no item.
  263.      *
  264.      * This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false
  265.      * and {@link ConfigureForm#isDeliverPayloads()}=false.
  266.      *
  267.      * This is a synchronous call which will throw an exception
  268.      * on failure.
  269.      *
  270.      * For asynchronous calls, use {@link #publish() publish()}.
  271.      * @throws XMPPErrorException
  272.      * @throws NoResponseException
  273.      * @throws NotConnectedException
  274.      * @throws InterruptedException
  275.      *
  276.      */
  277.     public void send() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  278.     {
  279.         PubSub packet = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PUBLISH, getId()));
  280.        
  281.         con.createPacketCollectorAndSend(packet).nextResultOrThrow();
  282.     }
  283.    
  284.     /**
  285.      * Publishes an event to the node.  This can be either a simple item
  286.      * with no payload, or one with it.  This is determined by the Node
  287.      * configuration.
  288.      *
  289.      * If the node has <b>deliver_payload=false</b>, the Item must not
  290.      * have a payload.
  291.      *
  292.      * If the id is null, an empty item (one without an id) will be sent.
  293.      * Please note that this is not the same as {@link #send()}, which
  294.      * publishes an event with NO item.
  295.      *
  296.      * This is a synchronous call which will throw an exception
  297.      * on failure.
  298.      *
  299.      * For asynchronous calls, use {@link #publish(Item) publish(Item)}.
  300.      *
  301.      * @param item - The item being sent
  302.      * @throws XMPPErrorException
  303.      * @throws NoResponseException
  304.      * @throws NotConnectedException
  305.      * @throws InterruptedException
  306.      *
  307.      */
  308.     @SuppressWarnings("unchecked")
  309.     public <T extends Item> void send(T item) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  310.     {
  311.         Collection<T> items = new ArrayList<T>(1);
  312.         items.add((item == null ? (T)new Item() : item));
  313.         send(items);
  314.     }
  315.    
  316.     /**
  317.      * Publishes multiple events to the node.  Same rules apply as in {@link #send(Item)}.
  318.      *
  319.      * In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input
  320.      * list will get stored on the node, assuming it stores the last sent item.
  321.      *  
  322.      * This is a synchronous call which will throw an exception
  323.      * on failure.
  324.      *
  325.      * For asynchronous calls, use {@link #publish(Collection) publish(Collection))}.
  326.      *
  327.      * @param items - The collection of {@link Item} objects being sent
  328.      * @throws XMPPErrorException
  329.      * @throws NoResponseException
  330.      * @throws NotConnectedException
  331.      * @throws InterruptedException
  332.      *
  333.      */
  334.     public <T extends Item> void send(Collection<T> items) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  335.     {
  336.         PubSub packet = createPubsubPacket(Type.set, new PublishItem<T>(getId(), items));
  337.        
  338.         con.createPacketCollectorAndSend(packet).nextResultOrThrow();
  339.     }
  340.    
  341.     /**
  342.      * Purges the node of all items.
  343.      *  
  344.      * <p>Note: Some implementations may keep the last item
  345.      * sent.
  346.      * @throws XMPPErrorException
  347.      * @throws NoResponseException if there was no response from the server.
  348.      * @throws NotConnectedException
  349.      * @throws InterruptedException
  350.      */
  351.     public void deleteAllItems() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  352.     {
  353.         PubSub request = createPubsubPacket(Type.set, new NodeExtension(PubSubElementType.PURGE_OWNER, getId()), PubSubElementType.PURGE_OWNER.getNamespace());
  354.        
  355.         con.createPacketCollectorAndSend(request).nextResultOrThrow();
  356.     }
  357.    
  358.     /**
  359.      * Delete the item with the specified id from the node.
  360.      *
  361.      * @param itemId The id of the item
  362.      * @throws XMPPErrorException
  363.      * @throws NoResponseException
  364.      * @throws NotConnectedException
  365.      * @throws InterruptedException
  366.      */
  367.     public void deleteItem(String itemId) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  368.     {
  369.         Collection<String> items = new ArrayList<String>(1);
  370.         items.add(itemId);
  371.         deleteItem(items);
  372.     }
  373.    
  374.     /**
  375.      * Delete the items with the specified id's from the node.
  376.      *
  377.      * @param itemIds The list of id's of items to delete
  378.      * @throws XMPPErrorException
  379.      * @throws NoResponseException if there was no response from the server.
  380.      * @throws NotConnectedException
  381.      * @throws InterruptedException
  382.      */
  383.     public void deleteItem(Collection<String> itemIds) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException
  384.     {
  385.         List<Item> items = new ArrayList<Item>(itemIds.size());
  386.        
  387.         for (String id : itemIds)
  388.         {
  389.             items.add(new Item(id));
  390.         }
  391.         PubSub request = createPubsubPacket(Type.set, new ItemsExtension(ItemsExtension.ItemsElementType.retract, getId(), items));
  392.         con.createPacketCollectorAndSend(request).nextResultOrThrow();
  393.     }
  394. }