mixpp: user_info.h Source File

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 "../bdmroot.h"
00025 #include "../shared_ptr.h"
00026 #include "itpp/itbase.h"
00027 #include "../math/square_mat.h"
00028 #include "../math/chmat.h"
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
00232
00233
00244 class UI {
00245 private:
00251     class MappedUI {
00252     private:
00254         typedef map< const string, const UI* const > StringToUIMap;
00255
00257         typedef map< const type_info * const, const string > TypeInfoToStringMap;
00258
00260         static StringToUIMap& mapped_strings();
00261
00263         static TypeInfoToStringMap& mapped_type_infos();
00264
00266         static void unregistered_class_error ( const string &unregistered_class_name );
00267
00268     public:
00270         static void add_class ( const string &class_name, const type_info * const class_type_info, const UI* const ui );
00271
00273         static const UI& retrieve_ui ( const string &class_name );
00274
00276         static const string& retrieve_class_name ( const type_info* const class_type_info );
00277     };
00278
00280     static void assert_type ( const Setting &element, Setting::Type type );
00281
00290     virtual root* new_instance() const = 0;
00291
00293     static const Setting& to_child_setting ( const Setting &element, const int index );
00294
00296     static const Setting& to_child_setting ( const Setting &element, const string &name );
00297
00299     static void call_from_setting( root &instance, const Setting &set, string class_name = "unknown");
00300
00302     static void call_to_setting( const root &instance, Setting &set, string class_name = "unknown" );
00303
00305     static void from_setting ( mat& matrix, const Setting &element );
00307     static void from_setting ( ldmat& matrix, const Setting &element );
00309     static void from_setting ( ivec &vector, const Setting &element );
00311     static void from_setting ( string &str, const Setting &element );
00313     static void from_setting ( vec &vector, const Setting &element );
00315     static void from_setting ( int &integer, const Setting &element );
00317     static void from_setting ( double &real, const Setting &element );
00319     static void from_setting ( root &instance, const Setting &element );
00325     static void from_setting ( log_level_base &log_level, const Setting &element );
00327     template<class T> static void from_setting ( T* &instance, const Setting &element ) {
00328         const SettingResolver link ( element );
00329         assert_type( link.result, Setting::TypeGroup );
00330
00331         // we get a value stored in the "class" attribute
00332         string class_name;
00333         if ( !link.result.lookupValue ( "class", class_name ) )
00334             throw UIClassException ( "UIException: the obligatory \"class\" identifier is missing.", link.result );
00335
00336         // then we find a user-info related to this type
00337         const UI& related_UI = MappedUI::retrieve_ui ( class_name );
00338
00339         root *typeless_instance = related_UI.new_instance();
00340         bdm_assert ( typeless_instance, "UI::new_instance failed" );
00341
00342         instance = dynamic_cast<T*> ( typeless_instance );
00343         if ( !instance ) {
00344             delete typeless_instance;
00345             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 );
00346         }
00347
00348         try {
00349             call_from_setting( *instance, link.result, class_name );
00350         } catch ( ... ) {
00351             delete instance;
00352             instance = 0;
00353             throw;
00354         }
00355     }
00356
00359     template<class T> static void from_setting ( bdm::shared_ptr<T> &instance, const Setting &element ) {
00360         T *tmp_inst = 0;
00361         from_setting ( tmp_inst, element );
00362         bdm_assert ( tmp_inst, "UI::from_setting failed" );
00363         instance = tmp_inst;
00364     }
00365
00367     template<class T> static void from_setting ( Array<T> &array_to_load, const Setting &element ) {
00368         const SettingResolver link ( element );
00369
00370         assert_type ( link.result, Setting::TypeList );
00371
00372         int len = link.result.getLength();
00373         array_to_load.set_length ( len );
00374         if ( len == 0 ) return;
00375
00376         for ( int i = 0; i < len; i++ )
00377             from_setting ( array_to_load ( i ), link.result[i] );
00378     }
00379
00380 protected:
00382     UI ( const string& class_name, const type_info * const class_type_info ) {
00383         MappedUI::add_class ( class_name, class_type_info, this );
00384     }
00385
00386 public:
00387
00389     enum SettingPresence { optional, compulsory } ;
00390
00394
00399     template<class T>
00400     static bdm::shared_ptr<T> build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
00401         if ( !element.exists ( name ) ) {
00402             if ( settingPresence == optional )
00403                 return bdm::shared_ptr<T>();
00404             else
00405                 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element );
00406         }
00407
00408         bdm::shared_ptr<T> instance;
00409         from_setting<T> ( instance, to_child_setting ( element, name ) );
00410         return instance;
00411     }
00412
00417     template<class T>
00418     static bdm::shared_ptr<T> build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) {
00419         if ( element.getLength() <= index ) {
00420             if ( settingPresence == optional )
00421                 return bdm::shared_ptr<T>();
00422             else {
00423                 stringstream stream;
00424                 stream << index;
00425                 throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element );
00426             }
00427         }
00428
00429         bdm::shared_ptr<T> instance;
00430         from_setting<T> ( instance, to_child_setting ( element, index ) );
00431         return instance;
00432     }
00433
00437     template<class T>
00438     static bdm::shared_ptr<T> build ( const Setting &element, SettingPresence settingPresence = optional ) {
00439         bdm::shared_ptr<T> instance;
00440         from_setting<T> ( instance,  element );
00441         return instance;
00442     }
00443
00445
00449
00452     template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
00453         if ( !element.exists ( name ) ) {
00454             if ( settingPresence == optional )
00455                 return false;
00456             else
00457                 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element );
00458         }
00459
00460         from_setting ( instance, to_child_setting ( element, name ) );
00461         return true;
00462     }
00463
00466     template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
00467         if ( element.getLength() <= index ) {
00468             if ( settingPresence == optional )
00469                 return false;
00470             else {
00471                 stringstream stream;
00472                 stream << "UIException: the compulsory Setting with the index " << index << " is missing.";
00473                 stream << index;
00474                 throw UISettingException ( stream.str(), element );
00475             }
00476         }
00477
00478         from_setting ( instance, to_child_setting ( element, index ) );
00479         return true;
00480     }
00481
00483     template<class T> static bool get ( T &instance, const Setting &element ) {
00484         from_setting ( instance, element );
00485         return true;
00486     }
00488
00492
00495     template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const string &name, SettingPresence settingPresence = optional ) {
00496         if ( !element.exists ( name ) ) {
00497             if ( settingPresence == optional )
00498                 return false;
00499             else
00500                 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element );
00501         }
00502
00503         from_setting ( array_to_load, to_child_setting ( element, name ) );
00504         return true;
00505     }
00506
00509     template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const int index, SettingPresence settingPresence = optional ) {
00510         if ( element.getLength() <= index ) {
00511             if ( settingPresence == optional )
00512                 return bdm::shared_ptr<T>();
00513             else {
00514                 stringstream stream;
00515                 stream << index;
00516                 throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element );
00517             }
00518         }
00519
00520         from_setting ( array_to_load, to_child_setting ( element, index ) );
00521         return true;
00522     }
00523
00525     template<class T> static bool get ( Array<T> &array_to_load, const Setting &element ) {
00526         from_setting ( array_to_load, element );
00527         return true;
00528     }
00530
00535
00537     static void save ( const root &instance, Setting &element, const string &name = "" );
00538
00540     static void save ( const root * const instance, Setting &element, const string &name = "" );
00541
00543     template< class T> static void save ( const bdm::shared_ptr<T> &instance, Setting &element, const string &name = "" ) {
00544         save( instance.get(), element, name );
00545     }
00546
00548     template<class T> static void save ( const Array<T> &array_to_save, Setting &element, const string &name = "" ) {
00549         assert_type ( element, Setting::TypeGroup );
00550         Setting &list = ( name == "" ) ? element.add ( Setting::TypeList )
00551                         : element.add ( name, Setting::TypeList );
00552         for ( int i = 0; i < array_to_save.length(); i++ )
00553             save ( array_to_save ( i ), list );
00554     }
00555
00557     static void save ( const mat &matrix, Setting &element, const string &name = "" );
00558
00560     static void save ( const ldmat &matrix, Setting &element, const string &name = "" );
00561
00563     static void save ( const ivec &vec, Setting &element, const string &name = "" );
00564
00566     static void save ( const vec &vector, Setting &element, const string &name = "" );
00567
00569     static void save ( const string &str, Setting &element, const string &name = "" );
00570
00572     static void save ( const int &integer, Setting &element, const string &name = "" );
00573
00575     static void save ( const double &real, Setting &element, const string &name = "" );
00576
00577     // The only difference from classical UserInfo approach here is the fact
00578     // that the actual UI element related to log_level_base could possibly exists yet. In this case,
00579     // we do not want to throw an exception as usually. We rather append current data into the existig element. This way, it is
00580     // possible that more instances of log_level_base  (templated with different classes)
00581     // can be stored in only one line in a configuration file
00582     static void save ( const log_level_base &log_level, Setting &element );
00583
00585
00587     virtual ~UI() {}
00588 };
00589
00590
00593 template<typename T> class ParticularUI : private UI {
00594 public:
00596     ParticularUI<T> ( const string &class_name ) : UI ( class_name, &typeid ( T ) ) {};
00597
00599     root* new_instance() const {
00600         return new T();
00601     }
00602 };
00603
00604 }
00605
00615 #ifndef BDMLIB
00616 #define UIREGISTER(class_name) static bdm::ParticularUI<class_name> UI##class_name(#class_name)
00617 #else
00618 #define UIREGISTER(class_name)
00619 #endif
00620 
00622 #define QUOTEME(x) #x
00623 
00632 #ifndef BDMLIB
00633 #define UIREGISTER2(class_name, temp_name) static bdm::ParticularUI<class_name<temp_name> > UI##class_name##_##temp_name( QUOTEME(class_name<temp_name>) )
00634 #else
00635 #define UIREGISTER2(class_name,temp_name)
00636 #endif
00637 
00638 #endif // #ifndef USER_INFO_H

Generated on 2 Dec 2013 for mixpp by  doxygen 1.4.7