- 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 private:
    00042         const string message;
    00043
    00044 public:
    00049         UIException ( const string &message ) :
    00050                 message ( message ) {
    00051         }
    00052
    00054         virtual const char* what() const throw() {
    00055                 return message.c_str();
    00056         }
    00057
    00058         ~UIException() throw() {};
    00059
    00060 protected:
    00065         static string format_message( const string &reason, const string &path );
    00066 };
    00067
    00071 class UISettingException : public UIException {
    00072 public:
    00074         UISettingException ( const string &message, const Setting &element ):
    00075                 UIException ( format_message ( message, string ( element.getPath() ) ) ) {
    00076         }
    00077
    00079         UISettingException ( const string &message, const string &path ):
    00080                 UIException ( format_message ( message, path ) ) {
    00081         }
    00082
    00083         ~UISettingException() throw() {};
    00084 };
    00085
    00089 class UIClassException : public UIException {
    00090 public:
    00092         UIClassException ( const string &message, const Setting &element ):
    00093                 UIException ( format_message ( message, string ( element.getPath() ) ) ) {
    00094         }
    00095
    00097         UIClassException ( const string &message, const string &path ):
    00098                 UIException ( format_message ( message, path ) ) {
    00099         }
    00100
    00101         ~UIClassException() throw() {};
    00102 };
    00103
    00128 class UIFile : public Config {
    00129 public:
    00131         UIFile();
    00132
    00134         UIFile ( const string &file_name );
    00135
    00137         void save ( const string &file_name );
    00138
    00140         operator Setting&();
    00141 };
    00142
    00209 class SettingResolver : root {
    00210 private:
    00212         UIFile *file;
    00213
    00219         const Setting &initialize_reference ( UIFile* &file, const Setting &potential_link );
    00220
    00221 public:
    00223         const Setting &result;
    00224
    00226         SettingResolver ( const Setting &potential_link );
    00227
    00229         ~SettingResolver();
    00230 };
    00231
    00242 class UI {
    00243 private:
    00249         class MappedUI {
    00250         private:
    00252                 typedef map< const string, const UI* const > StringToUIMap;
    00253
    00255                 typedef map< const type_info * const, const string > TypeInfoToStringMap;
    00256
    00258                 static StringToUIMap& mapped_strings();
    00259
    00261                 static TypeInfoToStringMap& mapped_type_infos();
    00262
    00264                 static void unregistered_class_error ( const string &unregistered_class_name );
    00265
    00266         public:
    00268                 static void add_class ( const string &class_name, const type_info * const class_type_info, const UI* const ui );
    00269
    00271                 static const UI& retrieve_ui ( const string &class_name );
    00272
    00274                 static const string& retrieve_class_name ( const type_info* const class_type_info );
    00275         };
    00276
    00278         static void assert_type ( const Setting &element, Setting::Type type );
    00279
    00288         virtual root* new_instance() const = 0;
    00289
    00291         static const Setting& to_child_setting ( const Setting &element, const int index );
    00292
    00294         static const Setting& to_child_setting ( const Setting &element, const string &name );
    00295
    00297         static void from_setting ( mat& matrix, const Setting &element );
    00299         static void from_setting ( ivec &vector, const Setting &element );
    00301         static void from_setting ( string &str, const Setting &element );
    00303         static void from_setting ( vec &vector, const Setting &element );
    00305         static void from_setting ( int &integer, const Setting &element );
    00307         static void from_setting ( double &real, const Setting &element );
    00308
    00310         template<class T> static void from_setting ( T* &instance, const Setting &element ) {
    00311                 const SettingResolver link ( element );
    00312                 assert_type ( link.result, Setting::TypeGroup );
    00313
    00314                 // we get a value stored in the "class" attribute
    00315                 string class_name;
    00316                 if ( !link.result.lookupValue ( "class", class_name ) )
    00317                         throw UIClassException ( "UIException: the obligatory \"class\" identifier is missing.", link.result );
    00318
    00319                 // then we find a user-info related to this type
    00320                 const UI& related_UI = MappedUI::retrieve_ui ( class_name );
    00321
    00322                 root *typeless_instance = related_UI.new_instance();
    00323                 bdm_assert ( typeless_instance, "UI::new_instance failed" );
    00324
    00325                 instance = dynamic_cast<T*> ( typeless_instance );
    00326                 if ( !instance ) {
    00327                         delete typeless_instance;
    00328                         throw UIClassException ( "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 );
    00329                 }
    00330
    00331                 try {
    00332                         instance->from_setting ( link.result );
    00333                 } catch ( SettingException &sttng_xcptn ) {
    00334                         delete instance;
    00335                         instance = 0;
    00336                         string msg = "UIException: method ";
    00337                         msg += class_name;
    00338                         msg += ".from_setting(Setting&) has thrown a SettingException.";
    00339                         throw UISettingException(msg, sttng_xcptn.getPath());
    00340                 } catch (std::runtime_error &e) {
    00341                         delete instance;
    00342                         instance = 0;
    00343                         string msg = "UIException: method ";
    00344                         msg += class_name;
    00345                         msg += " says: ";
    00346                         msg += e.what();
    00347                         throw UISettingException(msg, link.result);
    00348                 } catch (...) {
    00349                         delete instance;
    00350                         instance = 0;
    00351                         throw;
    00352                 }
    00353 }
    00354
    00357         template<class T>
    00358         static void from_setting ( shared_ptr<T> &instance, const Setting &element ) {
    00359                 T *tmp_inst = 0;
    00360                 from_setting ( tmp_inst, element );
    00361                 bdm_assert ( tmp_inst, "UI::from_setting failed" );
    00362                 instance = tmp_inst;
    00363         }
    00364
    00366         template<class T> static void from_setting ( Array<T> &array_to_load, const Setting &element ) {
    00367                 const SettingResolver link ( element );
    00368
    00369                 assert_type ( link.result, Setting::TypeList );
    00370
    00371                 int len = link.result.getLength();
    00372                 array_to_load.set_length ( len );
    00373                 if ( len == 0 ) return;
    00374
    00375                 for ( int i = 0; i < len; i++ )
    00376                         from_setting ( array_to_load ( i ), link.result[i] );
    00377         }
    00378
    00383         template<class T> static void from_setting ( T &variable_to_load, const Setting &element ) {
    00384                 std::string msg = "UIException: from_setting is not implemented for type ";
    00385                 msg += typeid(T).name();
    00386                 msg += '.';
    00387                 throw UISettingException ( msg, element );
    00388         }
    00389
    00390
    00391 protected:
    00393         UI ( const string& class_name, const type_info * const class_type_info ) {
    00394                 MappedUI::add_class ( class_name, class_type_info, this );
    00395         }
    00396
    00397 public:
    00398
    00400         enum SettingPresence { optional, compulsory } ;
    00401
    00405
    00409         template<class T>
    00410         static shared_ptr<T> build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00411                 if ( !element.exists ( name ) ) {
    00412                         if ( settingPresence == optional )
    00413                                 return shared_ptr<T>();
    00414                         else
    00415                                 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element );
    00416                 }
    00417
    00418                 shared_ptr<T> instance;
    00419                 from_setting<T> ( instance, to_child_setting ( element, name ) );
    00420                 return instance;
    00421         }
    00422
    00426         template<class T>
    00427         static shared_ptr<T> build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00428                 if ( element.getLength() <= index ) {
    00429                         if ( settingPresence == optional )
    00430                                 return shared_ptr<T>();
    00431                         else {
    00432                                 stringstream stream;
    00433                                 stream << index;
    00434                                 throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element );
    00435                         }
    00436                 }
    00437
    00438                 shared_ptr<T> instance;
    00439                 from_setting<T> ( instance, to_child_setting ( element, index ) );
    00440                 return instance;
    00441         }
    00442
    00444
    00448
    00451         template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00452                 if ( !element.exists ( name ) ) {
    00453                         if ( settingPresence == optional )
    00454                                 return false;
    00455                         else
    00456                                 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element );
    00457                 }
    00458
    00459                 from_setting ( instance, to_child_setting ( element, name ) );
    00460                 return true;
    00461         }
    00462
    00465         template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00466                 if ( element.getLength() <= index ) {
    00467                         if ( settingPresence == optional )
    00468                                 return false;
    00469                         else {
    00470                                 stringstream stream;
    00471                                 stream << "UIException: the compulsory Setting with the index " << index << " is missing.";
    00472                                 stream << index;
    00473                                 throw UISettingException (stream.str(), element );
    00474                         }
    00475                 }
    00476
    00477                 from_setting ( instance, to_child_setting ( element, index ) );
    00478                 return true;
    00479         }
    00480
    00482         template<class T> static bool get ( T &instance, const Setting &element ) {
    00483                 from_setting ( instance, element );
    00484                 return true;
    00485         }
    00487
    00491
    00494         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00495                 if ( !element.exists ( name ) )
    00496                         return false;
    00497
    00498                 from_setting ( array_to_load, to_child_setting ( element, name ) );
    00499                 return true;
    00500         }
    00501
    00504         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00505                 if ( element.getLength() <= index )
    00506                         return false;
    00507
    00508                 from_setting ( array_to_load, to_child_setting ( element, index ) );
    00509                 return true;
    00510         }
    00511
    00513         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element ) {
    00514                 from_setting ( array_to_load, element );
    00515                 return true;
    00516         }
    00518
    00523
    00525         template< class T> static void save ( const T * const instance, Setting &element, const string &name = "" ) {
    00526                 Setting &set = ( name == "" ) ? element.add ( Setting::TypeGroup )
    00527                                : element.add ( name, Setting::TypeGroup );
    00528
    00529                 const string &class_name = MappedUI::retrieve_class_name ( &typeid ( *instance ) );
    00530
    00531                 // add attribute "class"
    00532                 Setting &type = set.add ( "class", Setting::TypeString );
    00533                 type = class_name;
    00534
    00535                 try {
    00536                         instance->to_setting ( set );
    00537                 } catch ( SettingException &sttng_xcptn ) {
    00538                         string msg = "UIException: method ";
    00539                         msg += class_name;
    00540                         msg += ".to_setting(Setting&) has thrown a SettingException.";
    00541                         throw UISettingException(msg, sttng_xcptn.getPath());
    00542                 }
    00543         }
    00544
    00545         template< class T> static void save ( const shared_ptr<T> &instance, Setting &element, const string &name = "" ) {
    00546                 save<T> ( instance.get(), element, name );
    00547         }
    00548
    00550         template<class T> static void save ( const Array<T> &array_to_save, Setting &element, const string &name = "" ) {
    00551                 assert_type ( element, Setting::TypeGroup );
    00552                 Setting &list = ( name == "" ) ? element.add ( Setting::TypeList )
    00553                                 : element.add ( name, Setting::TypeList );
    00554                 for ( int i = 0; i < array_to_save.length(); i++ )
    00555                         save ( array_to_save ( i ), list );
    00556         }
    00557
    00559         static void save ( const mat &matrix, Setting &element, const string &name = "" );
    00560
    00562         static void save ( const ivec &vec, Setting &element, const string &name = "" );
    00563
    00565         static void save ( const vec &vector, Setting &element, const string &name = "" );
    00566
    00568         static void save ( const string &str, Setting &element, const string &name = "" );
    00569
    00571         static void save ( const int &integer, Setting &element, const string &name = "" );
    00572
    00574         static void save ( const double &real, Setting &element, const string &name = "" );
    00576
    00577 };
    00578
    00579
    00582 template<typename T> class ParticularUI : private UI {
    00583 public:
    00585         ParticularUI<T> ( const string &class_name ) : UI ( class_name, &typeid ( T ) ) {};
    00586
    00588         root* new_instance() const {
    00589                 return new T();
    00590         }
    00591 };
    00592
    00593 }
    00594
    00604 #ifndef BDMLIB
    00605 #define UIREGISTER(class_name) static bdm::ParticularUI<class_name> UI##class_name(#class_name)
    00606 #else
    00607 #define UIREGISTER(class_name)
    00608 #endif
    00609
    00611 #define QUOTEME(x) #x
    00612
    00621 #ifndef BDMLIB
    00622 #define UIREGISTER2(class_name, temp_name) static bdm::ParticularUI<class_name<temp_name> > UI##class_name##_##temp_name( QUOTEME(class_name<temp_name>) )
    00623 #else
    00624 #define UIREGISTER2(class_name,temp_name)
    00625 #endif
    00626
    00627 #endif // #ifndef USER_INFO_H