root/library/bdm/bdmroot.h @ 870

Revision 870, 8.4 kB (checked in by mido, 14 years ago)

LOG_LEVEL final cut (or rather semifinal? I hope to improve work with ids soon)
and also it rests to adapt applications, work is in progress

  • Property svn:eol-style set to native
Line 
1
2/*!
3  \file
4  \brief Bayesian Models (bm) that use Bayes rule to learn from observations
5  \author Vaclav Smidl.
6
7  -----------------------------------
8  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
9
10  Using IT++ for numerical operations
11  -----------------------------------
12*/
13
14#ifndef root_H
15#define root_H
16
17#include <string>
18#include <bitset>
19
20#include "itpp_ext.h"
21#include "bdmerror.h"
22
23#ifdef MEX
24        #include "base/libconfig/lib/libconfig.h++"     
25        // TODO DODELAT A NAHRADIT #include "base/libconfig_mex.h"
26#else
27        #include "base/libconfig/lib/libconfig.h++"
28#endif
29
30
31using namespace libconfig;
32using namespace itpp;
33using namespace std;
34
35namespace bdm {
36       
37//! auxiliary function for debugging
38void UI_DBG (const Setting &S, const string &spc, ostream &out );
39       
40//! This class stores a details that will be logged to a logger
41template<class T> class log_level_template {
42private:
43        // UserInfo class have to be able to read all the internal
44        // attributes to be able to write/read log_level to/from a Setting structure
45        friend class UI;
46
47        //! boolean flags related indicating which details will be logged to a logger
48        bitset<32> values;
49
50        //! string equivalents of the used enumerations which are filled with a help of #LOG_LEVEL macro within class T
51        const Array<string> &names() const
52        {
53                return T::log_level_names();
54        }
55
56public:
57       
58        //! a general utility transforming a comma-separated sequence of strings into an instance of Array<strings>
59        static Array<string> string2Array( const string &input )
60        {
61                string result = input;
62                string::size_type loc;
63                while( loc = result.find( ',' ), loc != string::npos )
64                        result[loc] = ' ';
65                return Array<string>("{ " + result + " }" );
66        }
67
68        //! is any field of log_level active?
69        bool any() const
70        {
71                return values.any();
72        }
73
74        //! read only operator for testing  individual fields of log_level
75        //!
76        //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe
77        bool operator [] (const enum T::log_level_enums &log_level ) const
78        {
79                return values[log_level];
80        }
81
82        //! operator for setting an individual field of log_level
83        //!
84        //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe
85        bitset<32>::reference operator [] (const enum T::log_level_enums &log_level )
86        {
87                return values[log_level];
88        }
89};
90
91/*!
92  \def LOG_LEVEL(classname,...)
93  \brief Macro for defining a log_level attribute with a specific set of enumerations related to a specific class
94
95  This macro has to be called within a class declaration. Its argument \a classname has to correspond to that wrapping class.
96  This macro defines a log_level instance which can be modified either directly or by the means of #UI class.
97
98  One of the main purposes of this macro is to allow variability in using enumerations. By relating them to their names through
99  an array of strings, we are no more dependant on their precise ordering. What is more, we can add or remove any without harming
100  any applications which are using this library.
101
102  \todo Write a more detailed explanation including also examples
103
104  \ref ui
105*/
106#define LOG_LEVEL(classname,...) public: enum log_level_enums { __VA_ARGS__ }; log_level_template<classname> log_level; private: friend class log_level_template<classname>; static const Array<string> &log_level_names() { static const Array<string> log_level_names = log_level_template<classname>::string2Array( #__VA_ARGS__ ); return log_level_names; }
107
108//forward declaration
109class logger;
110
111//! information about connection to a logger
112class log_record {
113public:
114        //!remember which logger is registered
115        logger &L;
116        //! vector of log IDs - one element for each entry
117        ivec ids;
118
119        //!default constructor
120        log_record ( logger &L0 ) : L ( L0 ), ids ( 0 ) {}
121};
122
123//! Root class of BDM objects
124class root {
125private:
126        //! It is necessary to allow calling of from_setting and to_setting within the UI class ++ i log_options
127        friend class UI;
128
129        //! This method is a dummy method closely related to to the #LOG_LEVEL macro, do not remove it
130        static const string &log_level_names() 
131        { 
132                static const string log_level_names; 
133                return log_level_names; 
134        }; 
135
136protected:
137        //! record of connections to the logger
138        log_record* logrec;
139
140        /*!     
141        \brief Read instance properties according the data stored in the Setting structure.
142        It has to be called only through UI class, therefore it is protected
143
144        At the begining of this method, it is obligatory to call
145        the corresponding base::from_setting method. Sometimes, there can be
146        an exception from this rule. If so, the programmer is encouraged
147        to describe the reasons for this exception in the documentation in detail.
148       
149        Then, all the configuration     components should be read through the UI mechanism.
150        Those with UI::SettingPresence set to optional shoud have their defaults fulfilled
151        within the body of this method.
152
153        For instance, declaring a class \c trunk derived from our #root class,
154        the implementation of the from_setting method should look like this
155
156        \code
157
158        public trunk : public root {
159
160                anytype xxx, yyy;
161
162                virtual void from_setting ( const Setting &set ) {
163                        root::from_setting( set );
164                       
165                        UI::get ( xxx, set, "xxx", UI::compulsory );
166
167                        if ( !UI::get ( yyy, set, "yyy", UI::optional ) ) {
168                                ... // here, it is necessary to set the default of attribute yyy                                               
169                        }
170
171                        ... // another stuff related to trunk class
172                }
173
174                ... // other members of this class
175        };
176
177        \endcode
178        */
179        virtual void from_setting ( const Setting &set ) {
180        }
181
182        /*!     
183        \brief  Save all the instance properties into the Setting structure.
184        It has to be called only through UI class, therefore it is protected
185
186        The only obligatory rule concerning the body of this method is to call
187        the corresponding base::to_setting method first.        Sometimes, there can
188        be an exception from this rule. If so, the programmer is encouraged
189        to describe the reasons for this exception in the documentation in detail.
190       
191        For instance, declaring
192        a class \c trunk derived from our #root class, the implementation of
193        the to_setting method should look like this
194
195        \code
196        public trunk : public root {
197
198                anytype xxx;
199
200                virtual void to_setting ( const Setting &set ) {
201                        root::to_setting( set );
202
203                        UI::save ( xxx, set, "xxx" );
204                       
205                        ... // another stuff related directly to trunk class
206
207                }
208
209                ... // other members of this class
210
211        };
212
213        \endcode
214        */
215        virtual void to_setting ( Setting &set ) const {
216        }
217
218public:
219        //! This enumeration defines all possible options specifing the level of details logged by a logger about this specific class
220        //!
221        //! It has to be reimplemented in descendant classes using the #LOG_LEVEL macro
222        enum log_level_enums { };
223
224        //!default constructor
225        root() : logrec ( NULL ) {};
226
227        //! make sure this is a virtual object
228        virtual ~root() {
229                if ( logrec ) delete logrec;
230        }
231
232        //! Returns basic textual info about the current instance
233        virtual string to_string() const {
234                Config C;
235                Setting &set=C.getRoot();
236                this->to_setting(set);
237                ostringstream os;
238                UI_DBG(set, "", os);
239                return os.str();
240        }
241        //! Register itself in a logger, i.e. allocate space for data from this class
242        //! The level of details (parameter \c level ) is individual for each class.
243        virtual void log_register ( logger &L, const string &prefix ) {
244                logrec = new log_record ( L );
245        }
246
247        //! Write current information into the given logger
248        virtual void log_write() const {
249        }
250
251        /*!     
252        \brief  This method checks that all internal structures has been set up correctly.
253
254        It is called automatically after the call of the #from_setting method by the mechanism of the UI class.
255        However, it can be called in any other situation to assure the correctness of an instance.
256       
257        The only obligatory rule concerning the body of this method is to call
258        the corresponding base::validate method first. Sometimes, there can be
259        an exception from this rule. If so, the programmer is encouraged
260        to describe the reasons for this exception in the documentation in detail.     
261       
262        Then, only those checks which are not implemented in the base method
263        are implemented here. For instance, declaring a class \c trunk derived from our
264        #root class, the implementation of the method validate should
265        look like this
266
267        \code
268        public trunk : public root {
269
270                virtual void validate ( ) {
271                        root::validate( );
272
273                        ... // checks related directly to trunk class
274                }
275
276                ... // other members of this class
277
278        };
279
280        \endcode
281
282        */
283        virtual void validate() {
284        }
285
286        //! Virtual method providing deep copy of instances
287        virtual root* _copy() const NOT_IMPLEMENTED(NULL);
288       
289};
290
291}; //namespace
292#endif // root_H
Note: See TracBrowser for help on using the browser.