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
00014 using std::string;
00015 using namespace std;
00016 using namespace libconfig;
00017
00018 #ifndef BDMLIB
00020 #define UIREGISTER(class_name) template<> const Particular_UI<class_name>& Particular_UI<class_name>::ui = Particular_UI<class_name>(#class_name)
00021 #else
00022 #define UIREGISTER(class_name)
00023 #endif
00024
00025 #define ASSERT_UITYPE(S,Type) it_assert_debug(S.getType()==Setting::Type, string("Wrong setting type, see input path \"")+string(S.getPath())+string("\""))
00026
00027 namespace bdm
00028 {
00029 class UI_File : public Config
00030 {
00031 private:
00032 const string file_name;
00033
00034 public:
00036 UI_File();
00037
00039 UI_File( const string &file_name );
00040
00042 void save(const string &file_name);
00043
00044 operator Setting&();
00045 };
00046
00078 class UI
00079 {
00080 private:
00085 class Mapped_UI
00086 {
00087 private:
00089 typedef map< const string, const UI* const > String_To_UI_Map;
00090
00092 typedef map< const type_info * const, const string > Type_Info_To_String_Map;
00093
00095 static String_To_UI_Map& mapped_strings();
00096
00098 static Type_Info_To_String_Map& mapped_type_infos();
00099
00100 public:
00102 static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
00103
00105 static const UI& retrieve_ui( const string &class_name );
00106
00108 static const string& retrieve_class_name( const type_info* const class_type_info );
00109 };
00110
00111
00112
00113
00115 virtual bdmroot* new_instance() const = 0;
00116
00120 static const Setting& to_child_setting( const Setting &element, const int index );
00121
00122 static const Setting& to_child_setting( const Setting &element, const string &name );
00123
00124
00127
00129 static void from_setting( mat& matrix, const Setting &element );
00131 static void from_setting( ivec &vector, const Setting &element );
00132
00133 static void from_setting( string &str, const Setting &element );
00135
00136 static void from_setting( vec &vector, const Setting &element );
00137
00138 template<class T> static void from_setting( T* &instance, const Setting &element )
00139 {
00140 const SettingsResolver link_expander( element );
00141 const Setting &root = link_expander.root();
00142
00143 ASSERT_UITYPE(root,TypeGroup);
00144
00145
00146 string class_name;
00147 if( !root.lookupValue( "class", class_name ) )
00148 ui_error( "the obligatory ""class"" identifier is missing", root );
00149
00150
00151 const UI& related_UI = Mapped_UI::retrieve_ui( class_name );
00152
00153 bdmroot* typeless_instance = related_UI.new_instance();
00154
00155 instance = NULL;
00156 try
00157 {
00158 instance = (T*) typeless_instance ;
00159 }
00160 catch(...)
00161 {
00162 it_error ( "UI error: class " + class_name + " is not a descendant of the desired output class. Try to call the UI::build function with a different type parameter." );
00163 }
00164
00165 try
00166 {
00167 instance->from_setting( root );
00168 }
00169 catch(SettingException xcptn)
00170 {
00171 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." );
00172 }
00173 }
00174
00175
00177
00178 template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
00179 {
00180 const SettingsResolver link_expander( element );
00181 const Setting &root = link_expander.root();
00182
00183 ASSERT_UITYPE(root,TypeList);
00184
00185 int len = root.getLength();
00186 array_to_load.set_length( len );
00187 if( len == 0 ) return;
00188
00189 for( int i=0; i < len; i++ )
00190 from_setting( array_to_load(i), root[i] );
00191 }
00192
00194
00195
00196 static void ui_error( string message, const Setting &element );
00197
00198 protected:
00200 UI( const string& class_name, const type_info * const class_type_info )
00201 {
00202 Mapped_UI::add_class( class_name, class_type_info, this );
00203 }
00204
00206 virtual ~UI(){};
00207
00208 public:
00212
00213
00214
00215 class SettingsResolver
00216 {
00217 private:
00218 UI_File *file;
00219 const Setting *result;
00220
00221 public:
00222
00223 SettingsResolver( const Setting &potential_link );
00224
00225 ~SettingsResolver();
00226
00227 const Setting& root() const;
00228 };
00229
00230
00231
00233 template<class T> static T* build( const Setting &element, const int index )
00234 {
00235 T* instance;
00236 from_setting<T>( to_child_setting( element, index ) );
00237 return instance;
00238 }
00239
00240 template<class T> static T* build( const Setting &element, const string &name )
00241 {
00242 T* instance;
00243 from_setting<T>( instance, to_child_setting( element, name ) );
00244 return instance;
00245 }
00246
00248 template<class T> static void get( T &instance, const Setting &element, const string &name )
00249 {
00250 from_setting( instance, to_child_setting( element, name ) );
00251 }
00252
00254 template<class T> static void get( T &instance, const Setting &element, const int index )
00255 {
00256 from_setting( instance, to_child_setting( element, index ) );
00257 }
00258
00260 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
00261 {
00262 from_setting( array_to_load, to_child_setting( element, name ) );
00263 }
00264
00266 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
00267 {
00268 from_setting( array_to_load, to_child_setting( element, index ) );
00269 }
00270
00271 template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
00272 {
00273 Setting &root = (name == "") ? element.add( Setting::TypeGroup )
00274 : element.add( name, Setting::TypeGroup );
00275
00276 const string &class_name = Mapped_UI::retrieve_class_name( &typeid(*instance) );
00277
00278
00279 Setting &type = root.add( "class", Setting::TypeString );
00280 type = class_name;
00281
00282 try
00283 {
00284 instance->to_setting( root );
00285 }
00286 catch(SettingException xcptn)
00287 {
00288 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." );
00289 }
00290 }
00291
00293 template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
00294 {
00295 ASSERT_UITYPE(element,TypeGroup);
00296 Setting &list = (name == "") ? element.add( Setting::TypeList )
00297 : element.add( name, Setting::TypeList );
00298 for( int i=0; i<array_to_save.length(); i++ )
00299 save( array_to_save(i), list );
00300 }
00301
00302
00304 static void save( const mat &matrix, Setting &element, const string &name = "" );
00305
00307 static void save( const ivec &vec, Setting &element, const string &name = "" );
00308
00309 static void save( const vec &vector, Setting &element, const string &name);
00310
00311 private:
00313 static void save( const string &str, Setting &element);
00314
00315 };
00316
00317
00323 template<typename T> class Particular_UI : private UI
00324 {
00325 public:
00326
00328 Particular_UI<T>( const string &class_name) : UI( class_name, &typeid(T) )
00329 { cout << class_name << endl;
00330 };
00331
00334 static const Particular_UI<T>& ui;
00335
00336 bdmroot* new_instance() const
00337 {
00338 return new T();
00339 }
00340 };
00341
00342
00343
00344
00345 }
00346
00370 #endif // #ifndef USER_INFO_H