root/bdm/user_info.h @ 377

Revision 377, 10.8 kB (checked in by mido, 15 years ago)

1) globalni prejmenovani Setting &root na Setting &set
2) smazani par zastaralych adresaru
3) oprava warningu v doc\local
4) prejmenovani SettingsResolver? na SettingResolver? a drobne vylepseni funkcnosti
5) odstranena duplikace kodu v user_info.cpp

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