diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java index b230b89b1..770bf8ff9 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java @@ -217,6 +217,31 @@ public abstract class Node { return subElem.getSubscriptions(); } + /** + * Modify the subscriptions for this PubSub node as owner. + *

+ * Note that the subscriptions are _not_ checked against the existing subscriptions + * since these are not cached (and indeed could change asynchronously) + *

+ * + * @param changedSubs subscriptions that have changed + * @return null or a PubSub stanza with additional information on success. + * @throws NoResponseException + * @throws XMPPErrorException + * @throws NotConnectedException + * @throws InterruptedException + * @see XEP-60 ยง 8.8.2 Modify Subscriptions + * @since 4.3 + */ + public PubSub modifySubscriptionsAsOwner(List changedSubs) + throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + + PubSub pubSub = createPubsubPacket(Type.set, + new SubscriptionsExtension(getId(), changedSubs), + PubSubNamespace.OWNER); + return sendPubsubPacket(pubSub); + } + /** * Get the affiliations of this node. * diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Subscription.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Subscription.java index 144dc308d..a00fcc7e1 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Subscription.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Subscription.java @@ -56,6 +56,16 @@ public class Subscription extends NodeExtension { this(subscriptionJid, nodeId, null, null); } + /** + * Construct a subscription change request to the specified state. + * + * @param subscriptionJid The subscriber JID + * @param state The requested new state + */ + public Subscription(Jid subscriptionJid, State state) { + this(subscriptionJid, null, null, state); + } + /** * Constructs a representation of a subscription reply to the specified node * and JID. The server will have supplied the subscription id and current state. diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/pubsub/PubSubNodeTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/pubsub/PubSubNodeTest.java new file mode 100644 index 000000000..28bf82a31 --- /dev/null +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/pubsub/PubSubNodeTest.java @@ -0,0 +1,70 @@ +/** + * + * Copyright 2018 Timothy Pitt + * + * 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; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.ThreadedDummyConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.test.util.TestUtils; +import org.jivesoftware.smack.util.PacketParserUtils; +import org.jivesoftware.smackx.pubsub.packet.PubSub; + +import org.junit.Test; +import org.jxmpp.jid.JidTestUtil; +import org.jxmpp.jid.impl.JidCreate; +import org.xmlpull.v1.XmlPullParser; + +public class PubSubNodeTest { + + @Test + public void modifySubscriptionsAsOwnerTest() throws InterruptedException, SmackException, IOException, XMPPException, Exception { + ThreadedDummyConnection con = ThreadedDummyConnection.newInstance(); + PubSubManager mgr = new PubSubManager(con, JidTestUtil.PUBSUB_EXAMPLE_ORG); + Node testNode = new LeafNode(mgr, "princely_musings"); + + List ChangeSubs = Arrays.asList( + new Subscription(JidCreate.from("romeo@montague.org"), Subscription.State.subscribed), + new Subscription(JidCreate.from("juliet@capulet.org"), Subscription.State.none) + ); + testNode.modifySubscriptionsAsOwner(ChangeSubs); + + PubSub request = con.getSentPacket(); + + assertEquals("http://jabber.org/protocol/pubsub#owner", request.getChildElementNamespace()); + assertEquals("pubsub", request.getChildElementName()); + + XmlPullParser parser = TestUtils.getIQParser(request.toXML().toString()); + PubSub pubsubResult = (PubSub) PacketParserUtils.parseIQ(parser); + SubscriptionsExtension subElem = pubsubResult.getExtension(PubSubElementType.SUBSCRIPTIONS); + List subscriptions = subElem.getSubscriptions(); + assertEquals(2, subscriptions.size()); + + Subscription sub1 = subscriptions.get(0); + assertEquals("romeo@montague.org", sub1.getJid().toString()); + assertEquals(Subscription.State.subscribed, sub1.getState()); + + Subscription sub2 = subscriptions.get(1); + assertEquals("juliet@capulet.org", sub2.getJid().toString()); + assertEquals(Subscription.State.none, sub2.getState()); + } +}