- 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 "itpp/itbase.h"
    00027
    00028
    00029 using std::string;
    00030 using namespace std;
    00031 using namespace libconfig;
    00032
    00033 namespace bdm {
    00034
    00038 class UIException : public std::exception {
    00039
    00040 public:
    00042         const string message;
    00043
    00045         const string path;
    00046
    00048         UIException ( const string &message, const Setting &element )
    00049                         : message ( "UI error: " + message + "." ), path ( "Check path \"" + string ( element.getPath() ) + "\"." ) {
    00050         }
    00051
    00053         UIException ( const string &message, const string &path )
    00054                         : message ( "UI error: " + message + "." ), path ( "Check path \"" + path + "\"." ) {
    00055         }
    00056
    00058         virtual const char* what() const throw() {
    00059                 return ( message + " " + path ).c_str();
    00060         }
    00061         ~UIException() throw() {};
    00062 };
    00063
    00064
    00089 class UIFile : public Config {
    00090 public:
    00092         UIFile();
    00093
    00095         UIFile ( const string &file_name );
    00096
    00098         void save ( const string &file_name );
    00099
    00101         operator Setting&();
    00102 };
    00103
    00170 class SettingResolver : root {
    00171 private:
    00173         UIFile *file;
    00174
    00180         const Setting &initialize_reference ( UIFile* &file, const Setting &potential_link );
    00181
    00182 public:
    00184         const Setting &result;
    00185
    00187         SettingResolver ( const Setting &potential_link );
    00188
    00190         ~SettingResolver();
    00191 };
    00192
    00203 class UI {
    00204 private:
    00210         class MappedUI {
    00211         private:
    00213                 typedef map< const string, const UI* const > StringToUIMap;
    00214
    00216                 typedef map< const type_info * const, const string > TypeInfoToStringMap;
    00217
    00219                 static StringToUIMap& mapped_strings();
    00220
    00222                 static TypeInfoToStringMap& mapped_type_infos();
    00223
    00225                 static void unregistered_class_error ( const string &unregistered_class_name );
    00226
    00227         public:
    00229                 static void add_class ( const string &class_name, const type_info * const class_type_info, const UI* const ui );
    00230
    00232                 static const UI& retrieve_ui ( const string &class_name );
    00233
    00235                 static const string& retrieve_class_name ( const type_info* const class_type_info );
    00236         };
    00237
    00239         static void assert_type ( const Setting &element, Setting::Type type );
    00240
    00242         virtual root* new_instance() const = 0;
    00243
    00245         static const Setting& to_child_setting ( const Setting &element, const int index );
    00246
    00248         static const Setting& to_child_setting ( const Setting &element, const string &name );
    00249
    00251         static void from_setting ( mat& matrix, const Setting &element );
    00253         static void from_setting ( ivec &vector, const Setting &element );
    00255         static void from_setting ( string &str, const Setting &element );
    00257         static void from_setting ( vec &vector, const Setting &element );
    00259         static void from_setting ( int &integer, const Setting &element );
    00261         static void from_setting ( double &real, const Setting &element );
    00263         template<class T> static void from_setting ( T* &instance, const Setting &element ) {
    00264                 const SettingResolver link ( element );
    00265                 assert_type ( link.result, Setting::TypeGroup );
    00266
    00267                 // we get a value stored in the "class" attribute
    00268                 string class_name;
    00269                 if ( !link.result.lookupValue ( "class", class_name ) )
    00270                         throw UIException ( "the obligatory \"class\" identifier is missing", link.result );
    00271
    00272                 // then we find a user-info related to this type
    00273                 const UI& related_UI = MappedUI::retrieve_ui ( class_name );
    00274
    00275                 root* typeless_instance = related_UI.new_instance();
    00276
    00277                 instance = dynamic_cast<T*> ( typeless_instance );
    00278                 if ( !instance )
    00279                         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 );
    00280
    00281                 try {
    00282                         instance->from_setting ( link.result );
    00283                 } catch ( SettingException sttng_xcptn ) {
    00284                         string msg = "the method " + class_name + ".from_setting(Setting&) has thrown a SettingException. Try to correct this method. Check path \"" + sttng_xcptn.getPath() + "\".";
    00285                         throw exception ( msg.c_str() );
    00286                 } catch ( UIException uixcptn ) {
    00287                         string msg = "the method " + class_name + ".from_setting(Setting&) has thrown an UIException \"" + uixcptn.message + "\" Try to correct this method. Check path \"" + uixcptn.path + "\".";
    00288                         throw exception ( msg.c_str() );
    00289                 } catch ( exception xcptn ) {
    00290                         string msg = "the method " + class_name + ".from_setting(Setting&) has thrown a general exception \"" + xcptn.what() + "\" Try to correct this method. Check path \"" + element.getPath() + "\".";
    00291                         throw exception ( msg.c_str() );
    00292                 }
    00293         }
    00294
    00296         template<class T> static void from_setting ( Array<T> &array_to_load, const Setting &element ) {
    00297                 const SettingResolver link ( element );
    00298
    00299                 assert_type ( link.result, Setting::TypeList );
    00300
    00301                 int len = link.result.getLength();
    00302                 array_to_load.set_length ( len );
    00303                 if ( len == 0 ) return;
    00304
    00305                 for ( int i = 0; i < len; i++ )
    00306                         from_setting ( array_to_load ( i ), link.result[i] );
    00307         }
    00308
    00313         template<class T> static void from_setting ( T &array_to_load, const Setting &element ) {
    00314                 throw UIException( "from_setting is not implemented for this type", element );
    00315         }
    00316
    00317
    00318 protected:
    00320         UI ( const string& class_name, const type_info * const class_type_info ) {
    00321                 MappedUI::add_class ( class_name, class_type_info, this );
    00322         }
    00323
    00324 public:
    00325
    00327         enum SettingPresence { optional, compulsory } ;
    00328
    00332
    00336         template<class T> static T* build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00337                 if ( !element.exists ( name ) )
    00338                 {
    00339                         if( settingPresence == optional )
    00340                                 return NULL;
    00341                         else
    00342                                 throw UIException ( "the compulsory Setting named \"" + name + "\" is missing", element );
    00343                 }
    00344
    00345                 T* instance;
    00346                 from_setting<T> ( instance, to_child_setting ( element, name ) );
    00347                 return instance;
    00348         }
    00349
    00353         template<class T> static T* build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00354                 if ( element.getLength() <= index )
    00355                 {
    00356                         if( settingPresence == optional )
    00357                                 return NULL;
    00358                         else
    00359                         {
    00360                                 stringstream stream;
    00361                                 stream << index;
    00362                                 throw UIException ( "the compulsory Setting with the index " + stream.str()+ " is missing", element );
    00363                         }
    00364                 }
    00365
    00366                 T* instance;
    00367                 from_setting<T> ( instance, to_child_setting ( element, index ) );
    00368                 return instance;
    00369         }
    00370
    00372         template<class T> static T* build ( const Setting &element ) {
    00373                 T* instance;
    00374                 from_setting<T> ( instance,  element );
    00375                 return instance;
    00376
    00377         }
    00378
    00380
    00384
    00387         template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00388                 if ( !element.exists ( name ) )
    00389                 {
    00390                         if( settingPresence == optional )
    00391                                 return false;
    00392                         else
    00393                                 throw UIException ( "the compulsory Setting named \"" + name + "\" is missing", element );
    00394                 }
    00395
    00396                 from_setting ( instance, to_child_setting ( element, name ) );
    00397                 return true;
    00398         }
    00399
    00402         template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00403                 if ( element.getLength() <= index )
    00404                 {
    00405                         if( settingPresence == optional )
    00406                                 return false;
    00407                         else
    00408                         {
    00409                                 stringstream stream;
    00410                                 stream << index;
    00411                                 throw UIException ( "the compulsory Setting with the index " + stream.str()+ " is missing", element );
    00412                         }
    00413                 }
    00414
    00415                 from_setting ( instance, to_child_setting ( element, index ) );
    00416                 return true;
    00417         }
    00418
    00420         template<class T> static bool get ( T &instance, const Setting &element ) {
    00421                 from_setting ( instance, element );
    00422                 return true;
    00423         }
    00425
    00429
    00432         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00433                 if ( !element.exists ( name ) )
    00434                         return false;
    00435
    00436                 from_setting ( array_to_load, to_child_setting ( element, name ) );
    00437                 return true;
    00438         }
    00439
    00442         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00443                 if ( element.getLength() <= index )
    00444                         return false;
    00445
    00446                 from_setting ( array_to_load, to_child_setting ( element, index ) );
    00447                 return true;
    00448         }
    00449
    00451         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element ) {
    00452                 from_setting ( array_to_load, element );
    00453                 return true;
    00454         }
    00456
    00461
    00463         template< class T> static void save ( const T * const instance, Setting &element, const string &name = "" ) {
    00464                 Setting &set = ( name == "" ) ? element.add ( Setting::TypeGroup )
    00465                                : element.add ( name, Setting::TypeGroup );
    00466
    00467                 const string &class_name = MappedUI::retrieve_class_name ( &typeid ( *instance ) );
    00468
    00469                 // add attribute "class"
    00470                 Setting &type = set.add ( "class", Setting::TypeString );
    00471                 type = class_name;
    00472
    00473                 try {
    00474                         instance->to_setting ( set );
    00475                 } catch ( SettingException sttng_xcptn ) {
    00476                         string msg = "the method " + class_name + ".to_setting(Setting&) has thrown a SettingException. Try to correct this method. Check path \"" + sttng_xcptn.getPath() + "\".";
    00477                         throw exception ( msg.c_str() );
    00478                 } catch ( UIException uixcptn ) {
    00479                         string msg = "the method " + class_name + ".to_setting(Setting&) has thrown an UIException \"" + uixcptn.message + "\" Try to correct this method. Check path \"" + uixcptn.path + "\".";
    00480                         throw exception ( msg.c_str() );
    00481                 } catch ( exception xcptn ) {
    00482                         string msg = "the method " + class_name + ".to_setting(Setting&) has thrown a general exception \"" + xcptn.what() + "\" Try to correct this method. Check path \"" + element.getPath() + "\".";
    00483                         throw exception ( msg.c_str() );
    00484                 }
    00485         }
    00486
    00488         template<class T> static void save ( const Array<T> &array_to_save, Setting &element, const string &name = "" ) {
    00489                 assert_type ( element, Setting::TypeGroup );
    00490                 Setting &list = ( name == "" ) ? element.add ( Setting::TypeList )
    00491                                 : element.add ( name, Setting::TypeList );
    00492                 for ( int i = 0; i < array_to_save.length(); i++ )
    00493                         save ( array_to_save ( i ), list );
    00494         }
    00495
    00497         static void save ( const mat &matrix, Setting &element, const string &name = "" );
    00498
    00500         static void save ( const ivec &vec, Setting &element, const string &name = "" );
    00501
    00503         static void save ( const vec &vector, Setting &element, const string &name = "" );
    00504
    00506         static void save ( const string &str, Setting &element, const string &name = "" );
    00507
    00509         static void save ( const int &integer, Setting &element, const string &name = "" );
    00510
    00512         static void save ( const double &real, Setting &element, const string &name = "" );
    00514
    00515 };
    00516
    00517
    00520 template<typename T> class ParticularUI : private UI {
    00521 private:
    00523         ParticularUI<T> ( const string &class_name ) : UI ( class_name, &typeid ( T ) ) {};
    00524
    00525 public:
    00527         static const ParticularUI<T>& factory;
    00528
    00530         root* new_instance() const {
    00531                 return new T();
    00532         }
    00533 };
    00534
    00535 }
    00536
    00546 #ifndef BDMLIB
    00547 #define UIREGISTER(class_name) template<> const ParticularUI<class_name>& ParticularUI<class_name>::factory = ParticularUI<class_name>(#class_name)
    00548 #else
    00549 #define UIREGISTER(class_name)
    00550 #endif
    00551
    00552 #endif // #ifndef USER_INFO_H