Not logged in. · Lost password · Register
Forum: agsXMPP RSS
Avatar
ThomWill #1
Member since Mar 2010 · 9 posts
Group memberships: Members
Show profile · Link to this post
Subject: PubSubIq (for node config)  and xdatacontrol
Hello,

I am working on a pubsub implementation to keep content syndication catalogs updated between a set of syndication partners and have run into several small issues, many of which I have been able to work around, but this one has me stumped.   I am sending OpenFire a request for the configuration form of a given topical node (stream captures below).  I then intend to take the agsXMPP.protocol.x.data.Data that is returned and render it using the xdatacontrol.   I create the request in this way

 agsXMPP.protocol.extensions.pubsub.PubSubIq getter = new agsXMPP.protocol.extensions.pubsub.PubSubIq(IqType.get);
 getter.PubSub.Namespace = "http://jabber.org/protocol/pubsub#owner";
 getter.PubSub.Configure = new Configure(NodeName);

I cannot use the agsXMPP.protocol.extensions.pubsub.owner.PubSubIq class (which would already have this namespace) because the agsXMPP.protocol.extensions.pubsub.owner.Configure class  renders without a tagname and causes stream termination.

(edit)  I have discovered that this only happens when one uses the overloaded constructor that takes a node name... here is why (tagname and namespace are not set in that constructor)

  #region << Constructor >>
        public Configure()
        {
            this.TagName    = "configure";
            this.Namespace  = Uri.PUBSUB_OWNER;
        }

        public Configure(string node)
        {
            this.Node = node;
        }



At issue is in my call back I get the IQ object it is a straight IQ, not a PubSubIQ, which means it is expecting a query element as a child and not a pubsub element as a child.  There seems to be no way to cast this to a pubsubIQ to that I can get to the x.data.DATA object expected by the xdatacontrol.createform() function and no way to gen ANY object by reading / loading it from the XML.   I have tried this

