root/bdm/user_info.h @ 351

Revision 351, 11.6 kB (checked in by mido, 15 years ago)

par uprav v UI, nikoli finalni verze, presto je zahodno ji ulozit jako zalohu - uz behaji vsechny podstatne funkce vcetne nacitani Array<T>

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