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                 
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                 
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                 
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