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 #warning BDMLIB-defined
00021 #else
00022 #define UIREGISTER(class_name)
00023 #warning BDMLIB-empty
00024 #endif
00025
00026 #define ASSERT_UITYPE(S,Type) it_assert_debug(S.getType()==Setting::Type, string("Wrong setting type, see input path \"")+string(S.getPath())+string("\""))
00027
00028 namespace bdm
00029 {
00030 class UI_File : public Config
00031 {
00032 private:
00033 const string file_name;
00034
00035 public:
00037 UI_File();
00038
00040 UI_File( const string &file_name );
00041
00043 void save(const string &file_name);
00044
00045 operator Setting&();
00046 };
00047
00079 class UI
00080 {
00081 private:
00086 class Mapped_UI
00087 {
00088 private:
00090 typedef map< const string, const UI* const > String_To_UI_Map;
00091
00093 typedef map< const type_info * const, const string > Type_Info_To_String_Map;
00094
00096 static String_To_UI_Map& mapped_strings();
00097
00099 static Type_Info_To_String_Map& mapped_type_infos();
00100
00101 public:
00103 static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
00104
00106 static const UI& retrieve_ui( const string &class_name );
00107
00109 static const string& retrieve_class_name( const type_info* const class_type_info );
00110 };
00111
00112
00113
00114
00116 virtual bdmroot* new_instance() const = 0;
00117
00121 static const Setting& to_child_setting( const Setting &element, const int index );
00122
00123 static const Setting& to_child_setting( const Setting &element, const string &name );
00124
00125
00128
00130 static void from_setting( mat& matrix, const Setting &element );
00132 static void from_setting( ivec &vector, const Setting &element );
00133
00134 static void from_setting( string &str, const Setting &element );
00136
00137 static void from_setting( vec &vector, const Setting &element );
00138
00139 template<class T> static void from_setting( T* &instance, const Setting &element )
00140 {
00141 const SettingsResolver link_expander( element );
00142 const Setting &root = link_expander.root();
00143
00144 ASSERT_UITYPE(root,TypeGroup);
00145
00146
00147 string class_name;
00148 if( !root.lookupValue( "class", class_name ) )
00149 ui_error( "the obligatory ""class"" identifier is missing", root );
00150
00151
00152 const UI& related_UI = Mapped_UI::retrieve_ui( class_name );
00153
00154 bdmroot* typeless_instance = related_UI.new_instance();
00155
00156 instance = NULL;
00157 try
00158 {
00159 instance = (T*) typeless_instance ;
00160 }
00161 catch(...)
00162 {
00163 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." );
00164 }
00165
00166 try
00167 {
00168 instance->from_setting( root );
00169 }
00170 catch(SettingException xcptn)
00171 {
00172 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." );
00173 }
00174 }
00175
00176
00178
00179 template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
00180 {
00181 const SettingsResolver link_expander( element );
00182 const Setting &root = link_expander.root();
00183
00184 ASSERT_UITYPE(root,TypeList);
00185
00186 int len = root.getLength();
00187 array_to_load.set_length( len );
00188 if( len == 0 ) return;
00189
00190 for( int i=0; i < len; i++ )
00191 from_setting( array_to_load(i), root[i] );
00192 }
00193
00195
00196
00197 static void ui_error( string message, const Setting &element );
00198
00199 protected:
00201 UI( const string& class_name, const type_info * const class_type_info )
00202 {
00203 Mapped_UI::add_class( class_name, class_type_info, this );
00204 }
00205
00207 virtual ~UI(){};
00208
00209 public:
00213
00214
00215
00216 class SettingsResolver
00217 {
00218 private:
00219 UI_File *file;
00220 const Setting *result;
00221
00222 public:
00223
00224 SettingsResolver( const Setting &potential_link );
00225
00226 ~SettingsResolver();
00227
00228 const Setting& root() const;
00229 };
00230
00231
00232
00234 template<class T> static T* build( const Setting &element, const int index )
00235 {
00236 T* instance;
00237 from_setting<T>( to_child_setting( element, index ) );
00238 return instance;
00239 }
00240
00241 template<class T> static T* build( const Setting &element, const string &name )
00242 {
00243 T* instance;
00244 from_setting<T>( instance, to_child_setting( element, name ) );
00245 return instance;
00246 }
00247
00249 template<class T> static void get( T &instance, const Setting &element, const string &name )
00250 {
00251 from_setting( instance, to_child_setting( element, name ) );
00252 }
00253
00255 template<class T> static void get( T &instance, const Setting &element, const int index )
00256 {
00257 from_setting( instance, to_child_setting( element, index ) );
00258 }
00259
00261 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
00262 {
00263 from_setting( array_to_load, to_child_setting( element, name ) );
00264 }
00265
00267 template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
00268 {
00269 from_setting( array_to_load, to_child_setting( element, index ) );
00270 }
00271
00272 template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
00273 {
00274 Setting &root = (name == "") ? element.add( Setting::TypeGroup )
00275 : element.add( name, Setting::TypeGroup );
00276
00277 const string &class_name = Mapped_UI::retrieve_class_name( &typeid(*instance) );
00278
00279
00280 Setting &type = root.add( "class", Setting::TypeString );
00281 type = class_name;
00282
00283 try
00284 {
00285 instance->to_setting( root );
00286 }
00287 catch(SettingException xcptn)
00288 {
00289 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." );
00290 }
00291 }
00292
00294 template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
00295 {
00296 ASSERT_UITYPE(element,TypeGroup);
00297 Setting &list = (name == "") ? element.add( Setting::TypeList )
00298 : element.add( name, Setting::TypeList );
00299 for( int i=0; i<array_to_save.length(); i++ )
00300 save( array_to_save(i), list );
00301 }
00302
00303
00305 static void save( const mat &matrix, Setting &element, const string &name = "" );
00306
00308 static void save( const ivec &vec, Setting &element, const string &name = "" );
00309
00310 static void save( const vec &vector, Setting &element, const string &name);
00311
00312 private:
00314 static void save( const string &str, Setting &element);
00315
00316 };
00317
00318
00324 template<typename T> class Particular_UI : private UI
00325 {
00326 public:
00327
00329 Particular_UI<T>( const string &class_name) : UI( class_name, &typeid(T) )
00330 { cout << class_name << endl;
00331 };
00332
00335 static const Particular_UI<T>& ui;
00336
00337 bdmroot* new_instance() const
00338 {
00339 return new T();
00340 }
00341 };
00342
00343
00344
00345
00346 }
00347
00371 #endif // #ifndef USER_INFO_H