gloox  1.0
search.cpp
00001 /*
00002   Copyright (c) 2006-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 
00014 
00015 #include "search.h"
00016 
00017 #include "clientbase.h"
00018 #include "dataform.h"
00019 #include "iq.h"
00020 
00021 namespace gloox
00022 {
00023 
00024   // Search::Query ----
00025   Search::Query::Query( DataForm* form )
00026     : StanzaExtension( ExtSearch ), m_form( form ), m_fields( 0 )
00027   {
00028   }
00029 
00030   Search::Query::Query( int fields, const SearchFieldStruct& values )
00031     : StanzaExtension( ExtSearch ), m_form( 0 ), m_fields( fields ), m_values( values )
00032   {
00033   }
00034 
00035   Search::Query::Query( const Tag* tag )
00036     : StanzaExtension( ExtSearch ), m_form( 0 ), m_fields( 0 )
00037   {
00038     if( !tag || tag->name() != "query" || tag->xmlns() != XMLNS_SEARCH )
00039       return;
00040 
00041     const TagList& l = tag->children();
00042     TagList::const_iterator it = l.begin();
00043     for( ; it != l.end(); ++it )
00044     {
00045       if( (*it)->name() == "instructions" )
00046       {
00047         m_instructions = (*it)->cdata();
00048       }
00049       else if( (*it)->name() == "item" )
00050       {
00051         m_srl.push_back( new SearchFieldStruct( (*it) ) );
00052       }
00053       else if( (*it)->name() == "first" )
00054         m_fields |= SearchFieldFirst;
00055       else if( (*it)->name() == "last" )
00056         m_fields |= SearchFieldLast;
00057       else if( (*it)->name() == "email" )
00058         m_fields |= SearchFieldEmail;
00059       else if( (*it)->name() == "nick" )
00060         m_fields |= SearchFieldNick;
00061       else if( !m_form && (*it)->name() == "x" && (*it)->xmlns() == XMLNS_X_DATA )
00062         m_form = new DataForm( (*it) );
00063     }
00064   }
00065 
00066   Search::Query::~Query()
00067   {
00068     delete m_form;
00069     SearchResultList::iterator it = m_srl.begin();
00070     for( ; it != m_srl.end(); ++it )
00071       delete (*it);
00072   }
00073 
00074   const std::string& Search::Query::filterString() const
00075   {
00076     static const std::string filter = "/iq/query[@xmlns='" + XMLNS_SEARCH + "']";
00077     return filter;
00078   }
00079 
00080   Tag* Search::Query::tag() const
00081   {
00082     Tag* t = new Tag( "query" );
00083     t->setXmlns( XMLNS_SEARCH );
00084     if( m_form )
00085       t->addChild( m_form->tag() );
00086     else if( m_fields )
00087     {
00088       if( !m_instructions.empty() )
00089         new Tag( t, "instructions", m_instructions );
00090       if( m_fields & SearchFieldFirst )
00091         new Tag( t, "first", m_values.first() );
00092       if( m_fields & SearchFieldLast )
00093         new Tag( t, "last", m_values.last() );
00094       if( m_fields & SearchFieldNick )
00095         new Tag( t, "nick", m_values.nick() );
00096       if( m_fields & SearchFieldEmail )
00097         new Tag( t, "email", m_values.email() );
00098     }
00099     else if( !m_srl.empty() )
00100     {
00101       SearchResultList::const_iterator it = m_srl.begin();
00102       for( ; it != m_srl.end(); ++it )
00103       {
00104         t->addChild( (*it)->tag() );
00105       }
00106     }
00107     return t;
00108   }
00109   // ---- ~Search::Query ----
00110 
00111   // ---- Search ----
00112   Search::Search( ClientBase* parent )
00113     : m_parent( parent )
00114   {
00115     if( m_parent )
00116       m_parent->registerStanzaExtension( new Query() );
00117   }
00118 
00119   Search::~Search()
00120   {
00121     if( m_parent )
00122     {
00123       m_parent->removeIDHandler( this );
00124       m_parent->removeStanzaExtension( ExtRoster );
00125     }
00126   }
00127 
00128   void Search::fetchSearchFields( const JID& directory, SearchHandler* sh )
00129   {
00130     if( !m_parent || !directory || !sh )
00131       return;
00132 
00133     const std::string& id = m_parent->getID();
00134     IQ iq( IQ::Get, directory, id );
00135     iq.addExtension( new Query() );
00136     m_track[id] = sh;
00137     m_parent->send( iq, this, FetchSearchFields );
00138   }
00139 
00140   void Search::search( const JID& directory, DataForm* form, SearchHandler* sh )
00141   {
00142     if( !m_parent || !directory || !sh )
00143       return;
00144 
00145     const std::string& id = m_parent->getID();
00146     IQ iq( IQ::Set, directory, id );
00147     iq.addExtension( new Query( form ) );
00148 
00149     m_track[id] = sh;
00150     m_parent->send( iq, this, DoSearch );
00151   }
00152 
00153   void Search::search( const JID& directory, int fields, const SearchFieldStruct& values, SearchHandler* sh )
00154   {
00155     if( !m_parent || !directory || !sh )
00156       return;
00157 
00158     const std::string& id = m_parent->getID();
00159 
00160     IQ iq( IQ::Set, directory );
00161     iq.addExtension( new Query( fields, values ) );
00162 
00163     m_track[id] = sh;
00164     m_parent->send( iq, this, DoSearch );
00165   }
00166 
00167   void Search::handleIqID( const IQ& iq, int context )
00168   {
00169     TrackMap::iterator it = m_track.find( iq.id() );
00170     if( it != m_track.end() )
00171     {
00172       switch( iq.subtype() )
00173       {
00174         case IQ::Result:
00175         {
00176           const Query* q = iq.findExtension<Query>( ExtSearch );
00177           if( !q )
00178             return;
00179 
00180           switch( context )
00181           {
00182             case FetchSearchFields:
00183             {
00184               if( q->form() )
00185               {
00186                 (*it).second->handleSearchFields( iq.from(), q->form() );
00187               }
00188               else
00189               {
00190                 (*it).second->handleSearchFields( iq.from(), q->fields(), q->instructions() );
00191               }
00192               break;
00193             }
00194             case DoSearch:
00195             {
00196               if( q->form() )
00197               {
00198                 (*it).second->handleSearchResult( iq.from(), q->form() );
00199               }
00200               else
00201               {
00202                 (*it).second->handleSearchResult( iq.from(), q->result() );
00203               }
00204               break;
00205             }
00206           }
00207           break;
00208         }
00209         case IQ::Error:
00210           (*it).second->handleSearchError( iq.from(), iq.error() );
00211           break;
00212 
00213         default:
00214           break;
00215       }
00216 
00217       m_track.erase( it );
00218     }
00219 
00220     return;
00221   }
00222 
00223 }