root/bdm/user_info.h @ 383

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

mex for merging and fixes in UI

  • 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 bdmroot* 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                bdmroot* 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
238        template<class T> static T* build( const Setting &element, const string &name )
239        {                       
240                T* instance;
241                from_setting<T>( instance, to_child_setting( element, name ) );
242                return instance;
243        }
244
245        //! This methods tries to build a new double matrix
246        template<class T> static void get( T &instance, const Setting &element, const string &name )
247        {
248                from_setting( instance, to_child_setting( element, name ) );
249        }
250
251        //! This methods tries to build a new double matrix
252        template<class T> static void get( T &instance, const Setting &element, const int index )
253        {
254                from_setting( instance, to_child_setting( element, index ) );
255        }
256
257        //! This methods tries to build a new double matrix
258        template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
259        {
260                from_setting( array_to_load, to_child_setting( element, name ) );
261        }
262
263        //! This methods tries to build a new double matrix
264        template<class T> static void get( Array<T> &array_to_load, const Setting &element, const int index )
265        {
266                from_setting( array_to_load, to_child_setting( element, index ) );
267        }
268
269        template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
270        {
271                Setting &set = (name == "") ? element.add( Setting::TypeGroup )                                                 
272                                                                         : element.add( name, Setting::TypeGroup );             
273
274                const string &class_name = Mapped_UI::retrieve_class_name( &typeid(*instance) );
275                       
276                // add attribute "class"
277                Setting &type = set.add( "class", Setting::TypeString );
278                type = class_name;
279
280                try
281                {
282                        instance->to_setting( set );
283                }
284                catch(SettingException xcptn)
285                {
286                        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." );
287                }       
288        }
289
290        //! This methods tries to save a double vec
291        template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
292        {
293                ASSERT_UITYPE(element,TypeGroup);
294                Setting &list = (name == "") ? element.add( Setting::TypeList )                                                 
295                                                                         : element.add( name, Setting::TypeList );             
296                for( int i=0; i<array_to_save.length(); i++ ) 
297                        save( array_to_save(i), list );
298        }
299
300
301        //! This methods tries to save a double matrix
302        static void save( const mat &matrix, Setting &element, const string &name = "" );
303
304        //! This methods tries to save a double vec
305        static void save( const ivec &vec, Setting &element, const string &name = "" );
306       
307        static void save( const vec &vector, Setting &element, const string &name);
308
309        private: 
310        //! This methods tries to save a double vec
311        static void save( const string &str, Setting &element); 
312
313};
314
315
316/*!
317@brief The main userinfo template class. You should derive this class whenever you need
318a new userinfo of a class which is compound from smaller elements (all having its
319own userinfo class prepared).
320*/
321template<typename T> class Particular_UI : private UI
322{
323        public:
324
325        //! default constructor, which is intentionally declared as private
326        Particular_UI<T>( const string &class_name) : UI( class_name, &typeid(T) ) 
327        {       cout << class_name << endl;
328        };
329
330        //! the only instance of this class (each type T has its own instance)
331        //! which is used as a factory for processing related UI
332        static const Particular_UI<T>& ui;     
333
334        bdmroot* new_instance() const
335        {
336                return new T();
337        }
338};
339
340
341
342
343}
344
345/*! Recursive build of objects defined in the same file
346
347\code
348{type="internal";
349path="system.profile.[0]";    // Path from the root
350};
351\endcode
352 */
353
354
355
356/*! Recursive build of objects defined in external file
357
358\code
359{type="external";
360filename="my_file.cfg";       // name of file from which to read
361path="system.profile.[0]";    // Path in the external file
362};
363\endcode
364/
365
366*/
367
368#endif // #ifndef USER_INFO_H
Note: See TracBrowser for help on using the browser.