gloox  1.0
pubsubevent.cpp
00001 /*
00002   Copyright (c) 2007-2009 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 #include "pubsubevent.h"
00014 #include "tag.h"
00015 #include "util.h"
00016 
00017 namespace gloox
00018 {
00019 
00020   namespace PubSub
00021   {
00022 
00023     static const char* eventTypeValues[] = {
00024       "collection",
00025       "configuration",
00026       "delete",
00027       "items",
00028       "items",
00029       "purge",
00030       "subscription"
00031     };
00032 
00033     Event::ItemOperation::ItemOperation( const ItemOperation& right )
00034       : retract( right.retract ), item( right.item ),
00035         payload( right.payload ? right.payload->clone() : 0 )
00036     {
00037     }
00038 
00039     Event::Event( const Tag* event )
00040       : StanzaExtension( ExtPubSubEvent ), m_type( PubSub::EventUnknown ),
00041         m_subscriptionIDs( 0 ), m_config( 0 ), m_itemOperations( 0 ), m_subscription( false )
00042     {
00043       if( !event || event->name() != "event" )
00044         return;
00045 
00046       const TagList& events = event->children();
00047       TagList::const_iterator it = events.begin();
00048       const Tag* tag = 0;
00049       for( ; it != events.end(); ++it )
00050       {
00051         tag = (*it);
00052         PubSub::EventType type = (PubSub::EventType)util::lookup( tag->name(), eventTypeValues );
00053 
00054         switch( type )
00055         {
00056           case PubSub::EventCollection:
00057             tag = tag->findChild( "node" );
00058             if( tag )
00059             {
00060               m_node = tag->findAttribute( "id" );
00061               if( ( m_config = tag->findChild( "x" ) ) )
00062                 m_config = m_config->clone();
00063             }
00064             break;
00065 
00066           case PubSub::EventConfigure:
00067           case PubSub::EventDelete:
00068           case PubSub::EventPurge:
00069             m_node = tag->findAttribute( "node" );
00070             if( type == PubSub::EventConfigure
00071                 && ( m_config = tag->findChild( "x" ) ) )
00072               m_config = m_config->clone();
00073             break;
00074 
00075           case PubSub::EventItems:
00076           case PubSub::EventItemsRetract:
00077           {
00078             if( !m_itemOperations )
00079               m_itemOperations = new ItemOperationList();
00080 
00081             m_node = tag->findAttribute( "node" );
00082             const TagList& items = tag->children();
00083             TagList::const_iterator itt = items.begin();
00084             for( ; itt != items.end(); ++itt )
00085             {
00086               tag = (*itt);
00087               bool retract = false;
00088               if( tag->name() == "retract" )
00089               {
00090                 retract = true;
00091                 type = PubSub::EventItemsRetract;
00092               }
00093               ItemOperation* op = new ItemOperation( retract,
00094                                                      tag->findAttribute( "id" ),
00095                                                      tag->clone() );
00096               m_itemOperations->push_back( op );
00097             }
00098             break;
00099           }
00100 
00101           case EventSubscription:
00102           {
00103             m_node = tag->findAttribute( "node" );
00104             m_jid.setJID( tag->findAttribute( "jid" ) );
00105             m_subscription = tag->hasAttribute( "subscription", "subscribed" );
00106             break;
00107           }
00108 
00109           case PubSub::EventUnknown:
00110             if( type == PubSub::EventUnknown )
00111             {
00112               if( tag->name() != "headers" || m_subscriptionIDs != 0 )
00113               {
00114                 m_valid = false;
00115                 return;
00116               }
00117 
00118               m_subscriptionIDs = new StringList();
00119 
00120               const TagList& headers = tag->children();
00121               TagList::const_iterator ith = headers.begin();
00122               for( ; ith != headers.end(); ++ith )
00123               {
00124                 const std::string& name = (*ith)->findAttribute( "name" );
00125                 if( name == "pubsub#subid" )
00126                   m_subscriptionIDs->push_back( (*ith)->cdata() );
00127                 else if( name == "pubsub#collection" )
00128                   m_collection = (*ith)->cdata();
00129               }
00130             }
00131 
00132           default:
00133             continue;
00134         }
00135         m_type = type;
00136       }
00137 
00138       m_valid = true;
00139     }
00140 
00141     Event::Event( const std::string& node, PubSub::EventType type )
00142      : StanzaExtension( ExtPubSubEvent ), m_type( type ),
00143         m_node( node ), m_subscriptionIDs( 0 ), m_config( 0 ),
00144         m_itemOperations( 0 )
00145     {
00146       if( type != PubSub::EventUnknown )
00147         m_valid = true;
00148     }
00149 
00150     Event::~Event()
00151     {
00152       delete m_subscriptionIDs;
00153       delete m_config;
00154       if( m_itemOperations )
00155       {
00156         ItemOperationList::iterator it = m_itemOperations->begin();
00157         for( ; it != m_itemOperations->end(); ++it )
00158         {
00159           delete (*it)->payload;
00160           delete (*it);
00161         }
00162         delete m_itemOperations;
00163       }
00164     }
00165 
00166     void Event::addItem( ItemOperation* op )
00167     {
00168       if( !m_itemOperations )
00169         m_itemOperations = new ItemOperationList();
00170 
00171       m_itemOperations->push_back( op );
00172     }
00173 
00174     const std::string& Event::filterString() const
00175     {
00176       static const std::string filter = "/message/event[@xmlns='" + XMLNS_PUBSUB_EVENT + "']";
00177       return filter;
00178     }
00179 
00180     Tag* Event::tag() const
00181     {
00182       if( !m_valid )
00183         return 0;
00184 
00185       Tag* event = new Tag( "event", XMLNS, XMLNS_PUBSUB_EVENT );
00186       Tag* child = new Tag( event, util::lookup( m_type, eventTypeValues ) );
00187 
00188       Tag* item = 0;
00189 
00190       switch( m_type )
00191       {
00192         case PubSub::EventCollection:
00193         {
00194           item = new Tag( child, "node", "id", m_node );
00195           item->addChildCopy( m_config );
00196           break;
00197         }
00198 
00199         case PubSub::EventPurge:
00200         case PubSub::EventDelete:
00201         case PubSub::EventConfigure:
00202           child->addAttribute( "node", m_node );
00203           if( m_type == PubSub::EventConfigure )
00204             child->addChildCopy( m_config );
00205           break;
00206 
00207         case PubSub::EventItems:
00208         case PubSub::EventItemsRetract:
00209         {
00210           child->addAttribute( "node", m_node );
00211           if( m_itemOperations )
00212           {
00213 //            Tag* item;
00214             ItemOperation* op;
00215             ItemOperationList::const_iterator itt = m_itemOperations->begin();
00216             for( ; itt != m_itemOperations->end(); ++itt )
00217             {
00218               op = (*itt);
00219 //               item = new Tag( child, op->retract ? "retract" : "item", "id", op->item );
00220               if( op->payload )
00221                 child->addChildCopy( op->payload );
00222             }
00223           }
00224           break;
00225         }
00226 
00227         case EventSubscription:
00228         {
00229           child->addAttribute( "node", m_node );
00230           child->addAttribute( "jid", m_jid.full() );
00231           child->addAttribute( "subscription", m_subscription ? "subscribed" : "none" );
00232           break;
00233         }
00234 
00235         default:
00236           delete event;
00237           return 0;
00238       }
00239 
00240       if( m_subscriptionIDs || !m_collection.empty() )
00241       {
00242         Tag* headers = new Tag( event, "headers", XMLNS, "http://jabber.org/protocol/shim" );
00243         StringList::const_iterator it = m_subscriptionIDs->begin();
00244         for( ; it != m_subscriptionIDs->end(); ++it )
00245         {
00246           (new Tag( headers, "header", "name", "pubsub#subid" ))->setCData( (*it) );
00247         }
00248 
00249         if( !m_collection.empty() )
00250           (new Tag( headers, "header", "name", "pubsub#collection" ) )
00251             ->setCData( m_collection );
00252       }
00253 
00254       return event;
00255     }
00256 
00257     StanzaExtension* Event::clone() const
00258     {
00259       Event* e = new Event( m_node, m_type );
00260       e->m_subscriptionIDs = m_subscriptionIDs ? new StringList( *m_subscriptionIDs ) : 0;
00261       e->m_config = m_config ? m_config->clone() : 0;
00262       if( m_itemOperations )
00263       {
00264         e->m_itemOperations = new ItemOperationList();
00265         ItemOperationList::const_iterator it = m_itemOperations->begin();
00266         for( ; it != m_itemOperations->end(); ++it )
00267           e->m_itemOperations->push_back( new ItemOperation( *(*it) ) );
00268       }
00269       else
00270         e->m_itemOperations = 0;
00271 
00272       e->m_collection = m_collection;
00273       return e;
00274     }
00275 
00276   }
00277 
00278 }