001/** 002 * 003 * Copyright the original author or authors 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 */ 017package org.jivesoftware.smackx.pubsub; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.List; 022 023import org.jivesoftware.smack.SmackException.NoResponseException; 024import org.jivesoftware.smack.SmackException.NotConnectedException; 025import org.jivesoftware.smack.XMPPConnection; 026import org.jivesoftware.smack.XMPPException.XMPPErrorException; 027import org.jivesoftware.smack.packet.IQ.Type; 028import org.jivesoftware.smackx.disco.packet.DiscoverItems; 029import org.jivesoftware.smackx.pubsub.packet.PubSub; 030 031/** 032 * The main class for the majority of pubsub functionality. In general 033 * almost all pubsub capabilities are related to the concept of a node. 034 * All items are published to a node, and typically subscribed to by other 035 * users. These users then retrieve events based on this subscription. 036 * 037 * @author Robin Collier 038 */ 039public class LeafNode extends Node 040{ 041 LeafNode(XMPPConnection connection, String nodeName) 042 { 043 super(connection, nodeName); 044 } 045 046 /** 047 * Get information on the items in the node in standard 048 * {@link DiscoverItems} format. 049 * 050 * @return The item details in {@link DiscoverItems} format 051 * @throws XMPPErrorException 052 * @throws NoResponseException if there was no response from the server. 053 * @throws NotConnectedException 054 */ 055 public DiscoverItems discoverItems() throws NoResponseException, XMPPErrorException, NotConnectedException 056 { 057 DiscoverItems items = new DiscoverItems(); 058 items.setTo(to); 059 items.setNode(getId()); 060 return (DiscoverItems) con.createPacketCollectorAndSend(items).nextResultOrThrow(); 061 } 062 063 /** 064 * Get the current items stored in the node. 065 * 066 * @return List of {@link Item} in the node 067 * @throws XMPPErrorException 068 * @throws NoResponseException if there was no response from the server. 069 * @throws NotConnectedException 070 */ 071 @SuppressWarnings("unchecked") 072 public <T extends Item> List<T> getItems() throws NoResponseException, XMPPErrorException, NotConnectedException 073 { 074 PubSub request = createPubsubPacket(Type.GET, new GetItemsRequest(getId())); 075 076 PubSub result = (PubSub) con.createPacketCollectorAndSend(request).nextResultOrThrow(); 077 ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); 078 return (List<T>)itemsElem.getItems(); 079 } 080 081 /** 082 * Get the current items stored in the node based 083 * on the subscription associated with the provided 084 * subscription id. 085 * 086 * @param subscriptionId - The subscription id for the 087 * associated subscription. 088 * @return List of {@link Item} in the node 089 * @throws XMPPErrorException 090 * @throws NoResponseException if there was no response from the server. 091 * @throws NotConnectedException 092 */ 093 @SuppressWarnings("unchecked") 094 public <T extends Item> List<T> getItems(String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException 095 { 096 PubSub request = createPubsubPacket(Type.GET, new GetItemsRequest(getId(), subscriptionId)); 097 098 PubSub result = (PubSub) con.createPacketCollectorAndSend(request).nextResultOrThrow(); 099 ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); 100 return (List<T>)itemsElem.getItems(); 101 } 102 103 /** 104 * Get the items specified from the node. This would typically be 105 * used when the server does not return the payload due to size 106 * constraints. The user would be required to retrieve the payload 107 * after the items have been retrieved via {@link #getItems()} or an 108 * event, that did not include the payload. 109 * 110 * @param ids Item ids of the items to retrieve 111 * 112 * @return The list of {@link Item} with payload 113 * @throws XMPPErrorException 114 * @throws NoResponseException if there was no response from the server. 115 * @throws NotConnectedException 116 */ 117 @SuppressWarnings("unchecked") 118 public <T extends Item> List<T> getItems(Collection<String> ids) throws NoResponseException, XMPPErrorException, NotConnectedException 119 { 120 List<Item> itemList = new ArrayList<Item>(ids.size()); 121 122 for (String id : ids) 123 { 124 itemList.add(new Item(id)); 125 } 126 PubSub request = createPubsubPacket(Type.GET, new ItemsExtension(ItemsExtension.ItemsElementType.items, getId(), itemList)); 127 128 PubSub result = (PubSub) con.createPacketCollectorAndSend(request).nextResultOrThrow(); 129 ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); 130 return (List<T>)itemsElem.getItems(); 131 } 132 133 /** 134 * Get items persisted on the node, limited to the specified number. 135 * 136 * @param maxItems Maximum number of items to return 137 * 138 * @return List of {@link Item} 139 * @throws XMPPErrorException 140 * @throws NoResponseException if there was no response from the server. 141 * @throws NotConnectedException 142 */ 143 @SuppressWarnings("unchecked") 144 public <T extends Item> List<T> getItems(int maxItems) throws NoResponseException, XMPPErrorException, NotConnectedException 145 { 146 PubSub request = createPubsubPacket(Type.GET, new GetItemsRequest(getId(), maxItems)); 147 148 PubSub result = (PubSub) con.createPacketCollectorAndSend(request).nextResultOrThrow(); 149 ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); 150 return (List<T>)itemsElem.getItems(); 151 } 152 153 /** 154 * Get items persisted on the node, limited to the specified number 155 * based on the subscription associated with the provided subscriptionId. 156 * 157 * @param maxItems Maximum number of items to return 158 * @param subscriptionId The subscription which the retrieval is based 159 * on. 160 * 161 * @return List of {@link Item} 162 * @throws XMPPErrorException 163 * @throws NoResponseException if there was no response from the server. 164 * @throws NotConnectedException 165 */ 166 @SuppressWarnings("unchecked") 167 public <T extends Item> List<T> getItems(int maxItems, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException 168 { 169 PubSub request = createPubsubPacket(Type.GET, new GetItemsRequest(getId(), subscriptionId, maxItems)); 170 171 PubSub result = (PubSub) con.createPacketCollectorAndSend(request).nextResultOrThrow(); 172 ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); 173 return (List<T>)itemsElem.getItems(); 174 } 175 176 /** 177 * Publishes an event to the node. This is an empty event 178 * with no item. 179 * 180 * This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false 181 * and {@link ConfigureForm#isDeliverPayloads()}=false. 182 * 183 * This is an asynchronous call which returns as soon as the 184 * packet has been sent. 185 * 186 * For synchronous calls use {@link #send() send()}. 187 * @throws NotConnectedException 188 */ 189 public void publish() throws NotConnectedException 190 { 191 PubSub packet = createPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.PUBLISH, getId())); 192 193 con.sendPacket(packet); 194 } 195 196 /** 197 * Publishes an event to the node. This is a simple item 198 * with no payload. 199 * 200 * If the id is null, an empty item (one without an id) will be sent. 201 * Please note that this is not the same as {@link #send()}, which 202 * publishes an event with NO item. 203 * 204 * This is an asynchronous call which returns as soon as the 205 * packet has been sent. 206 * 207 * For synchronous calls use {@link #send(Item) send(Item))}. 208 * 209 * @param item - The item being sent 210 * @throws NotConnectedException 211 */ 212 @SuppressWarnings("unchecked") 213 public <T extends Item> void publish(T item) throws NotConnectedException 214 { 215 Collection<T> items = new ArrayList<T>(1); 216 items.add((T)(item == null ? new Item() : item)); 217 publish(items); 218 } 219 220 /** 221 * Publishes multiple events to the node. Same rules apply as in {@link #publish(Item)}. 222 * 223 * In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input 224 * list will get stored on the node, assuming it stores the last sent item. 225 * 226 * This is an asynchronous call which returns as soon as the 227 * packet has been sent. 228 * 229 * For synchronous calls use {@link #send(Collection) send(Collection))}. 230 * 231 * @param items - The collection of items being sent 232 * @throws NotConnectedException 233 */ 234 public <T extends Item> void publish(Collection<T> items) throws NotConnectedException 235 { 236 PubSub packet = createPubsubPacket(Type.SET, new PublishItem<T>(getId(), items)); 237 238 con.sendPacket(packet); 239 } 240 241 /** 242 * Publishes an event to the node. This is an empty event 243 * with no item. 244 * 245 * This is only acceptable for nodes with {@link ConfigureForm#isPersistItems()}=false 246 * and {@link ConfigureForm#isDeliverPayloads()}=false. 247 * 248 * This is a synchronous call which will throw an exception 249 * on failure. 250 * 251 * For asynchronous calls, use {@link #publish() publish()}. 252 * @throws XMPPErrorException 253 * @throws NoResponseException 254 * @throws NotConnectedException 255 * 256 */ 257 public void send() throws NoResponseException, XMPPErrorException, NotConnectedException 258 { 259 PubSub packet = createPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.PUBLISH, getId())); 260 261 con.createPacketCollectorAndSend(packet).nextResultOrThrow(); 262 } 263 264 /** 265 * Publishes an event to the node. This can be either a simple item 266 * with no payload, or one with it. This is determined by the Node 267 * configuration. 268 * 269 * If the node has <b>deliver_payload=false</b>, the Item must not 270 * have a payload. 271 * 272 * If the id is null, an empty item (one without an id) will be sent. 273 * Please note that this is not the same as {@link #send()}, which 274 * publishes an event with NO item. 275 * 276 * This is a synchronous call which will throw an exception 277 * on failure. 278 * 279 * For asynchronous calls, use {@link #publish(Item) publish(Item)}. 280 * 281 * @param item - The item being sent 282 * @throws XMPPErrorException 283 * @throws NoResponseException 284 * @throws NotConnectedException 285 * 286 */ 287 @SuppressWarnings("unchecked") 288 public <T extends Item> void send(T item) throws NoResponseException, XMPPErrorException, NotConnectedException 289 { 290 Collection<T> items = new ArrayList<T>(1); 291 items.add((item == null ? (T)new Item() : item)); 292 send(items); 293 } 294 295 /** 296 * Publishes multiple events to the node. Same rules apply as in {@link #send(Item)}. 297 * 298 * In addition, if {@link ConfigureForm#isPersistItems()}=false, only the last item in the input 299 * list will get stored on the node, assuming it stores the last sent item. 300 * 301 * This is a synchronous call which will throw an exception 302 * on failure. 303 * 304 * For asynchronous calls, use {@link #publish(Collection) publish(Collection))}. 305 * 306 * @param items - The collection of {@link Item} objects being sent 307 * @throws XMPPErrorException 308 * @throws NoResponseException 309 * @throws NotConnectedException 310 * 311 */ 312 public <T extends Item> void send(Collection<T> items) throws NoResponseException, XMPPErrorException, NotConnectedException 313 { 314 PubSub packet = createPubsubPacket(Type.SET, new PublishItem<T>(getId(), items)); 315 316 con.createPacketCollectorAndSend(packet).nextResultOrThrow(); 317 } 318 319 /** 320 * Purges the node of all items. 321 * 322 * <p>Note: Some implementations may keep the last item 323 * sent. 324 * @throws XMPPErrorException 325 * @throws NoResponseException if there was no response from the server. 326 * @throws NotConnectedException 327 */ 328 public void deleteAllItems() throws NoResponseException, XMPPErrorException, NotConnectedException 329 { 330 PubSub request = createPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.PURGE_OWNER, getId()), PubSubElementType.PURGE_OWNER.getNamespace()); 331 332 con.createPacketCollectorAndSend(request).nextResultOrThrow(); 333 } 334 335 /** 336 * Delete the item with the specified id from the node. 337 * 338 * @param itemId The id of the item 339 * @throws XMPPErrorException 340 * @throws NoResponseException 341 * @throws NotConnectedException 342 */ 343 public void deleteItem(String itemId) throws NoResponseException, XMPPErrorException, NotConnectedException 344 { 345 Collection<String> items = new ArrayList<String>(1); 346 items.add(itemId); 347 deleteItem(items); 348 } 349 350 /** 351 * Delete the items with the specified id's from the node. 352 * 353 * @param itemIds The list of id's of items to delete 354 * @throws XMPPErrorException 355 * @throws NoResponseException if there was no response from the server. 356 * @throws NotConnectedException 357 */ 358 public void deleteItem(Collection<String> itemIds) throws NoResponseException, XMPPErrorException, NotConnectedException 359 { 360 List<Item> items = new ArrayList<Item>(itemIds.size()); 361 362 for (String id : itemIds) 363 { 364 items.add(new Item(id)); 365 } 366 PubSub request = createPubsubPacket(Type.SET, new ItemsExtension(ItemsExtension.ItemsElementType.retract, getId(), items)); 367 con.createPacketCollectorAndSend(request).nextResultOrThrow(); 368 } 369}