root/bdm/user_info.h @ 358

Revision 358, 10.9 kB (checked in by smidl, 15 years ago)

compilation fixes for Linux

  • 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#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
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
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.
90        class Mapped_UI
91        {
92        private:
93                //! Type definition of mapping which transforms type names to the related user infors
94                typedef map< const string, const UI* const > String_To_UI_Map;
95
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;
98
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
105        public:
106                //! add a pair key-userinfo into the internal map
107                static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
108
109                //! search for an userinfo related to the passed key within the internal map
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 );
114        };
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
134        //! internal method assembling a typeless instance from components obtained by the 'AssemblyComponentsFromSetting()' method
135        virtual bdmroot* new_instance() const = 0;
136       
137        //! This methods tries to save an instance of type T (or some of its descendant types)
138        //! and build DOM tree accordingly. Then, it creates a new DOMNode named according class_name
139        //! and connecti it to the passed Setting as a new child node.
140        static const Setting& to_child_setting( const Setting &element, const int index );
141
142        static const Setting& to_child_setting( const Setting &element, const string &name );
143
144
145        //! This methods tries to build a new double matrix
146        static void from_setting( mat& matrix, const Setting &element );       
147        //! This methods tries to build a new integer vector
148        static void from_setting( ivec &vector, const Setting &element );
149        // jednak kvuli pretypovani, apak taky proto, ze na string nefunguje link_expander..
150        static void from_setting( string &str, const Setting &element );
151        //! This methods tries to build a new templated array
152
153        static void from_setting( vec &vector, const Setting &element );
154
155        template<class T> static void from_setting( T* &instance, const Setting &element )
156        {                       
157                const Link_Expander link_expander( element );
158                const Setting &root = link_expander.root();
159
160                ASSERT_UITYPE(root,TypeGroup);
161
162                // we get a velue stored in the "class" attribute
163                string class_name;
164                if( !root.lookupValue( "class", class_name ) )
165                        ui_error( "the obligatory ""class"" identifier is missing", root );
166       
167                // and finally we find a UserInfo related to this type
168                const UI& related_UI = Mapped_UI::retrieve_ui( class_name );
169               
170                bdmroot* typeless_instance = related_UI.new_instance();
171
172                instance = NULL;
173                try
174                {
175                        instance = (T*) typeless_instance ;
176                }
177                catch(...)
178                {
179                        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." );
180                }
181               
182                try
183                {
184                        instance->from_setting( root );
185                }
186                catch(SettingException xcptn)
187                {
188                        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." );
189                }
190        }       
191
192
193        //! This methods tries to build a new templated array ,
194        // efektivne jen pro vect, mat a string, pro dalsi je nutne pridat from_setting metodu.. ale to asi necceme
195        template<class T> static void from_setting( Array<T> &array_to_load, const Setting &element )
196        {
197                const Link_Expander link_expander( element );
198                const Setting &root = link_expander.root();
199
200                ASSERT_UITYPE(root,TypeList);
201
202                int len = root.getLength();
203                array_to_load.set_length( len );
204                if( len == 0 ) return;
205               
206                for( int i=0; i < len; i++ ) 
207                        from_setting( array_to_load(i), root[i] ); 
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.