root/bdm/user_info.h @ 361

Revision 361, 10.8 kB (checked in by smidl, 15 years ago)
  • Property svn:eol-style set to native
RevLine 
[357]1#ifndef USER_INFO_H
2#define USER_INFO_H
[254]3
[344]4#include <stdio.h>
5#include <string>
6#include <typeinfo>
7#include <map>
[243]8
[351]9#include "libconfig/libconfig.h++"
[357]10#include "bdmroot.h"
11#include "itpp/itbase.h"
[351]12
13
[344]14using std::string;
15using namespace std;
[281]16using namespace libconfig;
[246]17
[361]18#ifndef BDMLIB
[358]19#define UIREGISTER(class_name) template<> const Particular_UI<class_name>& Particular_UI<class_name>::ui = Particular_UI<class_name>(#class_name)
20#else
21#define UIREGISTER(class_name)
22#endif
[246]23
[344]24#define ASSERT_UITYPE(S,Type) it_assert_debug(S.getType()==Setting::Type, string("Wrong setting type, see input path \"")+string(S.getPath())+string("\""))
[271]25
[344]26namespace bdm
27{
[351]28class UI_File : public Config
29{
30private:
31        const string file_name;
[246]32
[351]33public:
[357]34        //! create empty object prepared to store Settings
35        UI_File();
36
37        //! creates object and fills it from a file
[351]38        UI_File( const string &file_name );
39
[357]40        //! save UserInfo to the file
41        void save(const string &file_name);
[351]42
43        operator Setting&();
44};
45
[344]46/*!
47@brief This class serves to load and/or save DOMElements into/from files
48stored on a hard-disk.
[246]49
[344]50Firstly, you associate new RootElement instance with some filename during a time of its
51construtcion. Then, you save some object into the new RootElement instance,
52and save it into the file this way:
53\code
54        CAudi audi;
55        RootElement root("cars.xml");
[345]56        UserInfo::save( audi, root, "TT");
57        root.save();
[344]58\endcode
59
60In the other way round, when loading object from a XML file, the appropriate code looks like this:
61\code
62        RootElement root("cars.xml");
[345]63        root.load();
64        UserInfo::build<T>(root,"TT");
[344]65\endcode
66*/
67
68
69/*!
[345]70@brief UserInfo is an abstract is for internal purposes only. Use CompoundUserInfo<T> or Particular_UI<T> instead.
[344]71The raison d'etre of this class is to allow pointers to its templated descendants.
72
73Also, the main functions of the whole UserInfo library are included within this class, see
[345]74static methods 'build' and 'save'.
[344]75
76*/
77class UI
78{
79private:
80        //! static class encalupsating map of names to related UserInfos
81        //!
82        //! The key property of this class is that it initilaized the internal map immediately
83        //! when it is used for a first time.
[351]84        class Mapped_UI
[344]85        {
86        private:
87                //! Type definition of mapping which transforms type names to the related user infors
[351]88                typedef map< const string, const UI* const > String_To_UI_Map;
[344]89
[351]90                //! Type definition of mapping which transforms type names to the related user infors
91                typedef map< const type_info * const, const string > Type_Info_To_String_Map;
[344]92
[351]93                //! immediately initialized instance of type String_To_UI_Map
94                static String_To_UI_Map& mapped_strings();
95
96                //! immediately initialized instance of type String_To_UI_Map
97                static Type_Info_To_String_Map& mapped_type_infos();
98
[344]99        public:
100                //! add a pair key-userinfo into the internal map
[351]101                static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
[344]102
103                //! search for an userinfo related to the passed key within the internal map
[351]104                static const UI& retrieve_ui( const string &class_name );
105
106                //! search for an userinfo related to the passed key within the internal map
107                static const string& retrieve_class_name( const type_info* const class_type_info );
[344]108        };
[351]109
110        // vraci true, kdyz to byl platny link, jinak false.. v pripade chyby konci it_errorem..
111        // do elementu vrati setting prislusny po rozbaleni linku, jinak ponecha beze zmeny
112        class Link_Expander     
113        {
114        private:
115                UI_File *file;
116                const Setting *result;
117
118        public:
119
120                Link_Expander( const Setting &potential_link );
121               
122                ~Link_Expander();
123               
124                const Setting& root() const;
125        };
126
127
[344]128        //! internal method assembling a typeless instance from components obtained by the 'AssemblyComponentsFromSetting()' method
[351]129        virtual bdmroot* new_instance() const = 0;
[344]130       
131        //! This methods tries to save an instance of type T (or some of its descendant types)
[345]132        //! and build DOM tree accordingly. Then, it creates a new DOMNode named according class_name
[344]133        //! and connecti it to the passed Setting as a new child node.
[357]134        static const Setting& to_child_setting( const Setting &element, const int index );
[246]135
[357]136        static const Setting& to_child_setting( const Setting &element, const string &name );
[351]137
138
[359]139        //! \name Matematical Operations TODO
140        //!@{
141
[351]142        //! This methods tries to build a new double matrix
143        static void from_setting( mat& matrix, const Setting &element );       
144        //! This methods tries to build a new integer vector
[357]145        static void from_setting( ivec &vector, const Setting &element );
[351]146        // jednak kvuli pretypovani, apak taky proto, ze na string nefunguje link_expander..
147        static void from_setting( string &str, const Setting &element );
148        //! This methods tries to build a new templated array
149
[357]150        static void from_setting( vec &vector, const Setting &element );
151
[351]152        template<class T> static void from_setting( T* &instance, const Setting &element )
[344]153        {                       
[345]154                const Link_Expander link_expander( element );
155                const Setting &root = link_expander.root();
[246]156
[344]157                ASSERT_UITYPE(root,TypeGroup);
158
159                // we get a velue stored in the "class" attribute
[345]160                string class_name;
161                if( !root.lookupValue( "class", class_name ) )
162                        ui_error( "the obligatory ""class"" identifier is missing", root );
[344]163       
164                // and finally we find a UserInfo related to this type
[351]165                const UI& related_UI = Mapped_UI::retrieve_ui( class_name );
[344]166               
[351]167                bdmroot* typeless_instance = related_UI.new_instance();
[344]168
[351]169                instance = NULL;
[344]170                try
171                {
[351]172                        instance = (T*) typeless_instance ;
[344]173                }
174                catch(...)
175                {
[345]176                        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." );
[344]177                }
178               
179                try
180                {
[351]181                        instance->from_setting( root );
[344]182                }
183                catch(SettingException xcptn)
184                {
[345]185                        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." );
[344]186                }
187        }       
188
189
[351]190        //! This methods tries to build a new templated array ,
191        // efektivne jen pro vect, mat a string, pro dalsi je nutne pridat from_setting metodu.. ale to asi necceme
192        template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
[344]193        {
[345]194                const Link_Expander link_expander( element );
195                const Setting &root = link_expander.root();
196
[351]197                ASSERT_UITYPE(root,TypeList);
[344]198
[351]199                int len = root.getLength();
200                array_to_load.set_length( len );
201                if( len == 0 ) return;
202               
203                for( int i=0; i < len; i++ ) 
204                        from_setting( array_to_load(i), root[i] ); 
[281]205        }
[243]206
[359]207          //!@}
208
209
[357]210        static void ui_error( string message, const Setting &element );
211
[345]212protected:
213        //! default constructor
[351]214        UI( const string& class_name, const type_info * const class_type_info ) 
[345]215        {       
[351]216                Mapped_UI::add_class( class_name, class_type_info, this );
[345]217        }
218
219        //! Virtual destructor for future use;
220        virtual ~UI(){};
221
[351]222public: 
[344]223        //! This methods tries to build a new instance of type T (or some of its descendant types)
[345]224        //! according to a data stored in a DOMNode named class_name within a child nodes of the passed element.
[357]225        //! If an error occurs, it returns a NULL pointer.
[281]226
[344]227        //! Prototype of a UI builder. Return value is by the second argument since it type checking via \c dynamic_cast.
[351]228        template<class T> static T* build( const Setting &element, const int index )
[344]229        {
[351]230                T* instance;
[357]231                from_setting<T>( to_child_setting( element, index ) );
[351]232                return instance;
[344]233        }
[281]234
[351]235        template<class T> static T* build( const Setting &element, const string &name )
[344]236        {                       
[351]237                T* instance;
[357]238                from_setting<T>( instance, to_child_setting( element, name ) );
[351]239                return instance;
[344]240        }
[281]241
[344]242        //! This methods tries to build a new double matrix
[357]243        template<class T> static void get( T &instance, const Setting &element, const string &name )
[344]244        {
[357]245                from_setting( instance, to_child_setting( element, name ) );
[344]246        }
247
248        //! This methods tries to build a new double matrix
[357]249        template<class T> static void get( T &instance, const Setting &element, const int index )
[344]250        {
[357]251                from_setting( instance, to_child_setting( element, index ) );
[344]252        }
253
[351]254        //! This methods tries to build a new double matrix
[357]255        template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
[344]256        {
[357]257                from_setting( array_to_load, to_child_setting( element, name ) );
[344]258        }
259
[351]260        //! This methods tries to build a new double matrix
[357]261        template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
[344]262        {
[357]263                from_setting( array_to_load, to_child_setting( element, index ) );
[344]264        }
265
[351]266        template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
[344]267        {
[351]268                Setting &root = (name == "") ? element.add( Setting::TypeGroup )                                                       
269                                                                         : element.add( name, Setting::TypeGroup );             
[344]270
[351]271                const string &class_name = Mapped_UI::retrieve_class_name( &typeid(*instance) );
272                       
273                // add attribute "class"
274                Setting &type = root.add( "class", Setting::TypeString );
275                type = class_name;
[344]276
[351]277                try
278                {
279                        instance->to_setting( root );
280                }
281                catch(SettingException xcptn)
282                {
283                        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." );
284                }       
[344]285        }
286
[351]287        //! This methods tries to save a double vec
288        template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
[344]289        {
[351]290                ASSERT_UITYPE(element,TypeGroup);
291                Setting &list = (name == "") ? element.add( Setting::TypeList )                                                 
292                                                                         : element.add( name, Setting::TypeList );             
293                for( int i=0; i<array_to_save.length(); i++ ) 
294                        save( array_to_save(i), list );
[344]295        }
[351]296
297
298        //! This methods tries to save a double matrix
299        static void save( const mat &matrix, Setting &element, const string &name = "" );
300
301        //! This methods tries to save a double vec
302        static void save( const ivec &vec, Setting &element, const string &name = "" );
303       
[357]304        static void save( const vec &vector, Setting &element, const string &name);
305
[351]306        private: 
307        //! This methods tries to save a double vec
308        static void save( const string &str, Setting &element); 
309
[281]310};
311
312
[344]313/*!
314@brief The main userinfo template class. You should derive this class whenever you need
315a new userinfo of a class which is compound from smaller elements (all having its
316own userinfo class prepared).
[281]317*/
[345]318template<typename T> class Particular_UI : private UI
[344]319{
[358]320        public:
[344]321
322        //! default constructor, which is intentionally declared as private
[351]323        Particular_UI<T>( const string &class_name) : UI( class_name, &typeid(T) ) 
[344]324        {       
325        };
326
327        //! the only instance of this class (each type T has its own instance)
328        //! which is used as a factory for processing related UI
[358]329        static const Particular_UI<T>& ui;     
[344]330
[351]331        bdmroot* new_instance() const
[344]332        {
333                return new T();
334        }
[281]335};
336
[344]337
[351]338
339
[344]340}
341
[281]342/*! Recursive build of objects defined in the same file
343
344\code
345{type="internal";
346path="system.profile.[0]";    // Path from the root
347};
348\endcode
349 */
[344]350
351
352
353/*! Recursive build of objects defined in external file
354
355\code
356{type="external";
357filename="my_file.cfg";       // name of file from which to read
358path="system.profile.[0]";    // Path in the external file
[281]359};
[344]360\endcode
361/
[281]362
[344]363*/
364
[358]365#endif // #ifndef USER_INFO_H
Note: See TracBrowser for help on using the browser.