private void GetNodeConfigCallBack(object sender, IQ Iq, object Data)
{
    agsXMPP.protocol.extensions.pubsub.owner.PubSubIq oIq = new agsXMPP.protocol.extensions.pubsub.owner.PubSubIq(IqType.result);                   
    agsXMPP.Xml.Dom.Element pubsub = Iq.SelectSingleElement("pubsub");
 
    oIq.ReplaceChild(pubsub);
...

And although the innerxml of the oIq object now shows:
<pubsub xmlns=\"http://jabber.org/protocol/pubsub#owner\"><configure xmlns=\"http://jabber.org/protocol/pubsub\" node=\"Breast Cancer\"><x xmlns=\"jabber:x:data\" type=\"form\"><title>Node configuration</title><instructions>Please provide the configuration for node \"Breast Cancer\".</instructions><field type=\"jid-multi\" label=\"People to contact with questions\" var=\"pubsub#contact\" /><field type=\"text-single\" label=\"Default language\" var=\"pubsub#language\"><value>English</value></field>
...
<field type=\"text-single\" label=\"Max payload size in bytes\" var=\"pubsub#max_payload_size\"><value>5120</value></field></x></configure></pubsub>


the pubsub object property of oIq still appears to be empty:
<pubsub xmlns=\"http://jabber.org/protocol/pubsub#owner\" />

So, how does one?

A. Cast the Iq passed in the callback to something more meaningful in this context?
B. Create the agsXMPP namespace objects from preparsed xml (from other objects)?
C. Force a refresh of the object model after changing doing a replacechild at the DOM level?
D. Get to the agsXMPP.protocol.x.data.Data for pubsub configuration results Iqs?


Thanks,

ThomWill



From client:<iq type="get" to="pubsub.d194137" from="publisher" id="xmppClientIQ6"><pubsub xmlns="http://jabber.org/protocol/pubsub#owner"><configure xmlns="http://jabber.org/protocol/pubsub" node="Breast Cancer" /></pubsub></iq>
From server:<iq xmlns="jabber:client" from="pubsub.d194137" to="publisher@d194137/CDCPublisher" type="result" id="xmppClientIQ6"><pubsub xmlns="http://jabber.org/protocol/pubsub#owner"><configure xmlns="http://jabber.org/protocol/pubsub" node="Breast Cancer"><x xmlns="jabber:x:data" type="form"><title>Node configuration</title><instructions>Please provide the configuration for node "Breast Cancer".</instructions><field type="hidden" var="FORM_TYPE"><value>http://jabber.org/protocol/pubsub#node_config</value></field><field type="text-single" label="Short name for the node" var="pubsub#title"><value /></field><field type="text-single" label="Description of the node" var="pubsub#description"><value /></field><field type="boolean" label="Allow subscriptions to node" var="pubsub#subscribe"><value>1</value></field><field type="boolean" label="New subscriptions require configuration" var="pubsub#subscription_required"><value>0</value></field><field type="boolean" label="Deliver payloads with event notifications" var="pubsub#deliver_payloads"><value>1</value></field><field type="boolean" label="Notify subscribers when the node configuration changes" var="pubsub#notify_config"><value>1</value></field><field type="boolean" label="Notify subscribers when the node is deleted" var="pubsub#notify_delete"><value>1</value></field><field type="boolean" label="Notify subscribers when items are removed from the node" var="pubsub#notify_retract"><value>1</value></field><field type="boolean" label="Only deliver notifications to available users" var="pubsub#presence_based_delivery"><value>0</value></field><field type="text-single" label="Type of payload data to be provided at this node" var="pubsub#type"><value /></field><field type="text-single" label="Message body XSLT" var="pubsub#body_xslt"><value /></field><field type="text-single" label="Payload XSLT" var="pubsub#dataform_xslt"><value /></field><field type="list-single" label="Specify who may subscribe and retrieve items" var="pubsub#access_model"><option><value>authorize</value></option><option><value>open</value></option><option><value>presence</value></option><option><value>roster</value></option><option><value>whitelist</value></option><value>open</value></field><field type="list-single" label="Publisher model" var="pubsub#publish_model"><option><value>publishers</value></option><option><value>subscribers</value></option><option><value>open</value></option><value>publishers</value></field><field type="list-multi" label="Roster groups allowed to subscribe" var="pubsub#roster_groups_allowed" /><field type="jid-multi" label="People to contact with questions" var="pubsub#contact" /><field type="text-single" label="Default language" var="pubsub#language"><value>English</value></field><field type="jid-multi" label="Node owners" var="pubsub#owner"><value>publisher@d194137</value></field><field type="jid-multi" label="Node publishers" var="pubsub#publisher" /><field type="list-single" label="Select entity that should receive replies to items" var="pubsub#itemreply"><value>owner</value></field><field type="jid-multi" label="Multi-user chat room to which replies should be sent" var="pubsub#replyroom" /><field type="jid-multi" label="Users to which replies should be sent" var="pubsub#replyto" /><field type="boolean" label="Send items to new subscribers" var="pubsub#send_item_subscribe"><value>1</value></field><field type="boolean" label="Persist items to storage" var="pubsub#persist_items"><value>0</value></field><field type="text-single" label="Max number of items to persist" var="pubsub#max_items"><value>-1</value></field><field type="text-single" label="Max payload size in bytes" var="pubsub#max_payload_size"><value>5120</value></field></x></configure></pubsub></iq>
This post was edited on 2010-03-25, 21:08 by ThomWill.
Avatar
ThomWill #2
Member since Mar 2010 · 9 posts
Group memberships: Members
Show profile · Link to this post
FYI... I also tried this (thought I was being clever)

private void GetNodeConfigCallBack(object sender, IQ Iq, object Data)
{

            XmlSerializer xs = new XmlSerializer(typeof(PubSubIq));
            StringReader sr = new StringReader(Iq.ToString());
            agsXMPP.protocol.extensions.pubsub.PubSubIq oIq = (agsXMPP.protocol.extensions.pubsub.PubSubIq)xs.Deserialize(sr);

...
}

but , alas, I cannot create an XmlSerializer on that type because it returns the following...

"There was an error reflecting type 'agsXMPP.protocol.extensions.pubsub.PubSubIq"
with an inner exception of
"You must implement a default accessor on agsXMPP.Xml.Dom.NodeList because it inherits from ICollection."


I am beginning to believe that I am going to have to write my own code to render the data form since I can parse it all out of the XML, just cannot get to it through the classes provided.

Thanks,

ThomWill
Avatar
Alex #3
Member since Feb 2003 · 4328 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hi ThomWill,

I fixed the bug in the Configure constructor. The new code is in SVN. If you prefer a binary let me know which one you need and I will build it and upload for you.
You should be able to use agsXMPP.protocol.extensions.pubsub.owner.PubSubIq now.

There is no way to cast back to PubSubIq, this is by design.

To get the data object just use the following code:
  1. var xdata = iq.SelectSingleElement<Data>(true);

The optional parameter which is set to true in the code above means that the SelectSingleElement function traverses the whole DOM, otherwise it looks only at the children, but not the grand children and deeper.

I did not answer all your question because I think this is the solution you were looking for. Let me know if it helps or not, and if there are still open questions.

Alex
Avatar
ThomWill #4
Member since Mar 2010 · 9 posts
Group memberships: Members
Show profile · Link to this post
Thanks for the quick reply, Alex!
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Forum: agsXMPP RSS