mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-12-26 06:07:59 +01:00
Add support for XEP-0059: Result Set Management
SMACK-581
This commit is contained in:
parent
d3cea48c0d
commit
2dc93d7639
11 changed files with 407 additions and 10 deletions
|
@ -36,6 +36,7 @@ Smack Extensions and currently supported XEPs by Smack (smack-extensions)
|
|||
| Ad-Hoc Commands | [XEP-0050](http://xmpp.org/extensions/xep-0049.html) | Advertising and executing application-specific commands. |
|
||||
| vcard-temp | [XEP-0054](http://xmpp.org/extensions/xep-0049.html) | The vCard-XML format currently in use. |
|
||||
| Jabber Search | [XEP-0055](http://xmpp.org/extensions/xep-0055.html) | Search information repositories on the XMPP network. |
|
||||
| Result Set Management | [XEP-0059](http://xmpp.org/extensions/xep-0059.html) | Page through and otherwise manage the receipt of large result sets |
|
||||
| [PubSub](pubsub.html) | [XEP-0060](http://xmpp.org/extensions/xep-0060.html) | Generic publish and subscribe functionality. |
|
||||
| SOCKS5 Bytestrams | [XEP-0065](http://xmpp.org/extensions/xep-0065.html) | Out-of-band bytestream between any two XMPP entities. |
|
||||
| [XHTML-IM](xhtml.html) | [XEP-0071](http://xmpp.org/extensions/xep-0071.html) | Allows send and receiving formatted messages using XHTML. |
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.jivesoftware.smack.packet;
|
||||
|
||||
import org.jivesoftware.smack.util.PacketUtil;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
|
@ -232,19 +233,11 @@ public abstract class Packet extends TopLevelStreamElement {
|
|||
* @param namespace the XML element namespace of the packet extension.
|
||||
* @return the extension, or <tt>null</tt> if it doesn't exist.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <PE extends PacketExtension> PE getExtension(String elementName, String namespace) {
|
||||
if (namespace == null) {
|
||||
return null;
|
||||
}
|
||||
for (PacketExtension ext : packetExtensions) {
|
||||
if ((elementName == null || elementName.equals(ext.getElementName()))
|
||||
&& namespace.equals(ext.getNamespace()))
|
||||
{
|
||||
return (PE) ext;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return PacketUtil.packetExtensionfromCollection(packetExtensions, elementName, namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* Copyright © 2014 Florian Schmaus
|
||||
*
|
||||
* 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.smack.util;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jivesoftware.smack.packet.PacketExtension;
|
||||
|
||||
public class PacketUtil {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <PE extends PacketExtension> PE packetExtensionfromCollection(
|
||||
Collection<PacketExtension> collection, String element,
|
||||
String namespace) {
|
||||
for (PacketExtension packetExtension : collection) {
|
||||
if ((element == null || packetExtension.getElementName().equals(
|
||||
element))
|
||||
&& packetExtension.getNamespace().equals(namespace)) {
|
||||
return (PE) packetExtension;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.jivesoftware.smack.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
@ -77,6 +78,11 @@ public class ParserUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static int getIntegerFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
String intString = parser.nextText();
|
||||
return Integer.valueOf(intString);
|
||||
}
|
||||
|
||||
public static Long getLongAttribute(XmlPullParser parser, String name) {
|
||||
String valueString = parser.getAttributeValue("", name);
|
||||
if (valueString == null)
|
||||
|
|
|
@ -86,6 +86,13 @@ public class XmlStringBuilder implements Appendable, CharSequence {
|
|||
return this;
|
||||
}
|
||||
|
||||
public XmlStringBuilder optIntElement(String name, int value) {
|
||||
if (value >= 0) {
|
||||
element(name, String.valueOf(value));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmlStringBuilder halfOpenElement(String name) {
|
||||
sb.append('<').append(name);
|
||||
return this;
|
||||
|
|
|
@ -45,7 +45,7 @@ public class PubSubProvider implements IQProvider
|
|||
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
PacketExtension ext = PacketParserUtils.parsePacketExtension(parser.getName(), namespace, parser);
|
||||
PacketExtension ext = PacketParserUtils.parsePacketExtension(parser.getName(), parser.getNamespace(), parser);
|
||||
|
||||
if (ext != null)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
*
|
||||
* Copyright © 2014 Florian Schmaus
|
||||
*
|
||||
* 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.rsm;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.packet.PacketExtension;
|
||||
import org.jivesoftware.smack.util.PacketUtil;
|
||||
import org.jivesoftware.smackx.rsm.packet.RSMSet;
|
||||
import org.jivesoftware.smackx.rsm.packet.RSMSet.PageDirection;
|
||||
|
||||
public class RSMManager {
|
||||
|
||||
Collection<PacketExtension> page(int max) {
|
||||
List<PacketExtension> packetExtensions = new LinkedList<PacketExtension>();
|
||||
packetExtensions.add(new RSMSet(max));
|
||||
return packetExtensions;
|
||||
}
|
||||
|
||||
Collection<PacketExtension> contiunePage(int max, Collection<PacketExtension> returnedExtensions) {
|
||||
return continuePage(max, returnedExtensions, null);
|
||||
}
|
||||
|
||||
Collection<PacketExtension> continuePage(int max,
|
||||
Collection<PacketExtension> returnedExtensions,
|
||||
Collection<PacketExtension> additionalExtensions) {
|
||||
if (returnedExtensions == null) {
|
||||
throw new IllegalArgumentException("returnedExtensions must no be null");
|
||||
}
|
||||
if (additionalExtensions == null) {
|
||||
additionalExtensions = new LinkedList<PacketExtension>();
|
||||
}
|
||||
RSMSet resultRsmSet = PacketUtil.packetExtensionfromCollection(returnedExtensions, RSMSet.ELEMENT, RSMSet.NAMESPACE);
|
||||
if (resultRsmSet == null) {
|
||||
throw new IllegalArgumentException("returnedExtensions did not contain a RSMset");
|
||||
}
|
||||
RSMSet continePageRsmSet = new RSMSet(max, resultRsmSet.getLast(), PageDirection.after);
|
||||
additionalExtensions.add(continePageRsmSet);
|
||||
return additionalExtensions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
*
|
||||
* Copyright © 2014 Florian Schmaus
|
||||
*
|
||||
* 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.rsm.packet;
|
||||
|
||||
import org.jivesoftware.smack.packet.PacketExtension;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
public class RSMSet implements PacketExtension {
|
||||
|
||||
public static final String ELEMENT = "set";
|
||||
public static final String NAMESPACE = "http://jabber.org/protocol/rsm";
|
||||
|
||||
private final String after;
|
||||
private final String before;
|
||||
private final int count;
|
||||
private final int index;
|
||||
private final String last;
|
||||
private final int max;
|
||||
private final String firstString;
|
||||
private final int firstIndex;
|
||||
|
||||
public static enum PageDirection {
|
||||
before,
|
||||
after;
|
||||
}
|
||||
|
||||
public RSMSet(int max) {
|
||||
this(max, -1);
|
||||
}
|
||||
|
||||
public RSMSet(int max, int index) {
|
||||
this(null, null, -1, index, null, max, null, -1);
|
||||
}
|
||||
|
||||
public RSMSet(int max, String item, PageDirection pageDirection) {
|
||||
switch (pageDirection) {
|
||||
case before:
|
||||
this.before = item;
|
||||
this.after = null;
|
||||
break;
|
||||
case after:
|
||||
this.before = null;
|
||||
this.after = item;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
this.count = -1;
|
||||
this.index = -1;
|
||||
this.last = null;
|
||||
this.max = max;
|
||||
this.firstString = null;
|
||||
this.firstIndex = -1;
|
||||
}
|
||||
|
||||
public RSMSet(String after, String before, int count, int index,
|
||||
String last, int max, String firstString, int firstIndex) {
|
||||
this.after = after;
|
||||
this.before = before;
|
||||
this.count = count;
|
||||
this.index = index;
|
||||
this.last = last;
|
||||
this.max = max;
|
||||
this.firstString = firstString;
|
||||
this.firstIndex = firstIndex;
|
||||
}
|
||||
|
||||
public String getAfter() {
|
||||
return after;
|
||||
}
|
||||
|
||||
public String getBefore() {
|
||||
return before;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public String getLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
public String getFirst() {
|
||||
return firstString;
|
||||
}
|
||||
|
||||
public int getFirstIndex() {
|
||||
return firstIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return ELEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return NAMESPACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.rightAngleBracket();
|
||||
xml.optElement("after", after);
|
||||
xml.optElement("before", before);
|
||||
xml.optIntElement("count", count);
|
||||
if (firstString != null) {
|
||||
xml.halfOpenElement("first");
|
||||
xml.optIntAttribute("index", firstIndex);
|
||||
xml.rightAngleBracket();
|
||||
xml.append(firstString);
|
||||
xml.closeElement("first");
|
||||
}
|
||||
xml.optIntElement("index", index);
|
||||
xml.optElement("last", last);
|
||||
xml.optIntElement("max", max);
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
*
|
||||
* Copyright © 2014 Florian Schmaus
|
||||
*
|
||||
* 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.rsm.provider;
|
||||
|
||||
import org.jivesoftware.smack.packet.PacketExtension;
|
||||
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.rsm.packet.RSMSet;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class RSMSetProvider implements PacketExtensionProvider {
|
||||
|
||||
@Override
|
||||
public PacketExtension parseExtension(XmlPullParser parser)
|
||||
throws Exception {
|
||||
int initialDepth = parser.getDepth();
|
||||
|
||||
String after = null;
|
||||
String before = null;
|
||||
int count = -1;
|
||||
int index = -1;
|
||||
String last = null;
|
||||
int max = -1;
|
||||
String firstString = null;
|
||||
int firstIndex = -1;
|
||||
|
||||
outerloop: while (true) {
|
||||
int event = parser.next();
|
||||
switch (event) {
|
||||
case XmlPullParser.START_TAG:
|
||||
String name = parser.getName();
|
||||
switch (name) {
|
||||
case "after":
|
||||
after = parser.nextText();
|
||||
break;
|
||||
case "before":
|
||||
before = parser.nextText();
|
||||
break;
|
||||
case "count":
|
||||
count = ParserUtils.getIntegerFromNextText(parser);
|
||||
break;
|
||||
case "first":
|
||||
firstIndex = ParserUtils.getIntegerAttribute(parser,
|
||||
"index", -1);
|
||||
firstString = parser.nextText();
|
||||
break;
|
||||
case "index":
|
||||
index = ParserUtils.getIntegerFromNextText(parser);
|
||||
break;
|
||||
case "last":
|
||||
last = parser.nextText();
|
||||
break;
|
||||
case "max":
|
||||
max = ParserUtils.getIntegerFromNextText(parser);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XmlPullParser.END_TAG:
|
||||
if (parser.getDepth() == initialDepth) {
|
||||
break outerloop;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new RSMSet(after, before, count, index, last, max, firstString,
|
||||
firstIndex);
|
||||
}
|
||||
|
||||
}
|
|
@ -474,4 +474,11 @@
|
|||
<namespace>http://jabber.org/features/iq-register</namespace>
|
||||
<className>org.jivesoftware.smackx.iqregister.provider.RegistrationStreamFeatureProvider</className>
|
||||
</streamFeatureProvider>
|
||||
|
||||
<!-- XEP-0059: Result Set Management -->
|
||||
<extensionProvider>
|
||||
<elementName>set</elementName>
|
||||
<namespace>http://jabber.org/protocol/rsm</namespace>
|
||||
<className>org.jivesoftware.smackx.rsm.provider.RSMSetProvider</className>
|
||||
</extensionProvider>
|
||||
</smackProviders>
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
*
|
||||
* Copyright © 2014 Florian Schmaus
|
||||
*
|
||||
* 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.rsm.provider;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.jivesoftware.smackx.InitExtensions;
|
||||
import org.jivesoftware.smackx.rsm.packet.RSMSet;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RSMSetProviderTest extends InitExtensions {
|
||||
|
||||
@Test
|
||||
public void testRsmSetProvider() throws Exception {
|
||||
// @formatter:off
|
||||
final String rsmset =
|
||||
"<iq type='get' id='iqget'>"
|
||||
+ "<pubsub xmlns='http://jabber.org/protocol/pubsub'>"
|
||||
+ "<set xmlns='http://jabber.org/protocol/rsm'>"
|
||||
+ "<after>aftervalue</after>"
|
||||
+ "<before>beforevalue</before>"
|
||||
+ "<count>1</count>"
|
||||
+ "<first index='2'>foo@bar.com</first>"
|
||||
+ "<index>3</index>"
|
||||
+ "<last>lastvalue</last>"
|
||||
+ "<max>4</max>"
|
||||
+ "</set>"
|
||||
+ "</pubsub>"
|
||||
+ "</iq>";
|
||||
// @formatter:on
|
||||
|
||||
IQ iqWithRsm = (IQ) PacketParserUtils.parseStanza(rsmset);
|
||||
RSMSet rsm = (RSMSet) iqWithRsm.getExtension(RSMSet.ELEMENT, RSMSet.NAMESPACE);
|
||||
assertNotNull(rsm);
|
||||
assertEquals("aftervalue", rsm.getAfter());
|
||||
assertEquals("beforevalue", rsm.getBefore());
|
||||
assertEquals(1, rsm.getCount());
|
||||
assertEquals(2, rsm.getFirstIndex());
|
||||
assertEquals("foo@bar.com", rsm.getFirst());
|
||||
assertEquals(3, rsm.getIndex());
|
||||
assertEquals("lastvalue", rsm.getLast());
|
||||
assertEquals(4, rsm.getMax());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue