Add support for retrieving PubSub Node affiliations

This also marks the starting point for extending the PubSub API to allow
additional packet extensions to be added to the request. This is for
example useful if one wants to limit the result with "Result Set
Management (XEP-59)".

Fixes SMACK-580.
This commit is contained in:
Florian Schmaus 2014-07-09 12:57:51 +02:00
parent 4477561d4b
commit fc39ac88bd
4 changed files with 136 additions and 70 deletions

View File

@ -98,7 +98,9 @@ abstract public class Node
*/
public ConfigureForm getNodeConfiguration() throws NoResponseException, XMPPErrorException, NotConnectedException
{
Packet reply = sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.CONFIGURE_OWNER, getId()), PubSubNamespace.OWNER);
PubSub pubSub = createPubsubPacket(Type.GET, new NodeExtension(
PubSubElementType.CONFIGURE_OWNER, getId()), PubSubNamespace.OWNER);
Packet reply = sendPubsubPacket(pubSub);
return NodeUtils.getFormFromPacket(reply, PubSubElementType.CONFIGURE_OWNER);
}
@ -112,7 +114,8 @@ abstract public class Node
*/
public void sendConfigurationForm(Form submitForm) throws NoResponseException, XMPPErrorException, NotConnectedException
{
PubSub packet = createPubsubPacket(Type.SET, new FormNode(FormNodeType.CONFIGURE_OWNER, getId(), submitForm), PubSubNamespace.OWNER);
PubSub packet = createPubsubPacket(Type.SET, new FormNode(FormNodeType.CONFIGURE_OWNER,
getId(), submitForm), PubSubNamespace.OWNER);
con.createPacketCollectorAndSend(packet).nextResultOrThrow();
}
@ -143,11 +146,85 @@ abstract public class Node
*/
public List<Subscription> getSubscriptions() throws NoResponseException, XMPPErrorException, NotConnectedException
{
PubSub reply = (PubSub)sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.SUBSCRIPTIONS, getId()));
SubscriptionsExtension subElem = (SubscriptionsExtension)reply.getExtension(PubSubElementType.SUBSCRIPTIONS);
return subElem.getSubscriptions();
return getSubscriptions(null, null);
}
/**
* Get the subscriptions currently associated with this node.
* <p>
* {@code additionalExtensions} can be used e.g. to add a "Result Set Management" extension.
* {@code returnedExtensions} will be filled with the packet extensions found in the answer.
* </p>
*
* @param additionalExtensions
* @param returnedExtensions a collection that will be filled with the returned packet
* extensions
* @return List of {@link Subscription}
* @throws NoResponseException
* @throws XMPPErrorException
* @throws NotConnectedException
*/
public List<Subscription> getSubscriptions(List<PacketExtension> additionalExtensions, Collection<PacketExtension> returnedExtensions)
throws NoResponseException, XMPPErrorException, NotConnectedException {
PubSub pubSub = createPubsubPacket(Type.GET, new NodeExtension(
PubSubElementType.SUBSCRIPTIONS, getId()));
if (additionalExtensions != null) {
for (PacketExtension pe : additionalExtensions) {
pubSub.addExtension(pe);
}
}
PubSub reply = (PubSub) sendPubsubPacket(pubSub);
if (returnedExtensions != null) {
returnedExtensions.addAll(reply.getExtensions());
}
SubscriptionsExtension subElem = (SubscriptionsExtension) reply.getExtension(PubSubElementType.SUBSCRIPTIONS);
return subElem.getSubscriptions();
}
/**
* Get the affiliations of this node.
*
* @return List of {@link Affiliation}
* @throws NoResponseException
* @throws XMPPErrorException
* @throws NotConnectedException
*/
public List<Affiliation> getAffiliations() throws NoResponseException, XMPPErrorException,
NotConnectedException {
return getAffiliations(null, null);
}
/**
* Get the affiliations of this node.
* <p>
* {@code additionalExtensions} can be used e.g. to add a "Result Set Management" extension.
* {@code returnedExtensions} will be filled with the packet extensions found in the answer.
* </p>
*
* @param additionalExtensions additional {@code PacketExtensions} add to the request
* @param returnedExtensions a collection that will be filled with the returned packet
* extensions
* @return List of {@link Affiliation}
* @throws NoResponseException
* @throws XMPPErrorException
* @throws NotConnectedException
*/
public List<Affiliation> getAffiliations(List<PacketExtension> additionalExtensions, Collection<PacketExtension> returnedExtensions)
throws NoResponseException, XMPPErrorException, NotConnectedException {
PubSub pubSub = createPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.AFFILIATIONS, getId()));
if (additionalExtensions != null) {
for (PacketExtension pe : additionalExtensions) {
pubSub.addExtension(pe);
}
}
PubSub reply = (PubSub) sendPubsubPacket(pubSub);
if (returnedExtensions != null) {
returnedExtensions.addAll(reply.getExtensions());
}
AffiliationsExtension affilElem = (AffiliationsExtension) reply.getExtension(PubSubElementType.AFFILIATIONS);
return affilElem.getAffiliations();
}
/**
* The user subscribes to the node using the supplied jid. The
* bare jid portion of this one must match the jid for the connection.
@ -167,7 +244,8 @@ abstract public class Node
*/
public Subscription subscribe(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException
{
PubSub reply = (PubSub)sendPubsubPacket(Type.SET, new SubscribeExtension(jid, getId()));
PubSub pubSub = createPubsubPacket(Type.SET, new SubscribeExtension(jid, getId()));
PubSub reply = (PubSub)sendPubsubPacket(pubSub);
return (Subscription)reply.getExtension(PubSubElementType.SUBSCRIPTION);
}
@ -191,9 +269,9 @@ abstract public class Node
*/
public Subscription subscribe(String jid, SubscribeForm subForm) throws NoResponseException, XMPPErrorException, NotConnectedException
{
PubSub request = createPubsubPacket(Type.SET, new SubscribeExtension(jid, getId()));
PubSub request = createPubsubPacket(Type.SET, new SubscribeExtension(jid, getId()));
request.addExtension(new FormNode(FormNodeType.OPTIONS, subForm));
PubSub reply = (PubSub)PubSubManager.sendPubsubPacket(con, jid, Type.SET, request);
PubSub reply = (PubSub)PubSubManager.sendPubsubPacket(con, request);
return (Subscription)reply.getExtension(PubSubElementType.SUBSCRIPTION);
}
@ -224,7 +302,7 @@ abstract public class Node
*/
public void unsubscribe(String jid, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException
{
sendPubsubPacket(Type.SET, new UnsubscribeExtension(jid, getId(), subscriptionId));
sendPubsubPacket(createPubsubPacket(Type.SET, new UnsubscribeExtension(jid, getId(), subscriptionId)));
}
/**
@ -256,7 +334,7 @@ abstract public class Node
*/
public SubscribeForm getSubscriptionOptions(String jid, String subscriptionId) throws NoResponseException, XMPPErrorException, NotConnectedException
{
PubSub packet = (PubSub)sendPubsubPacket(Type.GET, new OptionsExtension(jid, getId(), subscriptionId));
PubSub packet = (PubSub)sendPubsubPacket(createPubsubPacket(Type.GET, new OptionsExtension(jid, getId(), subscriptionId)));
FormNode ext = (FormNode)packet.getExtension(PubSubElementType.OPTIONS);
return new SubscribeForm(ext.getForm());
}
@ -357,17 +435,12 @@ abstract public class Node
protected PubSub createPubsubPacket(Type type, PacketExtension ext, PubSubNamespace ns)
{
return PubSubManager.createPubsubPacket(to, type, ext, ns);
return PubSub.createPubsubPacket(to, type, ext, ns);
}
protected Packet sendPubsubPacket(Type type, NodeExtension ext) throws NoResponseException, XMPPErrorException, NotConnectedException
protected Packet sendPubsubPacket(PubSub packet) throws NoResponseException, XMPPErrorException, NotConnectedException
{
return PubSubManager.sendPubsubPacket(con, to, type, ext);
}
protected Packet sendPubsubPacket(Type type, NodeExtension ext, PubSubNamespace ns) throws NoResponseException, XMPPErrorException, NotConnectedException
{
return PubSubManager.sendPubsubPacket(con, to, type, ext, ns);
return PubSubManager.sendPubsubPacket(con, packet);
}

View File

@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.pubsub;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -86,7 +87,7 @@ final public class PubSubManager
*/
public LeafNode createNode() throws NoResponseException, XMPPErrorException, NotConnectedException
{
PubSub reply = (PubSub)sendPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.CREATE));
PubSub reply = (PubSub)sendPubsubPacket(Type.SET, new NodeExtension(PubSubElementType.CREATE), null);
NodeExtension elem = (NodeExtension)reply.getExtension("create", PubSubNamespace.BASIC.getXmlns());
LeafNode newNode = new LeafNode(con, elem.getNode());
@ -126,7 +127,7 @@ final public class PubSubManager
*/
public Node createNode(String name, Form config) throws NoResponseException, XMPPErrorException, NotConnectedException
{
PubSub request = createPubsubPacket(to, Type.SET, new NodeExtension(PubSubElementType.CREATE, name));
PubSub request = PubSub.createPubsubPacket(to, Type.SET, new NodeExtension(PubSubElementType.CREATE, name), null);
boolean isLeafNode = true;
if (config != null)
@ -140,7 +141,7 @@ final public class PubSubManager
// Errors will cause exceptions in getReply, so it only returns
// on success.
sendPubsubPacket(con, to, Type.SET, request);
sendPubsubPacket(con, request);
Node newNode = isLeafNode ? new LeafNode(con, name) : new CollectionNode(con, name);
newNode.setTo(to);
nodeMap.put(newNode.getId(), newNode);
@ -217,7 +218,7 @@ final public class PubSubManager
*/
public List<Subscription> getSubscriptions() throws NoResponseException, XMPPErrorException, NotConnectedException
{
Packet reply = sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.SUBSCRIPTIONS));
Packet reply = sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.SUBSCRIPTIONS), null);
SubscriptionsExtension subElem = (SubscriptionsExtension)reply.getExtension(PubSubElementType.SUBSCRIPTIONS.getElementName(), PubSubElementType.SUBSCRIPTIONS.getNamespace().getXmlns());
return subElem.getSubscriptions();
}
@ -233,7 +234,7 @@ final public class PubSubManager
*/
public List<Affiliation> getAffiliations() throws NoResponseException, XMPPErrorException, NotConnectedException
{
PubSub reply = (PubSub)sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.AFFILIATIONS));
PubSub reply = (PubSub)sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.AFFILIATIONS), null);
AffiliationsExtension listElem = (AffiliationsExtension)reply.getExtension(PubSubElementType.AFFILIATIONS);
return listElem.getAffiliations();
}
@ -282,53 +283,22 @@ final public class PubSubManager
ServiceDiscoveryManager mgr = ServiceDiscoveryManager.getInstanceFor(con);
return mgr.discoverInfo(to);
}
private Packet sendPubsubPacket(Type type, PacketExtension ext, PubSubNamespace ns) throws NoResponseException, XMPPErrorException, NotConnectedException
private Packet sendPubsubPacket(Type type, PacketExtension ext, PubSubNamespace ns)
throws NoResponseException, XMPPErrorException, NotConnectedException {
return sendPubsubPacket(con, to, type, Collections.singletonList(ext), ns);
}
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, List<PacketExtension> extList, PubSubNamespace ns) throws NoResponseException, XMPPErrorException, NotConnectedException
{
return sendPubsubPacket(con, to, type, ext, ns);
PubSub pubSub = new PubSub(to, type, ns);
for (PacketExtension pe : extList) {
pubSub.addExtension(pe);
}
return sendPubsubPacket(con ,pubSub);
}
private Packet sendPubsubPacket(Type type, PacketExtension ext) throws NoResponseException, XMPPErrorException, NotConnectedException
{
return sendPubsubPacket(type, ext, null);
}
static PubSub createPubsubPacket(String to, Type type, PacketExtension ext)
{
return createPubsubPacket(to, type, ext, null);
}
static PubSub createPubsubPacket(String to, Type type, PacketExtension ext, PubSubNamespace ns)
{
PubSub request = new PubSub();
request.setTo(to);
request.setType(type);
if (ns != null)
{
request.setPubSubNamespace(ns);
}
request.addExtension(ext);
return request;
}
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, PacketExtension ext) throws NoResponseException, XMPPErrorException, NotConnectedException
{
return sendPubsubPacket(con, to, type, ext, null);
}
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, PacketExtension ext, PubSubNamespace ns) throws NoResponseException, XMPPErrorException, NotConnectedException
{
return con.createPacketCollectorAndSend(createPubsubPacket(to, type, ext, ns)).nextResultOrThrow();
}
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, PubSub packet) throws NoResponseException, XMPPErrorException, NotConnectedException
{
return sendPubsubPacket(con, to, type, packet, null);
}
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, PubSub packet, PubSubNamespace ns) throws NoResponseException, XMPPErrorException, NotConnectedException
static Packet sendPubsubPacket(XMPPConnection con, PubSub packet) throws NoResponseException, XMPPErrorException, NotConnectedException
{
return con.createPacketCollectorAndSend(packet).nextResultOrThrow();
}

