- 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_debug ( 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 (...) {
    00341                         delete instance;
    00342                         instance = 0;
    00343                         throw;
    00344                 }
    00345         }
    00346
    00349         template<class T>
    00350         static void from_setting ( shared_ptr<T> &instance, const Setting &element ) {
    00351                 T *tmp_inst = 0;
    00352                 from_setting ( tmp_inst, element );
    00353                 bdm_assert_debug ( tmp_inst, "UI::from_setting failed" );
    00354                 instance = tmp_inst;
    00355         }
    00356
    00358         template<class T> static void from_setting ( Array<T> &array_to_load, const Setting &element ) {
    00359                 const SettingResolver link ( element );
    00360
    00361                 assert_type ( link.result, Setting::TypeList );
    00362
    00363                 int len = link.result.getLength();
    00364                 array_to_load.set_length ( len );
    00365                 if ( len == 0 ) return;
    00366
    00367                 for ( int i = 0; i < len; i++ )
    00368                         from_setting ( array_to_load ( i ), link.result[i] );
    00369         }
    00370
    00375         template<class T> static void from_setting ( T &variable_to_load, const Setting &element ) {
    00376                 std::string msg = "UIException: from_setting is not implemented for type ";
    00377                 msg += typeid(T).name();
    00378                 msg += '.';
    00379                 throw UISettingException ( msg, element );
    00380         }
    00381
    00382
    00383 protected:
    00385         UI ( const string& class_name, const type_info * const class_type_info ) {
    00386                 MappedUI::add_class ( class_name, class_type_info, this );
    00387         }
    00388
    00389 public:
    00390
    00392         enum SettingPresence { optional, compulsory } ;
    00393
    00397
    00401         template<class T>
    00402         static shared_ptr<T> build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00403                 if ( !element.exists ( name ) ) {
    00404                         if ( settingPresence == optional )
    00405                                 return shared_ptr<T>();
    00406                         else
    00407                                 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element );
    00408                 }
    00409
    00410                 shared_ptr<T> instance;
    00411                 from_setting<T> ( instance, to_child_setting ( element, name ) );
    00412                 return instance;
    00413         }
    00414
    00418         template<class T>
    00419         static shared_ptr<T> build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00420                 if ( element.getLength() <= index ) {
    00421                         if ( settingPresence == optional )
    00422                                 return shared_ptr<T>();
    00423                         else {
    00424                                 stringstream stream;
    00425                                 stream << index;
    00426                                 throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element );
    00427                         }
    00428                 }
    00429
    00430                 shared_ptr<T> instance;
    00431                 from_setting<T> ( instance, to_child_setting ( element, index ) );
    00432                 return instance;
    00433         }
    00434
    00436
    00440
    00443         template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00444                 if ( !element.exists ( name ) ) {
    00445                         if ( settingPresence == optional )
    00446                                 return false;
    00447                         else
    00448                                 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element );
    00449                 }
    00450
    00451                 from_setting ( instance, to_child_setting ( element, name ) );
    00452                 return true;
    00453         }
    00454
    00457         template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00458                 if ( element.getLength() <= index ) {
    00459                         if ( settingPresence == optional )
    00460                                 return false;
    00461                         else {
    00462                                 stringstream stream;
    00463                                 stream << "UIException: the compulsory Setting with the index " << index << " is missing.";
    00464                                 stream << index;
    00465                                 throw UISettingException (stream.str(), element );
    00466                         }
    00467                 }
    00468
    00469                 from_setting ( instance, to_child_setting ( element, index ) );
    00470                 return true;
    00471         }
    00472
    00474         template<class T> static bool get ( T &instance, const Setting &element ) {
    00475                 from_setting ( instance, element );
    00476                 return true;
    00477         }
    00479
    00483
    00486         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
    00487                 if ( !element.exists ( name ) )
    00488                         return false;
    00489
    00490                 from_setting ( array_to_load, to_child_setting ( element, name ) );
    00491                 return true;
    00492         }
    00493
    00496         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
    00497                 if ( element.getLength() <= index )
    00498                         return false;
    00499
    00500                 from_setting ( array_to_load, to_child_setting ( element, index ) );
    00501                 return true;
    00502         }
    00503
    00505         template<class T> static bool get ( Array<T> &array_to_load, const Setting &element ) {
    00506                 from_setting ( array_to_load, element );
    00507                 return true;
    00508         }
    00510
    00515
    00517         template< class T> static void save ( const T * const instance, Setting &element, const string &name = "" ) {
    00518                 Setting &set = ( name == "" ) ? element.add ( Setting::TypeGroup )
    00519                                : element.add ( name, Setting::TypeGroup );
    00520
    00521                 const string &class_name = MappedUI::retrieve_class_name ( &typeid ( *instance ) );
    00522
    00523                 // add attribute "class"
    00524                 Setting &type = set.add ( "class", Setting::TypeString );
    00525                 type = class_name;
    00526
    00527                 try {
    00528                         instance->to_setting ( set );
    00529                 } catch ( SettingException &sttng_xcptn ) {
    00530                         string msg = "UIException: method ";
    00531                         msg += class_name;
    00532                         msg += ".to_setting(Setting&) has thrown a SettingException.";
    00533                         throw UISettingException(msg, sttng_xcptn.getPath());
    00534                 }
    00535         }
    00536
    00537         template< class T> static void save ( const shared_ptr<T> &instance, Setting &element, const string &name = "" ) {
    00538                 save<T> ( instance.get(), element, name );
    00539         }
    00540
    00542         template<class T> static void save ( const Array<T> &array_to_save, Setting &element, const string &name = "" ) {
    00543                 assert_type ( element, Setting::TypeGroup );
    00544                 Setting &list = ( name == "" ) ? element.add ( Setting::TypeList )
    00545                                 : element.add ( name, Setting::TypeList );
    00546                 for ( int i = 0; i < array_to_save.length(); i++ )
    00547                         save ( array_to_save ( i ), list );
    00548         }
    00549
    00551         static void save ( const mat &matrix, Setting &element, const string &name = "" );
    00552
    00554         static void save ( const ivec &vec, Setting &element, const string &name = "" );
    00555
    00557         static void save ( const vec &vector, Setting &element, const string &name = "" );
    00558
    00560         static void save ( const string &str, Setting &element, const string &name = "" );
    00561
    00563         static void save ( const int &integer, Setting &element, const string &name = "" );
    00564
    00566         static void save ( const double &real, Setting &element, const string &name = "" );
    00568
    00569 };
    00570
    00571
    00574 template<typename T> class ParticularUI : private UI {
    00575 public:
    00577         ParticularUI<T> ( const string &class_name ) : UI ( class_name, &typeid ( T ) ) {};
    00578
    00580         root* new_instance() const {
    00581                 return new T();
    00582         }
    00583 };
    00584
    00585 }
    00586
    00596 #ifndef BDMLIB
    00597 #define UIREGISTER(class_name) static bdm::ParticularUI<class_name> UI##class_name(#class_name)
    00598 #else
    00599 #define UIREGISTER(class_name)
    00600 #endif
    00601
    00603 #define QUOTEME(x) #x
    00604
    00613 #ifndef BDMLIB
    00614 #define UIREGISTER2(class_name, temp_name) static bdm::ParticularUI<class_name<temp_name> > UI##class_name##_##temp_name( QUOTEME(class_name<temp_name>) )
    00615 #else
    00616 #define UIREGISTER2(class_name,temp_name)
    00617 #endif
    00618
    00619 #endif // #ifndef USER_INFO_H