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
00019 #define UIREGISTER(class_name) template<> const Particular_UI<class_name>& Particular_UI<class_name>::ui = Particular_UI<class_name>(#class_name)
00020 #else
00021 #define UIREGISTER(class_name)
00022 #endif
00023
00024 #define ASSERT_UITYPE(S,Type) it_assert_debug(S.getType()==Setting::Type, string("Wrong setting type, see input path \"")+string(S.getPath())+string("\""))
00025
00026 namespace bdm
00027 {
00028 class UI_File : public Config
00029 {
00030 private:
00031 const string file_name;
00032
00033 public:
00035 UI_File();
00036
00038 UI_File( const string &file_name );
00039
00041 void save(const string &file_name);
00042
00043 operator Setting&();
00044 };
00045
00077 class UI
00078 {
00079 private:
00084 class Mapped_UI
00085 {
00086 private:
00088 typedef map< const string, const UI* const > String_To_UI_Map;
00089
00091 typedef map< const type_info * const, const string > Type_Info_To_String_Map;
00092
00094 static String_To_UI_Map& mapped_strings();
00095
00097 static Type_Info_To_String_Map& mapped_type_infos();
00098
00099 public:
00101 static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
00102
00104 static const UI& retrieve_ui( const string &class_name );
00105
00107 static const string& retrieve_class_name( const type_info* const class_type_info );
00108 };
00109
00110
00111
00112
00114 virtual bdmroot* new_instance() const = 0;
00115
00119 static const Setting& to_child_setting( const Setting &element, const int index );
00120
00121 static const Setting& to_child_setting( const Setting &element, const string &name );
00122
00123
00126
00128 static void from_setting( mat& matrix, const Setting &element );
00130 static void from_setting( ivec &vector, const Setting &element );
00131
00132 static void from_setting( string &str, const Setting &element );
00134
00135 static void from_setting( vec &vector, const Setting &element );
00136
00137 template<class T> static void from_setting( T* &instance, const Setting &element )
00138 {
00139 const SettingsResolver link_expander( element );
00140 const Setting &root = link_expander.root();
00141
00142 ASSERT_UITYPE(root,TypeGroup);
00143
00144
00145 string class_name;
00146 if( !root.lookupValue( "class", class_name ) )
00147 ui_error( "the obligatory ""class"" identifier is missing", root );
00148
00149
00150 const UI& related_UI = Mapped_UI::retrieve_ui( class_name );
00151
00152 bdmroot* typeless_instance = related_UI.new_instance();
00153
00154 instance = NULL;
00155 try
00156 {
00157 instance = (T*) typeless_instance ;
00158 }
00159 catch(...)
00160 {
00161 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." );
00162 }
00163
00164 try
00165 {
00166 instance->from_setting( root );
00167 }
00168 catch(SettingException xcptn)
00169 {
00170 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." );
00171 }
00172 }
00173
00174
00176
00177 template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
00178 {
00179 const SettingsResolver link_expander( element );
00180 const Setting &root = link_expander.root();
00181
00182 ASSERT_UITYPE(root,TypeList);
00183
00184 int len = root.getLength();
00185 array_to_load.set_length( len );
00186 if( len == 0 ) return;
00187
00188 for( int i=0; i < len; i++ )
00189 from_setting( array_to_load(i), root[i] );
00190 }
00191
00193
00194
00195 static void ui_error( string message, const Setting &element );
00196
00197 protected:
00199 UI( const string& class_name, const type_info * const class_type_info )
00200 {
00201 Mapped_UI::add_class( class_name, class_type_info, this );
00202 }
00203
00205 virtual ~UI(){};
00206
00207 public:
00211
00212
00213
00214 class SettingsResolver
00215 {
00216 private:
00217 UI_File *file;
00218 const Setting *result;
00219
00220 public:
00221
00222 SettingsResolver( const Setting &potential_link );
00223
00224 ~SettingsResolver();
00225
00226 const Setting& root() const;
00227 };
00228
00229
00230
00232 template<class T> static T* build( const Setting &element, const int index )
00233 {
00234 T* instance;
00235 from_setting<T>( to_child_setting( element, index ) );
00236 return instance;
00237 }
00238
00239 template<class T> static T* build( const Setting &element, const string &name )
00240 {
00241 T* instance;
00242 from_setting<T>( instance, to_child_setting( element, name ) );
00243 return instance;
00244 }
00245
00247 template<class T> static void get( T &instance, const Setting &element, const string &name )
00248 {
00249 from_setting( instance, to_child_setting( element, name ) );
00250 }
00251
00253 template<class T> static void get( T &instance, const Setting &element, const int index )
00254 {
00255 from_setting( instance, to_child_setting( element, index ) );
00256 }
00257
00259 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
00260 {
00261 from_setting( array_to_load, to_child_setting( element, name ) );
00262 }
00263
00265 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
00266 {
00267 from_setting( array_to_load, to_child_setting( element, index ) );
00268 }
00269
00270 template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
00271 {
00272 Setting &root = (name == "") ? element.add( Setting::TypeGroup )
00273 : element.add( name, Setting::TypeGroup );
00274
00275 const string &class_name = Mapped_UI::retrieve_class_name( &typeid(*instance) );
00276
00277
00278 Setting &type = root.add( "class", Setting::TypeString );
00279 type = class_name;
00280
00281 try
00282 {
00283 instance->to_setting( root );
00284 }
00285 catch(SettingException xcptn)
00286 {
00287 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." );
00288 }
00289 }
00290
00292 template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
00293 {
00294 ASSERT_UITYPE(element,TypeGroup);
00295 Setting &list = (name == "") ? element.add( Setting::TypeList )
00296 : element.add( name, Setting::TypeList );
00297 for( int i=0; i<array_to_save.length(); i++ )
00298 save( array_to_save(i), list );
00299 }
00300
00301
00303 static void save( const mat &matrix, Setting &element, const string &name = "" );
00304
00306 static void save( const ivec &vec, Setting &element, const string &name = "" );
00307
00308 static void save( const vec &vector, Setting &element, const string &name);
00309
00310 private:
00312 static void save( const string &str, Setting &element);
00313
00314 };
00315
00316
00322 template<typename T> class Particular_UI : private UI
00323 {
00324 public:
00325
00327 Particular_UI<T>( const string &class_name) : UI( class_name, &typeid(T) )
00328 { cout << class_name << endl;
00329 };
00330
00333 static const Particular_UI<T>& ui;
00334
00335 bdmroot* new_instance() const
00336 {
00337 return new T();
00338 }
00339 };
00340
00341
00342
00343
00344 }
00345
00369 #endif // #ifndef USER_INFO_H