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