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