- 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         ~UIException() throw() {};
    00076 };
    00077
    00078
    00101 class UIFile : public Config
    00102 {
    00103 public:
    00105         UIFile();
    00106
    00108         UIFile( const string &file_name );
    00109
    00111         void save(const string &file_name);
    00112
    00114         operator Setting&();
    00115 };
    00116
    00181 class SettingResolver : root
    00182 {
    00183 private:
    00185         UIFile *file;
    00186
    00192         const Setting &initialize_reference( UIFile* &file, const Setting &potential_link);
    00193
    00194 public:
    00196         const Setting &result;
    00197
    00199         SettingResolver( const Setting &potential_link );
    00200
    00202         ~SettingResolver();
    00203 };
    00204
    00212 class UI
    00213 {
    00214 private:
    00220         class MappedUI
    00221         {
    00222         private:
    00224                 typedef map< const string, const UI* const > StringToUIMap;
    00225
    00227                 typedef map< const type_info * const, const string > TypeInfoToStringMap;
    00228
    00230                 static StringToUIMap& mapped_strings();
    00231
    00233                 static TypeInfoToStringMap& mapped_type_infos();
    00234
    00236                 static void unregistered_class_error( const string &unregistered_class_name );
    00237
    00238         public:
    00240                 static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
    00241
    00243                 static const UI& retrieve_ui( const string &class_name );
    00244
    00246                 static const string& retrieve_class_name( const type_info* const class_type_info );
    00247         };
    00248
    00250         static void assert_type( const Setting &element, Setting::Type type);
    00251
    00253         virtual root* new_instance() const = 0;
    00254
    00256         static const Setting& to_child_setting( const Setting &element, const int index );
    00257
    00259         static const Setting& to_child_setting( const Setting &element, const string &name );
    00260
    00262         static void from_setting( mat& matrix, const Setting &element );
    00264         static void from_setting( ivec &vector, const Setting &element );
    00266         static void from_setting( string &str, const Setting &element );
    00268         static void from_setting( vec &vector, const Setting &element );
    00270         static void from_setting( int &integer, const Setting &element );
    00272         static void from_setting( double &real, const Setting &element );
    00274         template<class T> static void from_setting( T* &instance, const Setting &element )
    00275         {
    00276                 const SettingResolver link( element );
    00277                 assert_type(link.result,Setting::TypeGroup);
    00278
    00279                 // we get a value stored in the "class" attribute
    00280                 string class_name;
    00281                 if( !link.result.lookupValue( "class", class_name ) )
    00282                         throw UIException( "the obligatory \"class\" identifier is missing", link.result );
    00283
    00284                 // then we find a user-info related to this type
    00285                 const UI& related_UI = MappedUI::retrieve_ui( class_name );
    00286
    00287                 root* typeless_instance = related_UI.new_instance();
    00288
    00289                 instance = dynamic_cast<T*>(typeless_instance);
    00290                 if (!instance)
    00291                         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 );
    00292
    00293                 try
    00294                 {
    00295                         instance->from_setting( link.result );
    00296                 }
    00297                 catch(SettingException xcptn)
    00298                 {
    00299                         throw UIException( "the method " + class_name + ".from_setting(Setting&) has thrown an SettingException. Try to correct this method", xcptn.getPath());
    00300                 }
    00301         }
    00302
    00304         template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
    00305         {
    00306                 const SettingResolver link( element );
    00307
    00308                 assert_type(link.result,Setting::TypeList);
    00309
    00310                 int len = link.result.getLength();
    00311                 array_to_load.set_length( len );
    00312                 if( len == 0 ) return;
    00313
    00314                 for( int i=0; i < len; i++ )
    00315                         from_setting( array_to_load(i), link.result[i] );
    00316         }
    00317
    00318 protected:
    00320         UI( const string& class_name, const type_info * const class_type_info )
    00321         {
    00322                 MappedUI::add_class( class_name, class_type_info, this );
    00323         }
    00324
    00325 public:
    00326
    00330
    00332         template<class T> static T* build( const Setting &element, const string &name )
    00333         {
    00334                 T* instance;
    00335                 from_setting<T>( instance, to_child_setting( element, name ) );
    00336                 return instance;
    00337         }
    00339         template<class T> static T* build( const Setting &element, const int index )
    00340         {
    00341                 T* instance;
    00342                 from_setting<T>( instance, to_child_setting( element, index ) );
    00343                 return instance;
    00344         }
    00346         template<class T> static T* build( const Setting &element )
    00347         {
    00348                 T* instance;
    00349                 from_setting<T>( instance,  element );
    00350                 return instance;
    00351         }
    00353
    00357
    00359         template<class T> static void get( T &instance, const Setting &element, const string &name )
    00360         {
    00361                 from_setting( instance, to_child_setting( element, name ) );
    00362         }
    00363
    00365         template<class T> static void get( T &instance, const Setting &element, const int index )
    00366         {
    00367                 from_setting( instance, to_child_setting( element, index ) );
    00368         }
    00369
    00371         template<class T> static void get( T &instance, const Setting &element  )
    00372         {
    00373                 from_setting( instance, element );
    00374         }
    00376
    00380
    00382         template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
    00383         {
    00384                 from_setting( array_to_load, to_child_setting( element, name ) );
    00385         }
    00386
    00388         template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
    00389         {
    00390                 from_setting( array_to_load, to_child_setting( element, index ) );
    00391         }
    00392
    00394         template<class T> static void get( Array<T> &array_to_load, const Setting &element  )
    00395         {
    00396                 from_setting( array_to_load, element );
    00397         }
    00399
    00404
    00406         template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
    00407         {
    00408                 Setting &set = (name == "") ? element.add( Setting::TypeGroup )
    00409                                                                          : element.add( name, Setting::TypeGroup );
    00410
    00411                 const string &class_name = MappedUI::retrieve_class_name( &typeid(*instance) );
    00412
    00413                 // add attribute "class"
    00414                 Setting &type = set.add( "class", Setting::TypeString );
    00415                 type = class_name;
    00416
    00417                 try
    00418                 {
    00419                         instance->to_setting( set );
    00420                 }
    00421                 catch(SettingException xcptn)
    00422                 {
    00423                         throw UIException( "the method " + class_name + ".to_setting(Setting&) has thrown an SettingException. Try to correct this method", xcptn.getPath());
    00424                 }
    00425         }
    00426
    00428         template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
    00429         {
    00430                 assert_type(element,Setting::TypeGroup);
    00431                 Setting &list = (name == "") ? element.add( Setting::TypeList )
    00432                                                                          : element.add( name, Setting::TypeList );
    00433                 for( int i=0; i<array_to_save.length(); i++ )
    00434                         save( array_to_save(i), list );
    00435         }
    00436
    00438         static void save( const mat &matrix, Setting &element, const string &name = "" );
    00439
    00441         static void save( const ivec &vec, Setting &element, const string &name = "" );
    00442
    00444         static void save( const vec &vector, Setting &element, const string &name = "" );
    00445
    00447         static void save( const string &str, Setting &element, const string &name = "" );
    00448
    00450         static void save( const int &integer, Setting &element, const string &name = "" );
    00451
    00453         static void save( const double &real, Setting &element, const string &name = "" );
    00455
    00456 };
    00457
    00458
    00460 template<typename T> class ParticularUI : private UI
    00461 {
    00462 private:
    00464         ParticularUI<T>( const string &class_name) : UI( class_name, &typeid(T) )
    00465         {};
    00466
    00467 public:
    00469         static const ParticularUI<T>& factory;
    00470
    00472         root* new_instance() const
    00473         {
    00474                 return new T();
    00475         }
    00476 };
    00477
    00478 }
    00479
    00480 #endif // #ifndef USER_INFO_H