- Main Page
- Related Pages
- Classes
- Files

- File List
- File Members

# user_info.h

Go to the documentation of this file.

    00001
    00015 #ifndef USER_INFO_H
    00016 #define USER_INFO_H
    00017
    00018 #include <stdio.h>
    00019 #include <string>
    00020 #include <typeinfo>
    00021 #include <map>
    00022 #include <stdexcept>
    00023
    00024 #include "libconfig/libconfig.h++"
    00025 #include "../bdmroot.h"
    00026 #include "../shared_ptr.h"
    00027 #include "itpp/itbase.h"
    00028
    00029
    00030 using std::string;
    00031 using namespace std;
    00032 using namespace libconfig;
    00033
    00034 namespace bdm {
    00035
    00039 class UIException : public std::exception {
    00040
    00041 public:
    00043         const string message;
    00044
    00046         const string path;
    00047
    00048 private:
    00049         string what_message;
    00050
    00051 public:
    00053         UIException ( const string &message, const Setting &element )
    00054                         : message ( "UI error: " + message + "." ), path ( "Check path \"" + string ( element.getPath() ) + "\"." ) {
    00055                 init_what_message();
    00056         }
    00057
    00059         UIException ( const string &message, const string &path )
    00060                         : message ( "UI error: " + message + "." ), path ( "Check path \"" + path + "\"." ) {
    00061                 init_what_message();
    00062         }
    00063
    00065         virtual const char* what() const throw() {
    00066                 return what_message.c_str();
    00067         }
    00068
    00069         ~UIException() throw() {};
    00070
    00071 private:
    00072         void init_what_message() {
    00073                 what_message = message;
    00074                 what_message += ' ';
    00075                 what_message += path;
    00076         }
    00077 };
    00078
    00079
    00104 class UIFile : public Config {
    00105 public:
    00107         UIFile();
    00108
    00110         UIFile ( const string &file_name );
    00111
    00113         void save ( const string &file_name );
    00114
    00116         operator Setting&();
    00117 };
    00118
    00185 class SettingResolver : root {
    00186 private:
    00188         UIFile *file;
    00189
    00195         const Setting &initialize_reference ( UIFile* &file, const Setting &potential_link );
    00196
    00197 public:
    00199         const Setting &result;
    00200
    00202         SettingResolver ( const Setting &potential_link );
    00203
    00205         ~SettingResolver();
    00206 };
    00207
    00218 class UI {
    00219 private:
    00225         class MappedUI {
    00226         private:
    00228                 typedef map< const string, const UI* const > StringToUIMap;
    00229
    00231                 typedef map< const type_info * const, const string > TypeInfoToStringMap;
    00232
    00234                 static StringToUIMap& mapped_strings();
    00235
    00237                 static TypeInfoToStringMap& mapped_type_infos();
    00238
    00240                 static void unregistered_class_error ( const string &unregistered_class_name );
    00241
    00242         public:
    00244                 static void add_class ( const string &class_name, const type_info * const class_type_info, const UI* const ui );
    00245
    00247                 static const UI& retrieve_ui ( const string &class_name );
    00248
    00250                 static const string& retrieve_class_name ( const type_info* const class_type_info );
    00251         };
    00252
    00254         static void assert_type ( const Setting &element, Setting::Type type );
    00255
    00264         virtual root* new_instance() const = 0;
    00265
    00267         static const Setting& to_child_setting ( const Setting &element, const int index );
    00268
    00270         static const Setting& to_child_setting ( const Setting &element, const string &name );
    00271
    00273         static void from_setting ( mat& matrix, const Setting &element );
    00275         static void from_setting ( ivec &vector, const Setting &element );
    00277         static void from_setting ( string &str, const Setting &element );
    00279         static void from_setting ( vec &vector, const Setting &element );
    00281         static void from_setting ( int &integer, const Setting &element );
    00283         static void from_setting ( double &real, const Setting &element );
    00284
    00286         template<class T> static void from_setting ( T* &instance, const Setting &element ) {
    00287                 const SettingResolver link ( element );
    00288                 assert_type ( link.result, Setting::TypeGroup );
    00289
    00290                 // we get a value stored in the "class" attribute
    00291                 string class_name;
    00292                 if ( !link.result.lookupValue ( "class", class_name ) )
    00293                         throw UIException ( "the obligatory \"class\" identifier is missing", link.result );
    00294
    00295                 // then we find a user-info related to this type
    00296                 const UI& related_UI = MappedUI::retrieve_ui ( class_name );
    00297
    00298                 root *typeless_instance = related_UI.new_instance();
    00299                 it_assert_debug ( typeless_instance, "UI::new_instance failed" );
    00300
    00301                 instance = dynamic_cast<T*> ( typeless_instance );
    00302                 if ( !instance ) {
    00303                         delete typeless_instance;
    00304                         throw UIException ( "class " + class_name + " is not a descendant of the desired output class. Try to call the UI::build<T> function with a different type parameter.", link.result );
    00305                 }
    00306
    00307                 try {
    00308                         instance->from_setting ( link.result );
    00309                 } catch ( SettingException sttng_xcptn ) {
    00310                         string msg = "the method " + class_name + ".from_setting(Setting&) has thrown a SettingException. Try to correct this method. Check path \"" + sttng_xcptn.getPath() + "\".";
    00311                         throw UIException(msg, link.result);
    00312                 }
    00313         }
    00314
    00317         template<class T>
    00318         static void from_setting ( shared_ptr<T> &instance, const Setting &element ) {
    00319                 T *tmp_inst = 0;
    00320                 from_setting ( tmp_inst, element );
    00321                 it_assert_debug ( tmp_inst, "UI::from_setting failed" );
    00322                 instance = tmp_inst;
    00323         }
    00324
    00326         template<class T> static void from_setting ( Array<T> &array_to_load, const Setting &element ) {
    00327                 const SettingResolver link ( element );
    00328
    00329                 assert_type ( link.result, Setting::TypeList );
    00330
    00331                 int len = link.result.getLength();
    00332                 array_to_load.set_length ( len );
    00333                 if ( len == 0 ) return;
    00334
    00335                 for ( int i = 0; i < len; i++ )
    00336                         from_setting ( array_to_load ( i ), link.result[i] );
    00337         }
    00338
    00343         template<class T> static void from_setting ( T &variable_to_load, const Setting &element ) {
    00344                 std::string msg = "from_setting is not implemented for type ";
    00345                 msg += typeid(T).name();
    00346                 throw UIException ( msg, element );
    00347         }
    00348
    00349
    00350 protected:
    00352         UI ( const string& class_name, const type_info * const class_type_info ) {
    00353                 MappedUI::add_class ( class_name, class_type_info, this );
    00354         }
    00355
    00356 public:
    00357
    00359         enum SettingPresence { optional, compulsory } ;
    00360
    00364
    00368         template<class T>
    00369         static shared_ptr<T> build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00370                 if ( !element.exists ( name ) ) {
    00371                         if ( settingPresence == optional )
    00372                                 return shared_ptr<T>();
    00373                         else
    00374                                 throw UIException ( "the compulsory Setting named \"" + name + "\" is missing", element );
    00375                 }
    00376
    00377                 shared_ptr<T> instance;
    00378                 from_setting<T> ( instance, to_child_setting ( element, name ) );
    00379                 return instance;
    00380         }
    00381
    00385         template<class T>
    00386         static shared_ptr<T> build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00387                 if ( element.getLength() <= index ) {
    00388                         if ( settingPresence == optional )
    00389                                 return shared_ptr<T>();
    00390                         else {
    00391                                 stringstream stream;
    00392                                 stream << index;
    00393                                 throw UIException ( "the compulsory Setting with the index " + stream.str() + " is missing", element );
    00394                         }
    00395                 }
    00396
    00397                 shared_ptr<T> instance;
    00398                 from_setting<T> ( instance, to_child_setting ( element, index ) );
    00399                 return instance;
    00400         }
    00401
    00403
    00407
    00410         template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00411                 if ( !element.exists ( name ) ) {
    00412                         if ( settingPresence == optional )
    00413                                 return false;
    00414                         else
    00415                                 throw UIException ( "the compulsory Setting named \"" + name + "\" is missing", element );
    00416                 }
    00417
    00418                 from_setting ( instance, to_child_setting ( element, name ) );
    00419                 return true;
    00420         }
    00421
    00424         template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00425                 if ( element.getLength() <= index ) {
    00426                         if ( settingPresence == optional )
    00427                                 return false;
    00428                         else {
    00429                                 stringstream stream;
    00430                                 stream << index;
    00431                                 throw UIException ( "the compulsory Setting with the index " + stream.str() + " is missing", element );
    00432                         }
    00433                 }
    00434
    00435                 from_setting ( instance, to_child_setting ( element, index ) );
    00436                 return true;
    00437         }
    00438
    00440         template<class T> static bool get ( T &instance, const Setting &element ) {
    00441                 from_setting ( instance, element );
    00442                 return true;
    00443         }
    00445
    00449
    00452         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00453                 if ( !element.exists ( name ) )
    00454                         return false;
    00455
    00456                 from_setting ( array_to_load, to_child_setting ( element, name ) );
    00457                 return true;
    00458         }
    00459
    00462         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00463                 if ( element.getLength() <= index )
    00464                         return false;
    00465
    00466                 from_setting ( array_to_load, to_child_setting ( element, index ) );
    00467                 return true;
    00468         }
    00469
    00471         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element ) {
    00472                 from_setting ( array_to_load, element );
    00473                 return true;
    00474         }
    00476
    00481
    00483         template< class T> static void save ( const T * const instance, Setting &element, const string &name = "" ) {
    00484                 Setting &set = ( name == "" ) ? element.add ( Setting::TypeGroup )
    00485                                : element.add ( name, Setting::TypeGroup );
    00486
    00487                 const string &class_name = MappedUI::retrieve_class_name ( &typeid ( *instance ) );
    00488
    00489                 // add attribute "class"
    00490                 Setting &type = set.add ( "class", Setting::TypeString );
    00491                 type = class_name;
    00492
    00493                 try {
    00494                         instance->to_setting ( set );
    00495                 } catch ( SettingException sttng_xcptn ) {
    00496                     string msg = "the method ";
    00497                     msg += class_name;
    00498                     msg += ".to_setting(Setting&) has thrown a SettingException. Try to correct this method.";
    00499                     throw UIException(msg, sttng_xcptn.getPath());
    00500                 }
    00501         }
    00502
    00503         template< class T> static void save ( const shared_ptr<T> &instance, Setting &element, const string &name = "" ) {
    00504                 save<T> ( instance.get(), element, name );
    00505         }
    00506
    00508         template<class T> static void save ( const Array<T> &array_to_save, Setting &element, const string &name = "" ) {
    00509                 assert_type ( element, Setting::TypeGroup );
    00510                 Setting &list = ( name == "" ) ? element.add ( Setting::TypeList )
    00511                                 : element.add ( name, Setting::TypeList );
    00512                 for ( int i = 0; i < array_to_save.length(); i++ )
    00513                         save ( array_to_save ( i ), list );
    00514         }
    00515
    00517         static void save ( const mat &matrix, Setting &element, const string &name = "" );
    00518
    00520         static void save ( const ivec &vec, Setting &element, const string &name = "" );
    00521
    00523         static void save ( const vec &vector, Setting &element, const string &name = "" );
    00524
    00526         static void save ( const string &str, Setting &element, const string &name = "" );
    00527
    00529         static void save ( const int &integer, Setting &element, const string &name = "" );
    00530
    00532         static void save ( const double &real, Setting &element, const string &name = "" );
    00534
    00535 };
    00536
    00537
    00540 template<typename T> class ParticularUI : private UI {
    00541 public:
    00543         ParticularUI<T> ( const string &class_name ) : UI ( class_name, &typeid ( T ) ) {};
    00544
    00546         root* new_instance() const {
    00547                 return new T();
    00548         }
    00549 };
    00550
    00551 }
    00552
    00562 #ifndef BDMLIB
    00563 #define UIREGISTER(class_name) static bdm::ParticularUI<class_name> UI##class_name(#class_name)
    00564 #else
    00565 #define UIREGISTER(class_name)
    00566 #endif
    00567
    00569 #define QUOTEME(x) #x
    00570
    00579 #ifndef BDMLIB
    00580 #define UIREGISTER2(class_name, temp_name) static bdm::ParticularUI<class_name<temp_name> > UI##class_name##_##temp_name( QUOTEME(class_name<temp_name>) )
    00581 #else
    00582 #define UIREGISTER2(class_name,temp_name)
    00583 #endif
    00584
    00585 #endif // #ifndef USER_INFO_H