- Main Page
- Related Pages
- Modules
- Classes
- Files

- File List
- File Members

# user_info.h

Go to the documentation of this file.

    00001
    00014 #ifndef USER_INFO_H
    00015 #define USER_INFO_H
    00016
    00017 #include <stdio.h>
    00018 #include <string>
    00019 #include <typeinfo>
    00020 #include <map>
    00021 #include <stdexcept>
    00022
    00023 #include "libconfig/libconfig.h++"
    00024 #include "../bdmroot.h"
    00025 #include "itpp/itbase.h"
    00026
    00027
    00028 using std::string;
    00029 using namespace std;
    00030 using namespace libconfig;
    00031
    00032 namespace bdm
    00033 {
    00034
    00044 #ifndef BDMLIB
    00045         #define UIREGISTER(class_name) template<> const ParticularUI<class_name>& ParticularUI<class_name>::factory = ParticularUI<class_name>(#class_name)
    00046 #else
    00047         #define UIREGISTER(class_name)
    00048 #endif
    00049
    00051 class UIException : public std::exception
    00052 {
    00053 private:
    00055         const string message;
    00056
    00057 public:
    00059         UIException( const string &message, const Setting &element  )
    00060                 : message( "UI error: " + message + ". Check path \"" + string(element.getPath()) + "\"." )
    00061         {
    00062         }
    00063
    00065         UIException( const string &message, const string &path  )
    00066                 : message( "UI error: " + message + "! Check path \"" + path + "\"." )
    00067         {
    00068         }
    00069
    00071         virtual const char* what() const throw()
    00072         {
    00073                 return message.c_str();
    00074         }
    00075 };
    00076
    00077
    00100 class UIFile : public Config
    00101 {
    00102 public:
    00104         UIFile();
    00105
    00107         UIFile( const string &file_name );
    00108
    00110         void save(const string &file_name);
    00111
    00113         operator Setting&();
    00114 };
    00115
    00180 class SettingResolver : root
    00181 {
    00182 private:
    00184         UIFile *file;
    00185
    00191         const Setting &initialize_reference( UIFile* &file, const Setting &potential_link);
    00192
    00193 public:
    00195         const Setting &result;
    00196
    00198         SettingResolver( const Setting &potential_link );
    00199
    00201         ~SettingResolver();
    00202 };
    00203
    00211 class UI
    00212 {
    00213 private:
    00219         class MappedUI
    00220         {
    00221         private:
    00223                 typedef map< const string, const UI* const > StringToUIMap;
    00224
    00226                 typedef map< const type_info * const, const string > TypeInfoToStringMap;
    00227
    00229                 static StringToUIMap& mapped_strings();
    00230
    00232                 static TypeInfoToStringMap& mapped_type_infos();
    00233
    00235                 static void unregistered_class_error( const string &unregistered_class_name );
    00236
    00237         public:
    00239                 static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
    00240
    00242                 static const UI& retrieve_ui( const string &class_name );
    00243
    00245                 static const string& retrieve_class_name( const type_info* const class_type_info );
    00246         };
    00247
    00249         static void assert_type( const Setting &element, Setting::Type type);
    00250
    00252         virtual root* new_instance() const = 0;
    00253
    00255         static const Setting& to_child_setting( const Setting &element, const int index );
    00256
    00258         static const Setting& to_child_setting( const Setting &element, const string &name );
    00259
    00261         static void from_setting( mat& matrix, const Setting &element );
    00263         static void from_setting( ivec &vector, const Setting &element );
    00265         static void from_setting( string &str, const Setting &element );
    00267         static void from_setting( vec &vector, const Setting &element );
    00269         static void from_setting( int &integer, const Setting &element );
    00271         static void from_setting( double &real, const Setting &element );
    00273         template<class T> static void from_setting( T* &instance, const Setting &element )
    00274         {
    00275                 const SettingResolver link( element );
    00276                 assert_type(link.result,Setting::TypeGroup);
    00277
    00278                 // we get a value stored in the "class" attribute
    00279                 string class_name;
    00280                 if( !link.result.lookupValue( "class", class_name ) )
    00281                         throw UIException( "the obligatory \"class\" identifier is missing", link.result );
    00282
    00283                 // then we find a user-info related to this type
    00284                 const UI& related_UI = MappedUI::retrieve_ui( class_name );
    00285
    00286                 root* typeless_instance = related_UI.new_instance();
    00287
    00288                 instance = dynamic_cast<T*>(typeless_instance);
    00289                 if (!instance)
    00290                         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 );
    00291
    00292                 try
    00293                 {
    00294                         instance->from_setting( link.result );
    00295                 }
    00296                 catch(SettingException xcptn)
    00297                 {
    00298                         throw UIException( "the method " + class_name + ".from_setting(Setting&) has thrown an SettingException. Try to correct this method", xcptn.getPath());
    00299                 }
    00300         }
    00301
    00303         template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
    00304         {
    00305                 const SettingResolver link( element );
    00306
    00307                 assert_type(link.result,Setting::TypeList);
    00308
    00309                 int len = link.result.getLength();
    00310                 array_to_load.set_length( len );
    00311                 if( len == 0 ) return;
    00312
    00313                 for( int i=0; i < len; i++ )
    00314                         from_setting( array_to_load(i), link.result[i] );
    00315         }
    00316
    00317 protected:
    00319         UI( const string& class_name, const type_info * const class_type_info )
    00320         {
    00321                 MappedUI::add_class( class_name, class_type_info, this );
    00322         }
    00323
    00324 public:
    00325
    00329
    00331         template<class T> static T* build( const Setting &element, const string &name )
    00332         {
    00333                 T* instance;
    00334                 from_setting<T>( instance, to_child_setting( element, name ) );
    00335                 return instance;
    00336         }
    00338         template<class T> static T* build( const Setting &element, const int index )
    00339         {
    00340                 T* instance;
    00341                 from_setting<T>( instance, to_child_setting( element, index ) );
    00342                 return instance;
    00343         }
    00345         template<class T> static T* build( const Setting &element )
    00346         {
    00347                 T* instance;
    00348                 from_setting<T>( instance,  element );
    00349                 return instance;
    00350         }
    00352
    00356
    00358         template<class T> static void get( T &instance, const Setting &element, const string &name )
    00359         {
    00360                 from_setting( instance, to_child_setting( element, name ) );
    00361         }
    00362
    00364         template<class T> static void get( T &instance, const Setting &element, const int index )
    00365         {
    00366                 from_setting( instance, to_child_setting( element, index ) );
    00367         }
    00368
    00370         template<class T> static void get( T &instance, const Setting &element  )
    00371         {
    00372                 from_setting( instance, element );
    00373         }
    00375
    00379
    00381         template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
    00382         {
    00383                 from_setting( array_to_load, to_child_setting( element, name ) );
    00384         }
    00385
    00387         template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
    00388         {
    00389                 from_setting( array_to_load, to_child_setting( element, index ) );
    00390         }
    00391
    00393         template<class T> static void get( Array<T> &array_to_load, const Setting &element  )
    00394         {
    00395                 from_setting( array_to_load, element );
    00396         }
    00398
    00403
    00405         template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
    00406         {
    00407                 Setting &set = (name == "") ? element.add( Setting::TypeGroup )
    00408                                                                          : element.add( name, Setting::TypeGroup );
    00409
    00410                 const string &class_name = MappedUI::retrieve_class_name( &typeid(*instance) );
    00411
    00412                 // add attribute "class"
    00413                 Setting &type = set.add( "class", Setting::TypeString );
    00414                 type = class_name;
    00415
    00416                 try
    00417                 {
    00418                         instance->to_setting( set );
    00419                 }
    00420                 catch(SettingException xcptn)
    00421                 {
    00422                         throw UIException( "the method " + class_name + ".to_setting(Setting&) has thrown an SettingException. Try to correct this method", xcptn.getPath());
    00423                 }
    00424         }
    00425
    00427         template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
    00428         {
    00429                 assert_type(element,Setting::TypeGroup);
    00430                 Setting &list = (name == "") ? element.add( Setting::TypeList )
    00431                                                                          : element.add( name, Setting::TypeList );
    00432                 for( int i=0; i<array_to_save.length(); i++ )
    00433                         save( array_to_save(i), list );
    00434         }
    00435
    00437         static void save( const mat &matrix, Setting &element, const string &name = "" );
    00438
    00440         static void save( const ivec &vec, Setting &element, const string &name = "" );
    00441
    00443         static void save( const vec &vector, Setting &element, const string &name = "" );
    00444
    00446         static void save( const string &str, Setting &element, const string &name = "" );
    00447
    00449         static void save( const int &integer, Setting &element, const string &name = "" );
    00450
    00452         static void save( const double &real, Setting &element, const string &name = "" );
    00454
    00455 };
    00456
    00457
    00459 template<typename T> class ParticularUI : private UI
    00460 {
    00461 private:
    00463         ParticularUI<T>( const string &class_name) : UI( class_name, &typeid(T) )
    00464         {};
    00465
    00466 public:
    00468         static const ParticularUI<T>& factory;
    00469
    00471         root* new_instance() const
    00472         {
    00473                 return new T();
    00474         }
    00475 };
    00476
    00477 }
    00478
    00479 #endif // #ifndef USER_INFO_H