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