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
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        // 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
128        //! internal method assembling a typeless instance from components obtained by the 'AssemblyComponentsFromSetting()' method
129        virtual bdmroot* new_instance() const = 0;
130       
131        //! This methods tries to save an instance of type T (or some of its descendant types)
132        //! and build DOM tree accordingly. Then, it creates a new DOMNode named according class_name
133        //! and connecti it to the passed Setting as a new child node.
134        static const Setting& to_child_setting( const Setting &element, const int index );
135
136        static const Setting& to_child_setting( const Setting &element, const string &name );
137
138
139        //! \name Matematical Operations TODO
140        //!@{
141
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
145        static void from_setting( ivec &vector, const Setting &element );
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
150        static void from_setting( vec &vector, const Setting &element );
151
152        template<class T> static void from_setting( T* &instance, const Setting &element )
153        {                       
154                const Link_Expander link_expander( element );
155                const Setting &root = link_expander.root();
156
157                ASSERT_UITYPE(root,TypeGroup);
158
159                // we get a velue stored in the "class" attribute
160                string class_name;
161                if( !root.lookupValue( "class", class_name ) )
162                        ui_error( "the obligatory ""class"" identifier is missing", root );
163       
164                // and finally we find a UserInfo related to this type
165                const UI& related_UI = Mapped_UI::retrieve_ui( class_name );
166               
167                bdmroot* typeless_instance = related_UI.new_instance();
168
169                instance = NULL;
170                try
171                {
172                        instance = (T*) typeless_instance ;
173                }
174                catch(...)
175                {
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." );
177                }
178               
179                try
180                {
181                        instance->from_setting( root );
182                }
183                catch(SettingException xcptn)
184                {
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." );
186                }
187        }       
188
189
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 )
193        {
194                const Link_Expander link_expander( element );
195                const Setting &root = link_expander.root();
196
197                ASSERT_UITYPE(root,TypeList);
198
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] ); 
205        }
206
207          //!@}
208
209
210        static void ui_error( string message, const Setting &element );
211
212protected:
213        //! default constructor
214        UI( const string& class_name, const type_info * const class_type_info ) 
215        {       
216                Mapped_UI::add_class( class_name, class_type_info, this );
217        }
218
219        //! Virtual destructor for future use;
220        virtual ~UI(){};
221
222public: 
223        //! This methods tries to build a new instance of type T (or some of its descendant types)
224        //! according to a data stored in a DOMNode named class_name within a child nodes of the passed element.
225        //! If an error occurs, it returns a NULL pointer.
226
227        //! Prototype of a UI builder. Return value is by the second argument since it type checking via \c dynamic_cast.
228        template<class T> static T* build( const Setting &element, const int index )
229        {
230                T* instance;
231                from_setting<T>( to_child_setting( element, index ) );
232                return instance;
233        }
234
235        template<class T> static T* build( const Setting &element, const string &name )
236        {                       
237                T* instance;
238                from_setting<T>( instance, to_child_setting( element, name ) );
239                return instance;
240        }
241
242        //! This methods tries to build a new double matrix
243        template<class T> static void get( T &instance, const Setting &element, const string &name )
244        {
245                from_setting( instance, to_child_setting( element, name ) );
246        }
247
248        //! This methods tries to build a new double matrix
249        template<class T> static void get( T &instance, const Setting &element, const int index )
250        {
251                from_setting( instance, to_child_setting( element, index ) );
252        }
253
254        //! This methods tries to build a new double matrix
255        template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
256        {
257                from_setting( array_to_load, to_child_setting( element, name ) );
258        }
259
260        //! This methods tries to build a new double matrix
261        template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
262        {
263                from_setting( array_to_load, to_child_setting( element, index ) );
264        }
265
266        template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
267        {
268                Setting &root = (name == "") ? element.add( Setting::TypeGroup )                                                       
269                                                                         : element.add( name, Setting::TypeGroup );             
270
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;
276
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                }       
285        }
286
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 = "" )
289        {
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 );
295        }
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       
304        static void save( const vec &vector, Setting &element, const string &name);
305
306        private: 
307        //! This methods tries to save a double vec
308        static void save( const string &str, Setting &element); 
309
310};
311
312
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).
317*/
318template<typename T> class Particular_UI : private UI
319{
320        public:
321
322        //! default constructor, which is intentionally declared as private
323        Particular_UI<T>( const string &class_name) : UI( class_name, &typeid(T) ) 
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
329        static const Particular_UI<T>& ui;     
330
331        bdmroot* new_instance() const
332        {
333                return new T();
334        }
335};
336
337
338
339
340}
341
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 */
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
359};
360\endcode
361/
362
363*/
364
365#endif // #ifndef USER_INFO_H
Note: See TracBrowser for help on using the browser.