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
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        //! \name Matematical Operations TODO
146        //!@{
147
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
151        static void from_setting( ivec &vector, const Setting &element );
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
156        static void from_setting( vec &vector, const Setting &element );
157
158        template<class T> static void from_setting( T* &instance, const Setting &element )
159        {                       
160                const Link_Expander link_expander( element );
161                const Setting &root = link_expander.root();
162
163                ASSERT_UITYPE(root,TypeGroup);
164
165                // we get a velue stored in the "class" attribute
166                string class_name;
167                if( !root.lookupValue( "class", class_name ) )
168                        ui_error( "the obligatory ""class"" identifier is missing", root );
169       
170                // and finally we find a UserInfo related to this type
171                const UI& related_UI = Mapped_UI::retrieve_ui( class_name );
172               
173                bdmroot* typeless_instance = related_UI.new_instance();
174
175                instance = NULL;
176                try
177                {
178                        instance = (T*) typeless_instance ;
179                }
180                catch(...)
181                {
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." );
183                }
184               
185                try
186                {
187                        instance->from_setting( root );
188                }
189                catch(SettingException xcptn)
190                {
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." );
192                }
193        }       
194
195
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 )
199        {
200                const Link_Expander link_expander( element );
201                const Setting &root = link_expander.root();
202
203                ASSERT_UITYPE(root,TypeList);
204
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] ); 
211        }
212
213          //!@}
214
215
216        static void ui_error( string message, const Setting &element );
217
218protected:
219        //! default constructor
220        UI( const string& class_name, const type_info * const class_type_info ) 
221        {       
222                Mapped_UI::add_class( class_name, class_type_info, this );
223        }
224
225        //! Virtual destructor for future use;
226        virtual ~UI(){};
227
228public: 
229        //! This methods tries to build a new instance of type T (or some of its descendant types)
230        //! according to a data stored in a DOMNode named class_name within a child nodes of the passed element.
231        //! If an error occurs, it returns a NULL pointer.
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        {       
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.