root/bdm/user_info.h @ 363

Revision 363, 10.8 kB (checked in by mido, 15 years ago)

Link_Expander prejmenovan na SettingsResolver?

  • 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#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*/
77class UI
78{
79private:
80        //! static class encalupsating map of names to related UserInfos
81        //!
82        //! The key property of this class is that it initilaized the internal map immediately
83        //! when it is used for a first time.
84        class Mapped_UI
85        {
86        private:
87                //! Type definition of mapping which transforms type names to the related user infors
88                typedef map< const string, const UI* const > String_To_UI_Map;
89
90                //! Type definition of mapping which transforms type names to the related user infors
91                typedef map< const type_info * const, const string > Type_Info_To_String_Map;
92
93                //! immediately initialized instance of type String_To_UI_Map
94                static String_To_UI_Map& mapped_strings();
95
96                //! immediately initialized instance of type String_To_UI_Map
97                static Type_Info_To_String_Map& mapped_type_infos();
98
99        public:
100                //! add a pair key-userinfo into the internal map
101                static void add_class( const string &class_name, const type_info * const class_type_info, const UI* const ui );
102
103                //! search for an userinfo related to the passed key within the internal map
104                static const UI& retrieve_ui( const string &class_name );
105
106                //! search for an userinfo related to the passed key within the internal map
107                static const string& retrieve_class_name( const type_info* const class_type_info );
108        };
109
110
111
112
113        //! internal method assembling a typeless instance from components obtained by the 'AssemblyComponentsFromSetting()' method
114        virtual bdmroot* new_instance() const = 0;
115       
116        //! This methods tries to save an instance of type T (or some of its descendant types)
117        //! and build DOM tree accordingly. Then, it creates a new DOMNode named according class_name
118        //! and connecti it to the passed Setting as a new child node.
119        static const Setting& to_child_setting( const Setting &element, const int index );
120
121        static const Setting& to_child_setting( const Setting &element, const string &name );
122
123
124        //! \name Matematical Operations TODO
125        //!@{
126
127        //! This methods tries to build a new double matrix
128        static void from_setting( mat& matrix, const Setting &element );       
129        //! This methods tries to build a new integer vector
130        static void from_setting( ivec &vector, const Setting &element );
131        // jednak kvuli pretypovani, apak taky proto, ze na string nefunguje link_expander..
132        static void from_setting( string &str, const Setting &element );
133        //! This methods tries to build a new templated array
134
135        static void from_setting( vec &vector, const Setting &element );
136
137        template<class T> static void from_setting( T* &instance, const Setting &element )
138        {                       
139                const SettingsResolver link_expander( element );
140                const Setting &root = link_expander.root();
141
142                ASSERT_UITYPE(root,TypeGroup);
143
144                // we get a velue stored in the "class" attribute
145                string class_name;
146                if( !root.lookupValue( "class", class_name ) )
147                        ui_error( "the obligatory ""class"" identifier is missing", root );
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( root );
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 SettingsResolver link_expander( element );
180                const Setting &root = link_expander.root();
181
182                ASSERT_UITYPE(root,TypeList);
183
184                int len = root.getLength();
185                array_to_load.set_length( len );
186                if( len == 0 ) return;
187               
188                for( int i=0; i < len; i++ ) 
189                        from_setting( array_to_load(i), root[i] ); 
190        }
191
192          //!@}
193
194
195        static void ui_error( string message, const Setting &element );
196
197protected:
198        //! default constructor
199        UI( const string& class_name, const type_info * const class_type_info ) 
200        {       
201                Mapped_UI::add_class( class_name, class_type_info, this );
202        }
203
204        //! Virtual destructor for future use;
205        virtual ~UI(){};
206
207public: 
208        //! This methods tries to build a new instance of type T (or some of its descendant types)
209        //! according to a data stored in a DOMNode named class_name within a child nodes of the passed element.
210        //! If an error occurs, it returns a NULL pointer.
211
212        // vraci true, kdyz to byl platny link, jinak false.. v pripade chyby konci it_errorem..
213        // do elementu vrati setting prislusny po rozbaleni linku, jinak ponecha beze zmeny
214        class SettingsResolver 
215        {
216        private:
217                UI_File *file;
218                const Setting *result;
219
220        public:
221
222                SettingsResolver( const Setting &potential_link );
223               
224                ~SettingsResolver();
225               
226                const Setting& root() const;
227        };
228
229
230
231        //! Prototype of a UI builder. Return value is by the second argument since it type checking via \c dynamic_cast.
232        template<class T> static T* build( const Setting &element, const int index )
233        {
234                T* instance;
235                from_setting<T>( to_child_setting( element, index ) );
236                return instance;
237        }
238
239        template<class T> static T* build( const Setting &element, const string &name )
240        {                       
241                T* instance;
242                from_setting<T>( instance, to_child_setting( element, name ) );
243                return instance;
244        }
245
246        //! This methods tries to build a new double matrix
247        template<class T> static void get( T &instance, const Setting &element, const string &name )
248        {
249                from_setting( instance, to_child_setting( element, name ) );
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 int index )
254        {
255                from_setting( instance, to_child_setting( element, index ) );
256        }
257
258        //! This methods tries to build a new double matrix
259        template<class T> static void get( Array<T> &array_to_load, const Setting &element, const string &name )
260        {
261                from_setting( array_to_load, to_child_setting( element, name ) );
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 int index )
266        {
267                from_setting( array_to_load, to_child_setting( element, index ) );
268        }
269
270        template< class T> static void save( const T * const instance, Setting &element, const string &name = "")
271        {
272                Setting &root = (name == "") ? element.add( Setting::TypeGroup )                                                       
273                                                                         : element.add( name, Setting::TypeGroup );             
274
275                const string &class_name = Mapped_UI::retrieve_class_name( &typeid(*instance) );
276                       
277                // add attribute "class"
278                Setting &type = root.add( "class", Setting::TypeString );
279                type = class_name;
280
281                try
282                {
283                        instance->to_setting( root );
284                }
285                catch(SettingException xcptn)
286                {
287                        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." );
288                }       
289        }
290
291        //! This methods tries to save a double vec
292        template<class T> static void save( const Array<T> &array_to_save, Setting &element, const string &name = "" )
293        {
294                ASSERT_UITYPE(element,TypeGroup);
295                Setting &list = (name == "") ? element.add( Setting::TypeList )                                                 
296                                                                         : element.add( name, Setting::TypeList );             
297                for( int i=0; i<array_to_save.length(); i++ ) 
298                        save( array_to_save(i), list );
299        }
300
301
302        //! This methods tries to save a double matrix
303        static void save( const mat &matrix, Setting &element, const string &name = "" );
304
305        //! This methods tries to save a double vec
306        static void save( const ivec &vec, Setting &element, const string &name = "" );
307       
308        static void save( const vec &vector, Setting &element, const string &name);
309
310        private: 
311        //! This methods tries to save a double vec
312        static void save( const string &str, Setting &element); 
313
314};
315
316
317/*!
318@brief The main userinfo template class. You should derive this class whenever you need
319a new userinfo of a class which is compound from smaller elements (all having its
320own userinfo class prepared).
321*/
322template<typename T> class Particular_UI : private UI
323{
324        public:
325
326        //! default constructor, which is intentionally declared as private
327        Particular_UI<T>( const string &class_name) : UI( class_name, &typeid(T) ) 
328        {       
329        };
330
331        //! the only instance of this class (each type T has its own instance)
332        //! which is used as a factory for processing related UI
333        static const Particular_UI<T>& ui;     
334
335        bdmroot* new_instance() const
336        {
337                return new T();
338        }
339};
340
341
342
343
344}
345
346/*! Recursive build of objects defined in the same file
347
348\code
349{type="internal";
350path="system.profile.[0]";    // Path from the root
351};
352\endcode
353 */
354
355
356
357/*! Recursive build of objects defined in external file
358
359\code
360{type="external";
361filename="my_file.cfg";       // name of file from which to read
362path="system.profile.[0]";    // Path in the external file
363};
364\endcode
365/
366
367*/
368
369#endif // #ifndef USER_INFO_H
Note: See TracBrowser for help on using the browser.