mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 22:32:06 +01:00
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:
parent
4477561d4b
commit
fc39ac88bd
4 changed files with 136 additions and 70 deletions
|
@ -98,7 +98,9 @@ abstract public class Node
|
||||||
*/
|
*/
|
||||||
public ConfigureForm getNodeConfiguration() throws NoResponseException, XMPPErrorException, NotConnectedException
|
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);
|
return NodeUtils.getFormFromPacket(reply, PubSubElementType.CONFIGURE_OWNER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +114,8 @@ abstract public class Node
|
||||||
*/
|
*/
|
||||||
public void sendConfigurationForm(Form submitForm) throws NoResponseException, XMPPErrorException, NotConnectedException
|
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();
|
con.createPacketCollectorAndSend(packet).nextResultOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,11 +146,85 @@ abstract public class Node
|
||||||
*/
|
*/
|
||||||
public List<Subscription> getSubscriptions() throws NoResponseException, XMPPErrorException, NotConnectedException
|
public List<Subscription> getSubscriptions() throws NoResponseException, XMPPErrorException, NotConnectedException
|
||||||
{
|
{
|
||||||
PubSub reply = (PubSub)sendPubsubPacket(Type.GET, new NodeExtension(PubSubElementType.SUBSCRIPTIONS, getId()));
|
return getSubscriptions(null, null);
|
||||||
SubscriptionsExtension subElem = (SubscriptionsExtension)reply.getExtension(PubSubElementType.SUBSCRIPTIONS);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
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
|
* The user subscribes to the node using the supplied jid. The
|
||||||
* bare jid portion of this one must match the jid for the connection.
|
* 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
|
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);
|
return (Subscription)reply.getExtension(PubSubElementType.SUBSCRIPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +271,7 @@ abstract public class Node
|
||||||
{
|
{
|
||||||
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));
|
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);
|
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
|
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
|
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);
|
FormNode ext = (FormNode)packet.getExtension(PubSubElementType.OPTIONS);
|
||||||
return new SubscribeForm(ext.getForm());
|
return new SubscribeForm(ext.getForm());
|
||||||
}
|
}
|
||||||
|
@ -357,17 +435,12 @@ abstract public class Node
|
||||||
|
|
||||||
protected PubSub createPubsubPacket(Type type, PacketExtension ext, PubSubNamespace ns)
|
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);
|
return PubSubManager.sendPubsubPacket(con, packet);
|
||||||
}
|
|
||||||
|
|
||||||
protected Packet sendPubsubPacket(Type type, NodeExtension ext, PubSubNamespace ns) throws NoResponseException, XMPPErrorException, NotConnectedException
|
|
||||||
{
|
|
||||||
return PubSubManager.sendPubsubPacket(con, to, type, ext, ns);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.pubsub;
|
package org.jivesoftware.smackx.pubsub;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -86,7 +87,7 @@ final public class PubSubManager
|
||||||
*/
|
*/
|
||||||
public LeafNode createNode() throws NoResponseException, XMPPErrorException, NotConnectedException
|
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());
|
NodeExtension elem = (NodeExtension)reply.getExtension("create", PubSubNamespace.BASIC.getXmlns());
|
||||||
|
|
||||||
LeafNode newNode = new LeafNode(con, elem.getNode());
|
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
|
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;
|
boolean isLeafNode = true;
|
||||||
|
|
||||||
if (config != null)
|
if (config != null)
|
||||||
|
@ -140,7 +141,7 @@ final public class PubSubManager
|
||||||
|
|
||||||
// Errors will cause exceptions in getReply, so it only returns
|
// Errors will cause exceptions in getReply, so it only returns
|
||||||
// on success.
|
// on success.
|
||||||
sendPubsubPacket(con, to, Type.SET, request);
|
sendPubsubPacket(con, request);
|
||||||
Node newNode = isLeafNode ? new LeafNode(con, name) : new CollectionNode(con, name);
|
Node newNode = isLeafNode ? new LeafNode(con, name) : new CollectionNode(con, name);
|
||||||
newNode.setTo(to);
|
newNode.setTo(to);
|
||||||
nodeMap.put(newNode.getId(), newNode);
|
nodeMap.put(newNode.getId(), newNode);
|
||||||
|
@ -217,7 +218,7 @@ final public class PubSubManager
|
||||||
*/
|
*/
|
||||||
public List<Subscription> getSubscriptions() throws NoResponseException, XMPPErrorException, NotConnectedException
|
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());
|
SubscriptionsExtension subElem = (SubscriptionsExtension)reply.getExtension(PubSubElementType.SUBSCRIPTIONS.getElementName(), PubSubElementType.SUBSCRIPTIONS.getNamespace().getXmlns());
|
||||||
return subElem.getSubscriptions();
|
return subElem.getSubscriptions();
|
||||||
}
|
}
|
||||||
|
@ -233,7 +234,7 @@ final public class PubSubManager
|
||||||
*/
|
*/
|
||||||
public List<Affiliation> getAffiliations() throws NoResponseException, XMPPErrorException, NotConnectedException
|
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);
|
AffiliationsExtension listElem = (AffiliationsExtension)reply.getExtension(PubSubElementType.AFFILIATIONS);
|
||||||
return listElem.getAffiliations();
|
return listElem.getAffiliations();
|
||||||
}
|
}
|
||||||
|
@ -283,52 +284,21 @@ final public class PubSubManager
|
||||||
return mgr.discoverInfo(to);
|
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, ext, ns);
|
return sendPubsubPacket(con, to, type, Collections.singletonList(ext), ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Packet sendPubsubPacket(Type type, PacketExtension ext) throws NoResponseException, XMPPErrorException, NotConnectedException
|
static Packet sendPubsubPacket(XMPPConnection con, String to, Type type, List<PacketExtension> extList, PubSubNamespace ns) throws NoResponseException, XMPPErrorException, NotConnectedException
|
||||||
{
|
{
|
||||||
return sendPubsubPacket(type, ext, null);
|
PubSub pubSub = new PubSub(to, type, ns);
|
||||||
|
for (PacketExtension pe : extList) {
|
||||||
|
pubSub.addExtension(pe);
|
||||||
|
}
|
||||||
|
return sendPubsubPacket(con ,pubSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PubSub createPubsubPacket(String to, Type type, PacketExtension ext)
|
static Packet sendPubsubPacket(XMPPConnection con, PubSub packet) throws NoResponseException, XMPPErrorException, NotConnectedException
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
return con.createPacketCollectorAndSend(packet).nextResultOrThrow();
|
return con.createPacketCollectorAndSend(packet).nextResultOrThrow();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,15 +29,33 @@ import org.jivesoftware.smackx.pubsub.PubSubElementType;
|
||||||
*/
|
*/
|
||||||
public class PubSub extends IQ
|
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;
|
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.
|
* Returns the XML element name of the extension sub-packet root element.
|
||||||
*
|
*
|
||||||
* @return the XML element name of the packet extension.
|
* @return the XML element name of the packet extension.
|
||||||
*/
|
*/
|
||||||
public String getElementName() {
|
public String getElementName() {
|
||||||
return "pubsub";
|
return ELEMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,4 +124,9 @@ public class PubSub extends IQ
|
||||||
return buf.toString();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public enum PubSubNamespace
|
||||||
|
|
||||||
public String getXmlns()
|
public String getXmlns()
|
||||||
{
|
{
|
||||||
String ns = "http://jabber.org/protocol/pubsub";
|
String ns = PubSub.NAMESPACE;
|
||||||
|
|
||||||
if (fragment != null)
|
if (fragment != null)
|
||||||
ns += '#' + fragment;
|
ns += '#' + fragment;
|
||||||
|
|
Loading…
Reference in a new issue