root/bdm/user_info.h @ 364

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

compile fixes

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