View File

@ -29,15 +29,33 @@ import org.jivesoftware.smackx.pubsub.PubSubElementType;
*/
public class PubSub extends IQ
{
public static final String ELEMENT = "pubsub";
public static final String NAMESPACE = "http://jabber.org/protocol/pubsub";
private PubSubNamespace ns = PubSubNamespace.BASIC;
public PubSub() {
}
public PubSub(String to, Type type) {
setTo(to);
setType(type);
}
public PubSub(String to, Type type, PubSubNamespace ns) {
this(to, type);
if (ns != null) {
setPubSubNamespace(ns);
}
}
/**
* Returns the XML element name of the extension sub-packet root element.
*
* @return the XML element name of the packet extension.
*/
public String getElementName() {
return "pubsub";
return ELEMENT;
}
/**
@ -106,4 +124,9 @@ public class PubSub extends IQ
return buf.toString();
}
public static PubSub createPubsubPacket(String to, Type type, PacketExtension extension, PubSubNamespace ns) {
PubSub pubSub = new PubSub(to, type, ns);
pubSub.addExtension(extension);
return pubSub;
}
}

View File

@ -40,7 +40,7 @@ public enum PubSubNamespace
public String getXmlns()
{
String ns = "http://jabber.org/protocol/pubsub";
String ns = PubSub.NAMESPACE;
if (fragment != null)
ns += '#' + fragment;