From 11a41e79ca28155a2269bf6b5503b46c495bae92 Mon Sep 17 00:00:00 2001 From: rcollier Date: Sat, 30 Jan 2010 00:04:39 +0000 Subject: [PATCH] SMACK-289 Added functionality for retrieving items when the user has multiple subscriptions git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@11579 b35dd754-fafc-0310-a699-88a17e54d16e --- .../smackx/pubsub/GetItemsRequest.java | 85 +++++++++++++++++++ .../smackx/pubsub/ItemsExtension.java | 41 ++++++--- .../jivesoftware/smackx/pubsub/LeafNode.java | 51 ++++++++++- .../smackx/pubsub/provider/ItemsProvider.java | 2 +- .../pubsub/MultiUserSubscriptionUseCases.java | 29 +++++++ .../smackx/pubsub/SubscriberUseCases.java | 7 -- 6 files changed, 189 insertions(+), 26 deletions(-) create mode 100644 source/org/jivesoftware/smackx/pubsub/GetItemsRequest.java diff --git a/source/org/jivesoftware/smackx/pubsub/GetItemsRequest.java b/source/org/jivesoftware/smackx/pubsub/GetItemsRequest.java new file mode 100644 index 000000000..55d3f5861 --- /dev/null +++ b/source/org/jivesoftware/smackx/pubsub/GetItemsRequest.java @@ -0,0 +1,85 @@ +/** + * 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.pubsub; + +/** + * Represents a request to subscribe to a node. + * + * @author Robin Collier + */ +public class GetItemsRequest extends NodeExtension +{ + protected String subId; + protected int maxItems; + + public GetItemsRequest(String nodeId) + { + super(PubSubElementType.ITEMS, nodeId); + } + + public GetItemsRequest(String nodeId, String subscriptionId) + { + super(PubSubElementType.ITEMS, nodeId); + subId = subscriptionId; + } + + public GetItemsRequest(String nodeId, int maxItemsToReturn) + { + super(PubSubElementType.ITEMS, nodeId); + maxItems = maxItemsToReturn; + } + + public GetItemsRequest(String nodeId, String subscriptionId, int maxItems) + { + super(PubSubElementType.ITEMS, nodeId); + subId = subscriptionId; + } + + public String getSubscriptionId() + { + return subId; + } + + public int getMaxItems() + { + return maxItems; + } + + @Override + public String toXML() + { + StringBuilder builder = new StringBuilder("<"); + builder.append(getElementName()); + + builder.append(" node='"); + builder.append(getNode()); + builder.append("'"); + + if (getSubscriptionId() != null) + { + builder.append(" subid='"); + builder.append(getSubscriptionId()); + builder.append("'/>"); + } + + if (getMaxItems() > 0) + { + builder.append(" max_items='"); + builder.append(getMaxItems()); + builder.append("'/>"); + } + builder.append("/>"); + return builder.toString(); + } +} diff --git a/source/org/jivesoftware/smackx/pubsub/ItemsExtension.java b/source/org/jivesoftware/smackx/pubsub/ItemsExtension.java index 320901c0c..c98d93af0 100644 --- a/source/org/jivesoftware/smackx/pubsub/ItemsExtension.java +++ b/source/org/jivesoftware/smackx/pubsub/ItemsExtension.java @@ -32,7 +32,7 @@ import org.jivesoftware.smack.packet.PacketExtension; public class ItemsExtension extends NodeExtension implements EmbeddedPacketExtension { protected ItemsElementType type; - protected String attValue; + protected Boolean notify; protected List items; public enum ItemsElementType @@ -81,24 +81,37 @@ public class ItemsExtension extends NodeExtension implements EmbeddedPacketExten * @param items The list of {@link Item} or {@link RetractItem} * @param attributeValue The value of the max_items */ - public ItemsExtension(ItemsElementType itemsType, String nodeId, List items, String attributeValue) + public ItemsExtension(ItemsElementType itemsType, String nodeId, List items) { super(itemsType.getNodeElement(), nodeId); type = itemsType; this.items = items; - attValue = attributeValue; } /** - * Constructs a request to get items from the node as defined in the first scenario - * in {@link #ItemsExtension(ItemsElementType, String, List, String)} + * Construct an instance with a list representing items that have been published or deleted. * - * @param nodeId The node the items will be requested from - * @param maxItems The limit on the number of items to retrieve (null for all) + *

Valid scenarios are: + *

  • Request items from node - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and an + * optional value for the max_items attribute. + *
  • Request to delete items - itemsType = {@link ItemsElementType#retract}, items = list of {@link Item} containing + * only id's and an optional value for the notify attribute. + *
  • Items published event - itemsType = {@link ItemsElementType#items}, items = list of {@link Item} and + * attributeValue = null + *
  • Items deleted event - itemsType = {@link ItemsElementType#items}, items = list of {@link RetractItem} and + * attributeValue = null + * + * @param itemsType Type of representation + * @param nodeId The node to which the items are being sent or deleted + * @param items The list of {@link Item} or {@link RetractItem} + * @param attributeValue The value of the max_items */ - public ItemsExtension(String nodeId, Integer maxItems) + public ItemsExtension(String nodeId, List items, boolean notify) { - this(ItemsElementType.items, nodeId, null, maxItems == null ? null : maxItems.toString()); + super(ItemsElementType.retract.getNodeElement(), nodeId); + type = ItemsElementType.retract; + this.items = items; + this.notify = notify; } /** @@ -131,15 +144,15 @@ public class ItemsExtension extends NodeExtension implements EmbeddedPacketExten * * @return The attribute value */ - public String getAttributeValue() + public boolean getNotify() { - return attValue; + return notify; } @Override public String toXML() { - if (((items == null) || (items.size() == 0)) && (attValue == null)) + if ((items == null) || (items.size() == 0)) { return super.toXML(); } @@ -150,12 +163,12 @@ public class ItemsExtension extends NodeExtension implements EmbeddedPacketExten builder.append(" node='"); builder.append(getNode()); - if (attValue != null) + if (notify != null) { builder.append("' "); builder.append(type.getElementAttribute()); builder.append("='"); - builder.append(attValue); + builder.append(notify.equals(Boolean.TRUE) ? 1 : 0); builder.append("'>"); } else diff --git a/source/org/jivesoftware/smackx/pubsub/LeafNode.java b/source/org/jivesoftware/smackx/pubsub/LeafNode.java index 413d6c2bb..2bd92dc95 100644 --- a/source/org/jivesoftware/smackx/pubsub/LeafNode.java +++ b/source/org/jivesoftware/smackx/pubsub/LeafNode.java @@ -66,13 +66,34 @@ public class LeafNode extends Node public List getItems() throws XMPPException { - PubSub request = createPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.ITEMS, getId())); + PubSub request = createPubsubPacket(Type.GET, new GetItemsRequest(getId())); PubSub result = (PubSub)SyncPacketSend.getReply(con, request); ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); return (List)itemsElem.getItems(); } + /** + * Get the current items stored in the node based + * on the subscription associated with the provided + * subscription id. + * + * @param subscriptionId - The subscription id for the + * associated subscription. + * @return List of {@link Item} in the node + * + * @throws XMPPException + */ + public List getItems(String subscriptionId) + throws XMPPException + { + PubSub request = createPubsubPacket(Type.GET, new GetItemsRequest(getId(), subscriptionId)); + + PubSub result = (PubSub)SyncPacketSend.getReply(con, request); + ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); + return (List)itemsElem.getItems(); + } + /** * Get the items specified from the node. This would typically be * used when the server does not return the payload due to size @@ -95,7 +116,7 @@ public class LeafNode extends Node { itemList.add(new Item(id)); } - PubSub request = createPubsubPacket(Type.GET, new ItemsExtension(ItemsExtension.ItemsElementType.items, getId(), itemList, null)); + PubSub request = createPubsubPacket(Type.GET, new ItemsExtension(ItemsExtension.ItemsElementType.items, getId(), itemList)); PubSub result = (PubSub)SyncPacketSend.getReply(con, request); ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); @@ -114,7 +135,29 @@ public class LeafNode extends Node public List getItems(int maxItems) throws XMPPException { - PubSub request = createPubsubPacket(Type.GET, new ItemsExtension(getId(), Integer.valueOf(maxItems))); + PubSub request = createPubsubPacket(Type.GET, new GetItemsRequest(getId(), maxItems)); + + PubSub result = (PubSub)SyncPacketSend.getReply(con, request); + ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); + return (List)itemsElem.getItems(); + } + + /** + * Get items persisted on the node, limited to the specified number + * based on the subscription associated with the provided subscriptionId. + * + * @param maxItems Maximum number of items to return + * @param subscriptionId The subscription which the retrieval is based + * on. + * + * @return List of {@link Item} + * + * @throws XMPPException + */ + public List getItems(int maxItems, String subscriptionId) + throws XMPPException + { + PubSub request = createPubsubPacket(Type.GET, new GetItemsRequest(getId(), subscriptionId, maxItems)); PubSub result = (PubSub)SyncPacketSend.getReply(con, request); ItemsExtension itemsElem = (ItemsExtension)result.getExtension(PubSubElementType.ITEMS); @@ -303,7 +346,7 @@ public class LeafNode extends Node { items.add(new Item(id)); } - PubSub request = createPubsubPacket(Type.SET, new ItemsExtension(ItemsExtension.ItemsElementType.retract, getId(), items, null)); + PubSub request = createPubsubPacket(Type.SET, new ItemsExtension(ItemsExtension.ItemsElementType.retract, getId(), items)); SyncPacketSend.getReply(con, request); } } diff --git a/source/org/jivesoftware/smackx/pubsub/provider/ItemsProvider.java b/source/org/jivesoftware/smackx/pubsub/provider/ItemsProvider.java index d058786d5..01cb9d4b2 100644 --- a/source/org/jivesoftware/smackx/pubsub/provider/ItemsProvider.java +++ b/source/org/jivesoftware/smackx/pubsub/provider/ItemsProvider.java @@ -32,7 +32,7 @@ public class ItemsProvider extends EmbeddedExtensionProvider @Override protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map attributeMap, List content) { - return new ItemsExtension(ItemsExtension.ItemsElementType.items, attributeMap.get("node"), content, null); + return new ItemsExtension(ItemsExtension.ItemsElementType.items, attributeMap.get("node"), content); } } diff --git a/test/org/jivesoftware/smackx/pubsub/MultiUserSubscriptionUseCases.java b/test/org/jivesoftware/smackx/pubsub/MultiUserSubscriptionUseCases.java index c3779f682..25e2e3a02 100644 --- a/test/org/jivesoftware/smackx/pubsub/MultiUserSubscriptionUseCases.java +++ b/test/org/jivesoftware/smackx/pubsub/MultiUserSubscriptionUseCases.java @@ -1,8 +1,10 @@ package org.jivesoftware.smackx.pubsub; import java.util.Collection; +import java.util.List; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smackx.pubsub.test.PubSubTestCase; public class MultiUserSubscriptionUseCases extends PubSubTestCase @@ -29,4 +31,31 @@ public class MultiUserSubscriptionUseCases extends PubSubTestCase Collection items = user2Node.getItems(); assertTrue(items.size() == 5); } + + public void testGetItemsWithMultiSubscription() throws XMPPException + { + LeafNode node = getRandomPubnode(getManager(0), true, false); + node.send((Item)null); + node.send((Item)null); + node.send((Item)null); + node.send((Item)null); + node.send((Item)null); + + LeafNode user2Node = (LeafNode) getManager(1).getNode(node.getId()); + Subscription sub1 = user2Node.subscribe(getBareJID(1)); + + Subscription sub2 = user2Node.subscribe(getBareJID(1)); + + try + { + user2Node.getItems(); + } + catch (XMPPException exc) + { + assertEquals("bad-request", exc.getXMPPError().getCondition()); + assertEquals(XMPPError.Type.MODIFY, exc.getXMPPError().getType()); + } + List items = user2Node.getItems(sub1.getId()); + assertTrue(items.size() == 5); + } } diff --git a/test/org/jivesoftware/smackx/pubsub/SubscriberUseCases.java b/test/org/jivesoftware/smackx/pubsub/SubscriberUseCases.java index 461728222..b5c3f8c32 100644 --- a/test/org/jivesoftware/smackx/pubsub/SubscriberUseCases.java +++ b/test/org/jivesoftware/smackx/pubsub/SubscriberUseCases.java @@ -130,13 +130,6 @@ public class SubscriberUseCases extends SingleUserTestCase // } // - public void testGetItemsWithSingleSubscription() throws XMPPException - { - LeafNode node = getPubnode(true, false); - node.subscribe(getBareJID(0)); - runNodeTests(node); - } - public void testGetItems() throws XMPPException { LeafNode node = getPubnode(true, false);