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 };
00076
00077
00100 class UIFile : public Config
00101 {
00102 public:
00104 UIFile();
00105
00107 UIFile( const string &file_name );
00108
00110 void save(const string &file_name);
00111
00113 operator Setting&();
00114 };
00115
00180 class SettingResolver : root
00181 {
00182 private:
00184 UIFile *file;
00185
00191 const Setting &initialize_reference( UIFile* &file, const Setting &potential_link);
00192
00193 public:
00195 const Setting &result;
00196
00198 SettingResolver( const Setting &potential_link );
00199
00201 ~SettingResolver();
00202 };
00203
00211 class UI
00212 {
00213 private:
00219 class MappedUI
00220 {
00221 private:
00223 typedef map< const string, const UI* const > StringToUIMap;
00224
00226 typedef map< const type_info * const, const string > TypeInfoToStringMap;
00227
00229 static StringToUIMap& mapped_strings();
00230
00232 static TypeInfoToStringMap& mapped_type_infos();
00233
00235 static void unregistered_class_error( const string &unregistered_class_name );
00236
00237 public:
00239 static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
00240
00242 static const UI& retrieve_ui( const string &class_name );
00243
00245 static const string& retrieve_class_name( const type_info* const class_type_info );
00246 };
00247
00249 static void assert_type( const Setting &element, Setting::Type type);
00250
00252 virtual root* new_instance() const = 0;
00253
00255 static const Setting& to_child_setting( const Setting &element, const int index );
00256
00258 static const Setting& to_child_setting( const Setting &element, const string &name );
00259
00261 static void from_setting( mat& matrix, const Setting &element );
00263 static void from_setting( ivec &vector, const Setting &element );
00265 static void from_setting( string &str, const Setting &element );
00267 static void from_setting( vec &vector, const Setting &element );
00269 static void from_setting( int &integer, const Setting &element );
00271 static void from_setting( double &real, const Setting &element );
00273 template<class T> static void from_setting( T* &instance, const Setting &element )
00274 {
00275 const SettingResolver link( element );
00276 assert_type(link.result,Setting::TypeGroup);
00277
00278
00279 string class_name;
00280 if( !link.result.lookupValue( "class", class_name ) )
00281 throw UIException( "the obligatory \"class\" identifier is missing", link.result );
00282
00283
00284 const UI& related_UI = MappedUI::retrieve_ui( class_name );
00285
00286 root* typeless_instance = related_UI.new_instance();
00287
00288 instance = dynamic_cast<T*>(typeless_instance);
00289 if (!instance)
00290 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 );
00291
00292 try
00293 {
00294 instance->from_setting( link.result );
00295 }
00296 catch(SettingException xcptn)
00297 {
00298 throw UIException( "the method " + class_name + ".from_setting(Setting&) has thrown an SettingException. Try to correct this method", xcptn.getPath());
00299 }
00300 }
00301
00303 template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
00304 {
00305 const SettingResolver link( element );
00306
00307 assert_type(link.result,Setting::TypeList);
00308
00309 int len = link.result.getLength();
00310 array_to_load.set_length( len );
00311 if( len == 0 ) return;
00312
00313 for( int i=0; i < len; i++ )
00314 from_setting( array_to_load(i), link.result[i] );
00315 }
00316
00317 protected:
00319 UI( const string& class_name, const type_info * const class_type_info )
00320 {
00321 MappedUI::add_class( class_name, class_type_info, this );
00322 }
00323
00324 public:
00325
00329
00331 template<class T> static T* build( const Setting &element, const string &name )
00332 {
00333 T* instance;
00334 from_setting<T>( instance, to_child_setting( element, name ) );
00335 return instance;
00336 }
00338 template<class T> static T* build( const Setting &element, const int index )
00339 {
00340 T* instance;
00341 from_setting<T>( instance, to_child_setting( element, index ) );
00342 return instance;
00343 }
00345 template<class T> static T* build( const Setting &element )
00346 {
00347 T* instance;
00348 from_setting<T>( instance, element );
00349 return instance;
00350 }
00352
00356
00358 template<class T> static void get( T &instance, const Setting &element, const string &name )
00359 {
00360 from_setting( instance, to_child_setting( element, name ) );
00361 }
00362
00364 template<class T> static void get( T &instance, const Setting &element, const int index )
00365 {
00366 from_setting( instance, to_child_setting( element, index ) );
00367 }
00368
00370 template<class T> static void get( T &instance, const Setting &element )
00371 {
00372 from_setting( instance, element );
00373 }
00375
00379
00381 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
00382 {
00383 from_setting( array_to_load, to_child_setting( element, name ) );
00384 }
00385
00387 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
00388 {
00389 from_setting( array_to_load, to_child_setting( element, index ) );
00390 }
00391
00393 template<class T> static void get( Array<T> &array_to_load, const Setting &element )
00394 {
00395 from_setting( array_to_load, element );
00396 }
00398
00403
00405 template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
00406 {
00407 Setting &set = (name == "") ? element.add( Setting::TypeGroup )
00408 : element.add( name, Setting::TypeGroup );
00409
00410 const string &class_name = MappedUI::retrieve_class_name( &typeid(*instance) );
00411
00412
00413 Setting &type = set.add( "class", Setting::TypeString );
00414 type = class_name;
00415
00416 try
00417 {
00418 instance->to_setting( set );
00419 }
00420 catch(SettingException xcptn)
00421 {
00422 throw UIException( "the method " + class_name + ".to_setting(Setting&) has thrown an SettingException. Try to correct this method", xcptn.getPath());
00423 }
00424 }
00425
00427 template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
00428 {
00429 assert_type(element,Setting::TypeGroup);
00430 Setting &list = (name == "") ? element.add( Setting::TypeList )
00431 : element.add( name, Setting::TypeList );
00432 for( int i=0; i<array_to_save.length(); i++ )
00433 save( array_to_save(i), list );
00434 }
00435
00437 static void save( const mat &matrix, Setting &element, const string &name = "" );
00438
00440 static void save( const ivec &vec, Setting &element, const string &name = "" );
00441
00443 static void save( const vec &vector, Setting &element, const string &name = "" );
00444
00446 static void save( const string &str, Setting &element, const string &name = "" );
00447
00449 static void save( const int &integer, Setting &element, const string &name = "" );
00450
00452 static void save( const double &real, Setting &element, const string &name = "" );
00454
00455 };
00456
00457
00459 template<typename T> class ParticularUI : private UI
00460 {
00461 private:
00463 ParticularUI<T>( const string &class_name) : UI( class_name, &typeid(T) )
00464 {};
00465
00466 public:
00468 static const ParticularUI<T>& factory;
00469
00471 root* new_instance() const
00472 {
00473 return new T();
00474 }
00475 };
00476
00477 }
00478
00479 #endif // #ifndef USER_INFO_H