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

Revision 392, 11.4 kB (checked in by smidl, 15 years ago)

compilation fixes - UI_build use exceptions now!!!!

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