00001 #ifndef USER_INFO_H
00002 #define USER_INFO_H
00003
00004 #include <stdio.h>
00005 #include <string>
00006 #include <typeinfo>
00007 #include <map>
00008
00009 #include "libconfig/libconfig.h++"
00010 #include "../bdmroot.h"
00011 #include "itpp/itbase.h"
00012
00013 #include <stdexcept>
00014
00015 using std::string;
00016 using namespace std;
00017 using namespace libconfig;
00018
00019 namespace bdm
00020 {
00021
00028 #ifndef BDMLIB
00029 #define UIREGISTER(class_name) template<> const ParticularUI<class_name>& ParticularUI<class_name>::ui = ParticularUI<class_name>(#class_name)
00030 #else
00031 #define UIREGISTER(class_name)
00032 #endif
00033
00035 #define ASSERT_UITYPE(SET,TYPE) it_assert_debug(SET.getType()==Setting::TYPE, string("Wrong setting type, see input path \"")+string(SET.getPath())+string("\""))
00036
00038 class UIbuildException : public std::invalid_argument {
00039 public:
00040 UIbuildException() : std::invalid_argument("class name") { }
00041 };
00042
00065 class UIFile : public Config
00066 {
00067 public:
00069 UIFile();
00070
00072 UIFile( const string &file_name );
00073
00075 void save(const string &file_name);
00076
00078 operator Setting&();
00079 };
00080
00081
00082
00090 class UI
00091 {
00092 private:
00098 class MappedUI
00099 {
00100 private:
00102 typedef map< const string, const UI* const > StringToUIMap;
00103
00105 typedef map< const type_info * const, const string > TypeInfoToStringMap;
00106
00108 static StringToUIMap& mapped_strings();
00109
00111 static TypeInfoToStringMap& mapped_type_infos();
00112
00114 static void unregistered_class_error( const string &unregistered_class_name );
00115
00116 public:
00118 static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
00119
00121 static const UI& retrieve_ui( const string &class_name );
00122
00124 static const string& retrieve_class_name( const type_info* const class_type_info );
00125 };
00126
00128 virtual root* new_instance() const = 0;
00129
00131 static const Setting& to_child_setting( const Setting &element, const int index );
00132
00134 static const Setting& to_child_setting( const Setting &element, const string &name );
00135
00137 static void from_setting( mat& matrix, const Setting &element );
00139 static void from_setting( ivec &vector, const Setting &element );
00141 static void from_setting( string &str, const Setting &element );
00143 static void from_setting( vec &vector, const Setting &element );
00145 static void from_setting( int &integer, const Setting &element );
00147 static void from_setting( double &real, const Setting &element );
00149 template<class T> static void from_setting( T* &instance, const Setting &element )
00150 {
00151 const SettingResolver link( element );
00152
00153 ASSERT_UITYPE(link.result,TypeGroup);
00154
00155
00156 string class_name;
00157 if( !link.result.lookupValue( "class", class_name ) )
00158 ui_error( "the obligatory ""class"" identifier is missing", link.result );
00159
00160
00161 const UI& related_UI = MappedUI::retrieve_ui( class_name );
00162
00163 root* typeless_instance = related_UI.new_instance();
00164
00165 instance = NULL;
00166
00167 instance = dynamic_cast<T*>(typeless_instance);
00168 if (!instance){
00169 throw UIbuildException();
00170 }
00171
00172
00173
00174
00175
00176
00177 try
00178 {
00179 instance->from_setting( link.result );
00180 }
00181 catch(SettingException xcptn)
00182 {
00183
00184 it_error ( "UI error: the method " + class_name + ".from_setting(Setting&) has thrown an exception when parsing the setting " + xcptn.getPath() + ". Try to correct this method." );
00185 }
00186 }
00187
00189
00190 template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
00191 {
00192 const SettingResolver link( element );
00193
00194 ASSERT_UITYPE(link.result,TypeList);
00195
00196 int len = link.result.getLength();
00197 array_to_load.set_length( len );
00198 if( len == 0 ) return;
00199
00200 for( int i=0; i < len; i++ )
00201 from_setting( array_to_load(i), link.result[i] );
00202 }
00203
00205 static void ui_error( string message, const Setting &element );
00206
00207 protected:
00209 UI( const string& class_name, const type_info * const class_type_info )
00210 {
00211 MappedUI::add_class( class_name, class_type_info, this );
00212 }
00213
00214 public:
00215
00234 class SettingResolver
00235 {
00236 private:
00238 UIFile *file;
00239
00245 const Setting &initialize_reference( UIFile* &file, const Setting &potential_link);
00246
00247 public:
00249 const Setting &result;
00250
00252 SettingResolver( const Setting &potential_link );
00253
00255 ~SettingResolver();
00256 };
00257
00258
00262 template<class T> static T* build( const Setting &element, const int index )
00263 {
00264 T* instance;
00265 from_setting<T>( instance, to_child_setting( element, index ) );
00266 return instance;
00267 }
00269 template<class T> static T* build( const Setting &element )
00270 {
00271 T* instance;
00272 from_setting<T>( instance, element );
00273 return instance;
00274 }
00275
00276 template<class T> static T* build( const Setting &element, const string &name )
00277 {
00278 T* instance;
00279 from_setting<T>( instance, to_child_setting( element, name ) );
00280 return instance;
00281 }
00283
00287 template<class T> static void get( T &instance, const Setting &element, const string &name )
00288 {
00289 from_setting( instance, to_child_setting( element, name ) );
00290 }
00291
00293 template<class T> static void get( T &instance, const Setting &element, const int index )
00294 {
00295 from_setting( instance, to_child_setting( element, index ) );
00296 }
00297
00299 template<class T> static void get( T &instance, const Setting &element )
00300 {
00301 from_setting( instance, element );
00302 }
00303
00305 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
00306 {
00307 from_setting( array_to_load, to_child_setting( element, name ) );
00308 }
00309
00311 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
00312 {
00313 from_setting( array_to_load, to_child_setting( element, index ) );
00314 }
00315
00317 template<class T> static void get( Array<T> &array_to_load, const Setting &element )
00318 {
00319 from_setting( array_to_load, element );
00320 }
00322
00323 template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
00324 {
00325 Setting &set = (name == "") ? element.add( Setting::TypeGroup )
00326 : element.add( name, Setting::TypeGroup );
00327
00328 const string &class_name = MappedUI::retrieve_class_name( &typeid(*instance) );
00329
00330
00331 Setting &type = set.add( "class", Setting::TypeString );
00332 type = class_name;
00333
00334 try
00335 {
00336 instance->to_setting( set );
00337 }
00338 catch(SettingException xcptn)
00339 {
00340 it_error ( "UI error: the method " + class_name + ".to_setting(Setting&) has thrown an exception when filling the setting " + xcptn.getPath() + ". Try to correct this method." );
00341 }
00342 }
00343
00345 template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
00346 {
00347 ASSERT_UITYPE(element,TypeGroup);
00348 Setting &list = (name == "") ? element.add( Setting::TypeList )
00349 : element.add( name, Setting::TypeList );
00350 for( int i=0; i<array_to_save.length(); i++ )
00351 save( array_to_save(i), list );
00352 }
00353
00354
00356 static void save( const mat &matrix, Setting &element, const string &name = "" );
00357
00359 static void save( const ivec &vec, Setting &element, const string &name = "" );
00360
00361 static void save( const vec &vector, Setting &element, const string &name = "" );
00363 static void save( const string &str, Setting &element, const string &name = "" );
00364
00365 static void save( const int &integer, Setting &element, const string &name = "" );
00366
00367 static void save( const double &real, Setting &element, const string &name = "" );
00368
00369 };
00370
00371
00377 template<typename T> class ParticularUI : private UI
00378 {
00379 public:
00380
00382 ParticularUI<T>( const string &class_name) : UI( class_name, &typeid(T) )
00383 { cout << class_name << endl;
00384 };
00385
00388 static const ParticularUI<T>& ui;
00389
00390 root* new_instance() const
00391 {
00392 return new T();
00393 }
00394 };
00395
00396
00397
00398
00399 }
00400
00424 #endif // #ifndef USER_INFO_H