root/library/bdm/base/user_info.h @ 390

Revision 390, 11.1 kB (checked in by mido, 15 years ago)

class bdmroot renamed to root, ui matrix patched (possibility of a "matrix" string at first place of the matrix list was allowed)

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