root/bdm/user_info.h @ 359

Revision 359, 10.9 kB (checked in by mido, 15 years ago)

patch buildu ve windows, nyni je pod winxp/vs9.0 vse v cajku

  • 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
[358]18#ifdef BDMLIB
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
77/*!\brief Builds computational object from a UserInfo structure
78
79Return value is a pointer to the created object (memory management issue?)
80/
81
82*/
83class UI
84{
85private:
86        //! static class encalupsating map of names to related UserInfos
87        //!
88        //! The key property of this class is that it initilaized the internal map immediately
89        //! when it is used for a first time.
[351]90        class Mapped_UI
[344]91        {
92        private:
93                //! Type definition of mapping which transforms type names to the related user infors
[351]94                typedef map< const string, const UI* const > String_To_UI_Map;
[344]95
[351]96                //! Type definition of mapping which transforms type names to the related user infors
97                typedef map< const type_info * const, const string > Type_Info_To_String_Map;
[344]98
[351]99                //! immediately initialized instance of type String_To_UI_Map
100                static String_To_UI_Map& mapped_strings();
101
102                //! immediately initialized instance of type String_To_UI_Map
103                static Type_Info_To_String_Map& mapped_type_infos();
104
[344]105        public:
106                //! add a pair key-userinfo into the internal map
[351]107                static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
[344]108
109                //! search for an userinfo related to the passed key within the internal map
[351]110                static const UI& retrieve_ui( const string &class_name );
111
112                //! search for an userinfo related to the passed key within the internal map
113                static const string& retrieve_class_name( const type_info* const class_type_info );
[344]114        };
[351]115
116        // vraci true, kdyz to byl platny link, jinak false.. v pripade chyby konci it_errorem..
117        // do elementu vrati setting prislusny po rozbaleni linku, jinak ponecha beze zmeny
118        class Link_Expander     
119        {
120        private:
121                UI_File *file;
122                const Setting *result;
123
124        public:
125
126                Link_Expander( const Setting &potential_link );
127               
128                ~Link_Expander();
129               
130                const Setting& root() const;
131        };
132
133
[344]134        //! internal method assembling a typeless instance from components obtained by the 'AssemblyComponentsFromSetting()' method
[351]135        virtual bdmroot* new_instance() const = 0;
[344]136       
137        //! This methods tries to save an instance of type T (or some of its descendant types)
[345]138        //! and build DOM tree accordingly. Then, it creates a new DOMNode named according class_name
[344]139        //! and connecti it to the passed Setting as a new child node.
[357]140        static const Setting& to_child_setting( const Setting &element, const int index );
[246]141
[357]142        static const Setting& to_child_setting( const Setting &element, const string &name );
[351]143
144
[359]145        //! \name Matematical Operations TODO
146        //!@{
147
[351]148        //! This methods tries to build a new double matrix
149        static void from_setting( mat& matrix, const Setting &element );       
150        //! This methods tries to build a new integer vector
[357]151        static void from_setting( ivec &vector, const Setting &element );
[351]152        // jednak kvuli pretypovani, apak taky proto, ze na string nefunguje link_expander..
153        static void from_setting( string &str, const Setting &element );
154        //! This methods tries to build a new templated array
155
[357]156        static void from_setting( vec &vector, const Setting &element );
157
[351]158        template<class T> static void from_setting( T* &instance, const Setting &element )
[344]159        {                       
[345]160                const Link_Expander link_expander( element );
161                const Setting &root = link_expander.root();
[246]162
[344]163                ASSERT_UITYPE(root,TypeGroup);
164
165                // we get a velue stored in the "class" attribute
[345]166                string class_name;
167                if( !root.lookupValue( "class", class_name ) )
168                        ui_error( "the obligatory ""class"" identifier is missing", root );
[344]169       
170                // and finally we find a UserInfo related to this type
[351]171                const UI& related_UI = Mapped_UI::retrieve_ui( class_name );
[344]172               
[351]173                bdmroot* typeless_instance = related_UI.new_instance();
[344]174
[351]175                instance = NULL;
[344]176                try
177                {
[351]178                        instance = (T*) typeless_instance ;
[344]179                }
180                catch(...)
181                {
[345]182                        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]183                }
184               
185                try
186                {
[351]187                        instance->from_setting( root );
[344]188                }
189                catch(SettingException xcptn)
190                {
[345]191                        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]192                }
193        }       
194
195
[351]196        //! This methods tries to build a new templated array ,
197        // efektivne jen pro vect, mat a string, pro dalsi je nutne pridat from_setting metodu.. ale to asi necceme
198        template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
[344]199        {
[345]200                const Link_Expander link_expander( element );
201                const Setting &root = link_expander.root();
202
[351]203                ASSERT_UITYPE(root,TypeList);
[344]204
[351]205                int len = root.getLength();
206                array_to_load.set_length( len );
207                if( len == 0 ) return;
208               
209                for( int i=0; i < len; i++ ) 
210                        from_setting( array_to_load(i), root[i] ); 
[281]211        }
[243]212
[359]213          //!@}
214
215
[357]216        static void ui_error( string message, const Setting &element );
217
[345]218protected:
219        //! default constructor
[351]220        UI( const string& class_name, const type_info * const class_type_info ) 
[345]221        {       
[351]222                Mapped_UI::add_class( class_name, class_type_info, this );
[345]223        }
224
225        //! Virtual destructor for future use;
226        virtual ~UI(){};
227
[351]228public: 
[344]229        //! This methods tries to build a new instance of type T (or some of its descendant types)
[345]230        //! according to a data stored in a DOMNode named class_name within a child nodes of the passed element.
[357]231        //! If an error occurs, it returns a NULL pointer.
[281]232
[344]233        //! Prototype of a UI builder. Return value is by the second argument since it type checking via \c dynamic_cast.
[351]234        template<class T> static T* build( const Setting &element, const int index )
[344]235        {
[351]236                T* instance;
[357]237                from_setting<T>( to_child_setting( element, index ) );
[351]238                return instance;
[344]239        }
[281]240
[351]241        template<class T> static T* build( const Setting &element, const string &name )
[344]242        {                       
[351]243                T* instance;
[357]244                from_setting<T>( instance, to_child_setting( element, name ) );
[351]245                return instance;
[344]246        }
[281]247
[344]248        //! This methods tries to build a new double matrix
[357]249        template<class T> static void get( T &instance, const Setting &element, const string &name )
[344]250        {
[357]251                from_setting( instance, to_child_setting( element, name ) );
[344]252        }
253
254        //! This methods tries to build a new double matrix
[357]255        template<class T> static void get( T &instance, const Setting &element, const int index )
[344]256        {
[357]257                from_setting( instance, to_child_setting( element, index ) );
[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 string &name )
[344]262        {
[357]263                from_setting( array_to_load, to_child_setting( element, name ) );
[344]264        }
265
[351]266        //! This methods tries to build a new double matrix
[357]267        template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
[344]268        {
[357]269                from_setting( array_to_load, to_child_setting( element, index ) );
[344]270        }
271
[351]272        template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
[344]273        {
[351]274                Setting &root = (name == "") ? element.add( Setting::TypeGroup )                                                       
275                                                                         : element.add( name, Setting::TypeGroup );             
[344]276
[351]277                const string &class_name = Mapped_UI::retrieve_class_name( &typeid(*instance) );
278                       
279                // add attribute "class"
280                Setting &type = root.add( "class", Setting::TypeString );
281                type = class_name;
[344]282
[351]283                try
284                {
285                        instance->to_setting( root );
286                }
287                catch(SettingException xcptn)
288                {
289                        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." );
290                }       
[344]291        }
292
[351]293        //! This methods tries to save a double vec
294        template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
[344]295        {
[351]296                ASSERT_UITYPE(element,TypeGroup);
297                Setting &list = (name == "") ? element.add( Setting::TypeList )                                                 
298                                                                         : element.add( name, Setting::TypeList );             
299                for( int i=0; i<array_to_save.length(); i++ ) 
300                        save( array_to_save(i), list );
[344]301        }
[351]302
303
304        //! This methods tries to save a double matrix
305        static void save( const mat &matrix, Setting &element, const string &name = "" );
306
307        //! This methods tries to save a double vec
308        static void save( const ivec &vec, Setting &element, const string &name = "" );
309       
[357]310        static void save( const vec &vector, Setting &element, const string &name);
311
[351]312        private: 
313        //! This methods tries to save a double vec
314        static void save( const string &str, Setting &element); 
315
[281]316};
317
318
[344]319/*!
320@brief The main userinfo template class. You should derive this class whenever you need
321a new userinfo of a class which is compound from smaller elements (all having its
322own userinfo class prepared).
[281]323*/
[345]324template<typename T> class Particular_UI : private UI
[344]325{
[358]326        public:
[344]327
328        //! default constructor, which is intentionally declared as private
[351]329        Particular_UI<T>( const string &class_name) : UI( class_name, &typeid(T) ) 
[344]330        {       
331        };
332
333        //! the only instance of this class (each type T has its own instance)
334        //! which is used as a factory for processing related UI
[358]335        static const Particular_UI<T>& ui;     
[344]336
[351]337        bdmroot* new_instance() const
[344]338        {
339                return new T();
340        }
[281]341};
342
[344]343
[351]344
345
[344]346}
347
[281]348/*! Recursive build of objects defined in the same file
349
350\code
351{type="internal";
352path="system.profile.[0]";    // Path from the root
353};
354\endcode
355 */
[344]356
357
358
359/*! Recursive build of objects defined in external file
360
361\code
362{type="external";
363filename="my_file.cfg";       // name of file from which to read
364path="system.profile.[0]";    // Path in the external file
[281]365};
[344]366\endcode
367/
[281]368
[344]369*/
370
[358]371#endif // #ifndef USER_INFO_H
Note: See TracBrowser for help on using the browser.