Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Examples

PkgModuleCallbacks.YCP.h

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                                                                      |
00003 |                      __   __    ____ _____ ____                      |
00004 |                      \ \ / /_ _/ ___|_   _|___ \                     |
00005 |                       \ V / _` \___ \ | |   __) |                    |
00006 |                        | | (_| |___) || |  / __/                     |
00007 |                        |_|\__,_|____/ |_| |_____|                    |
00008 |                                                                      |
00009 |                               core system                            |
00010 |                                                        (C) SuSE GmbH |
00011 \----------------------------------------------------------------------/
00012 
00013   File:       PkgModuleCallbacks.YCP.h
00014 
00015   Author:     Michael Andres <ma@suse.de>
00016   Maintainer: Michael Andres <ma@suse.de>
00017 
00018   Purpose: Implementation of PkgModuleFunctions::CallbackHandler::YCPCallbacks
00019            (not intended to be distributed)
00020 
00021 /-*/
00022 #ifndef PkgModuleCallbacksYCP_h
00023 #define PkgModuleCallbacksYCP_h
00024 
00025 #include <stack>
00026 
00027 #include <y2util/Y2SLog.h>
00028 #include <y2util/stringutil.h>
00029 #include <y2util/Date.h>
00030 #include <y2util/FSize.h>
00031 #include <y2util/Url.h>
00032 #include <y2util/Pathname.h>
00033 
00034 #include <y2/Y2ComponentBroker.h>
00035 #include <y2/Y2Component.h>
00036 #include <y2/Y2Namespace.h>
00037 #include <y2/Y2Function.h>
00038 
00039 #include <ycpTools.h>
00040 #include <PkgModuleCallbacks.h>
00041 
00042 #include <ycp/y2log.h>
00043 
00044 using namespace std;
00045 
00047 //
00048 //      CLASS NAME : PkgModuleFunctions::CallbackHandler::YCPCallbacks
00063 class PkgModuleFunctions::CallbackHandler::YCPCallbacks
00064 {
00065   public:
00066 
00071     enum CBid {
00072       CB_StartRebuildDb, CB_ProgressRebuildDb, CB_NotifyRebuildDb, CB_StopRebuildDb,
00073       CB_StartConvertDb, CB_ProgressConvertDb, CB_NotifyConvertDb, CB_StopConvertDb,
00074       CB_StartProvide, CB_ProgressProvide, CB_DoneProvide,
00075       CB_StartPackage, CB_ProgressPackage, CB_DonePackage,
00076       CB_StartDownload, CB_ProgressDownload, CB_DoneDownload,
00077       CB_MediaChange,
00078       CB_SourceChange,
00079       CB_YouProgress,
00080       CB_YouPatchProgress,
00081       CB_YouError,
00082       CB_YouMessage,
00083       CB_YouLog,
00084       CB_YouExecuteYcpScript,
00085       CB_YouScriptProgress
00086     };
00087 
00093     static string cbName( CBid id_r ) {
00094       switch ( id_r ) {
00095 #define ENUM_OUT(N) case CB_##N: return #N
00096         ENUM_OUT( StartRebuildDb );
00097         ENUM_OUT( ProgressRebuildDb );
00098         ENUM_OUT( NotifyRebuildDb );
00099         ENUM_OUT( StopRebuildDb );
00100         ENUM_OUT( StartConvertDb );
00101         ENUM_OUT( ProgressConvertDb );
00102         ENUM_OUT( NotifyConvertDb );
00103         ENUM_OUT( StopConvertDb );
00104         ENUM_OUT( StartProvide );
00105         ENUM_OUT( ProgressProvide );
00106         ENUM_OUT( DoneProvide );
00107         ENUM_OUT( StartPackage );
00108         ENUM_OUT( ProgressPackage );
00109         ENUM_OUT( DonePackage );
00110         ENUM_OUT( StartDownload );
00111         ENUM_OUT( ProgressDownload );
00112         ENUM_OUT( DoneDownload );
00113         ENUM_OUT( MediaChange );
00114         ENUM_OUT( SourceChange );
00115         ENUM_OUT( YouProgress );
00116         ENUM_OUT( YouPatchProgress );
00117         ENUM_OUT( YouError );
00118         ENUM_OUT( YouMessage );
00119         ENUM_OUT( YouLog );
00120         ENUM_OUT( YouExecuteYcpScript );
00121         ENUM_OUT( YouScriptProgress );
00122 #undef ENUM_OUT
00123         // no default! let compiler warn missing values
00124       }
00125       return stringutil::form( "CBid(%d)", id_r );
00126     }
00127 
00128   private:
00129 
00130     struct CBdata
00131     {
00132        CBdata (string module, string symbol, Y2Namespace* component)
00133            : module (module), symbol (symbol), component (component)
00134            { }
00135 
00136        const string module, symbol;
00137        Y2Namespace* component;
00138     };
00139 
00140     typedef map <CBid, stack <CBdata> > _cbdata_t;
00141     _cbdata_t _cbdata;
00142 
00143   public:
00144 
00148     YCPCallbacks( )
00149     {}
00150 
00151 
00152     void popCallback( CBid id_r ) {
00153        _cbdata_t::iterator tmp1 = _cbdata.find(id_r);
00154        if (tmp1 != _cbdata.end() && !tmp1->second.empty())
00155            tmp1->second.pop();
00156     }
00157 
00161     void setCallback( CBid id_r, const string & name_r ) {
00162       y2debug ("Registering callback %s", name_r.c_str ());
00163       string::size_type colonpos = name_r.find("::");
00164       if ( colonpos != string::npos ) {
00165 
00166         string module = name_r.substr ( 0, colonpos );
00167         string symbol = name_r.substr ( colonpos + 2 );
00168 
00169         Y2Component *c = Y2ComponentBroker::getNamespaceComponent (module.c_str());
00170         if (c == NULL)
00171         {
00172           ycp2error ("No component can provide namespace %s for a callback of %s (callback id %d)",
00173                  module.c_str (), symbol.c_str (), id_r);
00174           return;
00175         }
00176 
00177         Y2Namespace *ns = c->import (module.c_str ());
00178         if (ns == NULL)
00179         {
00180           y2error ("Component %p could not provide namespace %s for a callback of %s",
00181                  c, module.c_str (), symbol.c_str ());
00182           return;
00183         }
00184 
00185         // ensure it is an initialized namespace
00186         ns->initialize ();
00187 
00188         _cbdata[id_r].push (CBdata (module, symbol, ns));
00189       } else {
00190         ycp2error ("Callback must be a part of a namespace");
00191       }
00192     }
00196     bool setCallback( CBid id_r, const YCPString & args ) {
00197       string name = args->value();
00198       setCallback( id_r, name );
00199       return true;
00200     }
00205     YCPValue setYCPCallback( CBid id_r, const YCPString & args_r ) {
00206        if (!args_r->value().empty ())
00207        {
00208            if ( ! setCallback( id_r, args_r ) ) {
00209                 return YCPError( string("Bad args to Pkg::Callback") + cbName( id_r ) );
00210             }
00211        }
00212        else
00213        {
00214            popCallback( id_r );
00215        }
00216        return YCPVoid();
00217     }
00218 
00223     bool isSet( CBid id_r ) const {
00224        const _cbdata_t::const_iterator tmp1 = _cbdata.find(id_r);
00225        return tmp1 != _cbdata.end() && !tmp1->second.empty();
00226     }
00227 
00228   public:
00229 
00233     Y2Function* createCallback( CBid id_r ) const {
00234        const _cbdata_t::const_iterator tmp1 = _cbdata.find(id_r);
00235        if (tmp1 == _cbdata.end() || tmp1->second.empty())
00236            return NULL;
00237        const CBdata& tmp2 = tmp1->second.top();
00238 
00239       string module = tmp2.module;
00240       string name = tmp2.symbol;
00241       Y2Namespace *ns = tmp2.component;
00242       if (ns == NULL)
00243       {
00244           y2error ("No namespace %s for a callback of %s", module.c_str (), name.c_str ());
00245           return NULL;
00246       }
00247 
00248       Y2Function* func = ns->createFunctionCall (name);
00249       if (func == NULL)
00250       {
00251           ycp2error ("Cannot find function %s in module %s as a callback", name.c_str (), module.c_str());
00252           return NULL;
00253       }
00254 
00255       return func;
00256     }
00257 
00258   public:
00259 
00260 #warning Free interface for YCPCallback sending is ok, but a functional one is desired too.
00261 
00272     class Send {
00273       public:
00277         struct CB {
00278           const Send & _send;
00279           CBid _id;
00280           bool     _set;
00281           Y2Function* _func;
00282           YCPValue _result;
00283           CB( const Send & send_r, CBid func )
00284             : _send( send_r )
00285             , _id( func )
00286             , _set( _send.ycpcb().isSet( func ) )
00287             , _func( _send.ycpcb().createCallback( func ) )
00288             , _result( YCPVoid() )
00289           {}
00290 
00291           ~CB ()
00292           {
00293             if (_func) delete _func;
00294           }
00295 
00296           CB & addStr( const string & arg ) { if (_func != NULL) _func->appendParameter( YCPString( arg ) ); return *this; }
00297           CB & addStr( const Pathname & arg ) { return addStr( arg.asString() ); }
00298           CB & addStr( const Url & arg ) { return addStr( arg.asString() ); }
00299 
00300           CB & addInt( long long arg ) { if (_func != NULL) _func->appendParameter( YCPInteger( arg ) ); return *this; }
00301 
00302           CB & addBool( bool arg ) { if (_func != NULL) _func->appendParameter( YCPBoolean( arg ) ); return *this; }
00303 
00304           bool isStr() const { return _result->isString(); }
00305           bool isInt() const { return _result->isInteger(); }
00306           bool isBool() const { return _result->isBoolean(); }
00307 
00308           bool expecting( YCPValueType exp_r ) const {
00309             if ( _result->valuetype() == exp_r )
00310               return true;
00311             INT << "Wrong return type " << _result->valuetype() << ": Expected " << exp_r << endl;
00312             return false;
00313           }
00314 
00315           bool evaluate() {
00316             if ( _set && _func ) {
00317               y2debug ("Evaluating callback");
00318               _result = _func->evaluateCall ();
00319 
00320               delete _func;
00321               _func = _send.ycpcb().createCallback( _id );
00322               return true;
00323             }
00324             return false;
00325           }
00326 
00327           bool evaluate( YCPValueType exp_r ) {
00328             return evaluate() && expecting( exp_r );
00329           }
00330 
00331           string evaluateStr( const string & def_r = "" ) {
00332             return evaluate( YT_STRING ) ? _result->asString()->value() : def_r;
00333           }
00334 
00335           long long evaluateInt( const long long & def_r = 0 ) {
00336             return evaluate( YT_INTEGER ) ? _result->asInteger()->value() : def_r;
00337           }
00338 
00339           bool evaluateBool( const bool & def_r = false ) {
00340             return evaluate( YT_BOOLEAN ) ? _result->asBoolean()->value() : def_r;
00341           }
00342         };
00343       private:
00344         const YCPCallbacks & _ycpcb;
00345       public:
00346         Send( const YCPCallbacks & ycpcb_r ) : _ycpcb( ycpcb_r ) {}
00347         virtual ~Send() {}
00348         const YCPCallbacks & ycpcb() const { return _ycpcb; }
00349         CB ycpcb( CBid func ) const { return CB( *this, func ); }
00350     };
00351 };
00352 
00354 
00355 #endif // PkgModuleCallbacksYCP_h

Generated on Fri Nov 9 18:15:22 2007 for yast2-core by doxygen 1.3.6