]> Creatis software - bbtk.git/blob - kernel/src/bbtkMessageManager.h
No longer 'Core' messages but 'Kernel' ones
[bbtk.git] / kernel / src / bbtkMessageManager.h
1
2 /*! \file
3  
4   \brief Class bbtkMessageManager and Macros for outputing messages in bbtk
5
6   There are 4 kinds of messages :
7   - Messages (normal messages)
8   - Debug messages (not compiled in release)
9   - Warnings 
10   - Errors
11   There are also "types" of messages which are strings which identify the nature of the message 
12   (for example : "Kernel" messages are generated by the core classes of the library, there can be a type of 
13   message for each type of Node, and so on...)
14   A type of message must be declared by registering it into the MessageManager. This is done by a line like :
15   bbtk::MessageManager::RegisterMessageType("Kernel","Messages generated by the core classes of the library",5);
16   where : 
17   -The first string is the type of the message (the category which will be used to generate a message of this type)
18   -The second string is help string
19   -The integer is the initial level for the messages of this type (see below).
20   
21   To generate a message of a known type then use one of the macros :
22   bbtkMessage, bbtkDebugMessage, bbtkWarning, bbtkError or their variants.
23
24   example :
25
26   bbtkMessage("Kernel",4,"problem with "<<GetName()<<bbtkendl);
27
28   will push the 3rd argument in std::cout if the message level of "Kernel" messages is greater or equal to 4.
29   which means that it generates a message of level 4 (0 : very important/always displayed ... 9 : deep debug message).
30
31   At run time, one is able to change the level of the messages displayed by using a command like :
32   
33   bbtk::MessageManager::SetMessageLevel("Kernel",5); 
34   
35   which tells the manager to display all Kernel messages of level up to 5.
36
37   Variants :
38
39   bbtk*Cont : continues a previous bbtkMessage on the same line (without rewriting the type and level)
40   bbtk*Inc / Dec : displays the message and then increments/decrement the messages tabulation 
41
42 */
43   //===========================================================
44   /**
45      \class bbtk::MessageManager
46      \brief Manages the messages displayed by bbtk
47   */
48
49
50 #ifndef __bbtkMessageManager_h__
51 #define __bbtkMessageManager_h__
52
53 // The do { } while(0) statement in macros is made to "swallow the semicolon" 
54 // see http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html#Swallowing-the-Semicolon
55
56 #include "bbtkSystem.h"
57 #include "bbtkRTTI.h"
58
59 #include <string>
60 #include <map>
61 #include <iostream>
62 #include <sstream>
63
64 // Comment out these symbols to prevent compilation 
65 //#define BBTK_COMPILE_MESSAGES
66 //#define BBTK_COMPILE_DEBUG_MESSAGES
67 //#define BBTK_COMPILE_WARNING_MESSAGES
68 //#define BBTK_COMPILE_ERROR_MESSAGES
69
70
71 #define bbtkOnMessageLevel(key,value)                   \
72   int __bbtkOnMessageLevelVariable =                    \
73     bbtk::MessageManager::GetMessageLevel(key);         \
74   if ( __bbtkOnMessageLevelVariable<0)                  \
75     {                                                   \
76       bbtkWarning("message type '"<<key<<"' unknown");  \
77     }                                                   \
78   else if (value<= __bbtkOnMessageLevelVariable) 
79
80 #ifdef BBTK_PREPEND_MESSAGE_WITH_CODE
81 #define bbtkMessageCode                         \
82   key[0] << key[1] << key[2] << value << " "
83 #else 
84 #define bbtkMessageCode ""
85 #endif 
86
87 #ifdef BBTK_PREPEND_MESSAGE_WITH_TAB
88 #define bbtkMessageTab                          \
89   bbtk::MessageManager::GetTab()
90 #else 
91 #define bbtkMessageTab ""
92 #endif
93
94 #define BBTK_PREPEND_MESSAGE_WITH_SPACE
95 #ifdef BBTK_PREPEND_MESSAGE_WITH_SPACE
96 #define bbtkMessageSpace(value)                 \
97   bbtk::MessageManager::GetSpace(value)
98 #else 
99 #define bbtkMessageSpace(value) ""
100 #endif
101  
102
103 //===========================================================
104 #ifdef BBTK_COMPILE_MESSAGES
105
106 // Macro for messages
107 #define bbtkMessage(key,value,MESSAGE)                  \
108   do {                                                  \
109     bbtkOnMessageLevel(key,value)                       \
110       {                                                 \
111         std::cout << bbtkMessageCode                    \
112                   << bbtkMessageTab                     \
113                   << bbtkMessageSpace(value)            \
114                   << MESSAGE;                           \
115       }                                                 \
116   }                                                     \
117   while (0)
118
119 // Macro for continuing a message (when one wants to split the macro
120 // call into multiple lines)
121 #define bbtkMessageCont(key,value,MESSAGE)      \
122   do                                            \
123     {                                           \
124       bbtkOnMessageLevel(key,value)             \
125         {                                       \
126           std::cout << MESSAGE;                 \
127         }                                       \
128     }                                           \
129   while (0)
130
131 #define bbtkMessageInc(key,value,MESSAGE)               \
132   do                                                    \
133     {                                                   \
134       bbtkOnMessageLevel(key,value)                     \
135         {                                               \
136           std::cout << bbtkMessageCode                  \
137                     << bbtkMessageTab                   \
138                     << bbtkMessageSpace(value)          \
139                     << MESSAGE;                         \
140           bbtk::MessageManager::IncTab();               \
141         }                                               \
142     }                                                   \
143   while (0)
144
145 #define bbtkMessageDec(key,value,MESSAGE)               \
146   do                                                    \
147     {                                                   \
148       bbtkOnMessageLevel(key,value)                     \
149         {                                               \
150           bbtk::MessageManager::DecTab();               \
151           std::cout << bbtkMessageCode                  \
152                     << bbtkMessageTab                   \
153                     << bbtkMessageSpace(value)          \
154                     << MESSAGE;                         \
155         }                                               \
156     }                                                   \
157   while (0)
158
159 #define bbtkDecTab(key,value)                   \
160   do                                            \
161     {                                           \
162       bbtkOnMessageLevel(key,value)             \
163         {                                       \
164           bbtk::MessageManager::DecTab();       \
165         }                                       \
166     }                                           \
167   while (0)
168
169 #define bbtkIncTab(key,value)                   \
170   do                                            \
171     {                                           \
172       bbtkOnMessageLevel(key,value)             \
173         {                                       \
174           bbtk::MessageManager::IncTab();       \
175         }                                       \
176     }                                           \
177   while (0)
178
179 #define bbtkResetTab()                          \
180   do                                            \
181     {                                           \
182       bbtk::MessageManager::ResetTab();         \
183     }                                           \
184   while (0)
185
186 #else
187 #define bbtkMessage(key,value,MESSAGE)
188 #define bbtkMessageInc(key,value,MESSAGE)
189 #define bbtkMessageDec(key,value,MESSAGE)
190 #define bbtkMessageCont(key,value,MESSAGE)
191 #define bbtkDecTab(key,value)
192 #define bbtkIncTab(key,value)
193 #define bbtkResetTab()
194 #endif
195 //===========================================================
196
197
198
199 //===========================================================
200 #ifdef BBTK_COMPILE_DEBUG_MESSAGES
201
202 // Macro for debug messages
203 #define bbtkDebugMessage(key,value,MESSAGE)             \
204   do                                                    \
205     {                                                   \
206       bbtkOnMessageLevel(key,value)                     \
207         {                                               \
208           std::cout << bbtkMessageCode                  \
209                     << bbtkMessageTab                   \
210                     << bbtkMessageSpace(value)          \
211                     << MESSAGE;                         \
212         }                                               \
213     }                                                   \
214   while (0)
215
216 // Macro for continuing a debug message (when one wants to split the
217 // macro call into multiple lines)
218 #define bbtkDebugMessageCont(key,value,MESSAGE) \
219   do                                            \
220     {                                           \
221       bbtkOnMessageLevel(key,value)             \
222         {                                       \
223           std::cout << MESSAGE;                 \
224         }                                       \
225     }                                           \
226   while (0)
227
228 #define bbtkDebugMessageInc(key,value,MESSAGE)          \
229   do                                                    \
230     {                                                   \
231       bbtkOnMessageLevel(key,value)                     \
232         {                                               \
233           std::cout << bbtkMessageCode                  \
234                     << bbtkMessageTab                   \
235                     << bbtkMessageSpace(value)          \
236                     << MESSAGE;                         \
237           bbtk::MessageManager::IncTab();               \
238         }                                               \
239     }                                                   \
240   while (0)
241
242 #define bbtkDebugMessageDec(key,value,MESSAGE)          \
243   do                                                    \
244     {                                                   \
245       bbtkOnMessageLevel(key,value)                     \
246         {                                               \
247           bbtk::MessageManager::DecTab();               \
248           std::cout << bbtkMessageCode                  \
249                     << bbtkMessageTab                   \
250                     << bbtkMessageSpace(value)          \
251                     << MESSAGE;                         \
252         }                                               \
253     }                                                   \
254   while (0)
255
256 #define bbtkDebugDecTab(key,value)              \
257   do                                            \
258     {                                           \
259       bbtkOnMessageLevel(key,value)             \
260         {                                       \
261           bbtk::MessageManager::DecTab();       \
262         }                                       \
263     }                                           \
264   while (0)
265
266 #define bbtkDebugIncTab(key,value)              \
267     do                                          \
268       {                                         \
269         bbtkOnMessageLevel(key,value)           \
270           {                                     \
271             bbtk::MessageManager::IncTab();     \
272           }                                     \
273       }                                         \
274     while (0)
275     
276 #define bbtkDebugResetTab()                     \
277     do                                          \
278       {                                         \
279         bbtk::MessageManager::ResetTab();       \
280       }                                         \
281     while (0)
282
283 #else
284 #define bbtkDebugMessage(key,value,MESSAGE) 
285 #define bbtkDebugMessageCont(key,value,MESSAGE) 
286 #define bbtkDebugMessageInc(key,value,MESSAGE)
287 #define bbtkDebugMessageDec(key,value,MESSAGE) 
288 #define bbtkDebugDecTab(key,value)
289 #define bbtkDebugIncTab(key,value)
290 #endif
291 //===========================================================
292
293 //===========================================================
294 #ifdef BBTK_COMPILE_WARNING_MESSAGES
295 #define bbtkWarning(MESSAGE)                                            \
296   do                                                                    \
297     {                                                                   \
298       int lev = bbtk::MessageManager::GetMessageLevel("Warning");       \
299       if (lev >0)                                                       \
300         {                                                               \
301           std::cerr << "!! WARNING !! " << MESSAGE << std::endl;        \
302           if (lev >1)                                                   \
303             {                                                           \
304               std::cerr << "!! WARNING !! In file '"<<__FILE__          \
305                         <<"' ; Line "<<__LINE__<<std::endl;             \
306             }                                                           \
307         }                                                               \
308     }                                                                   \
309   while (0) 
310
311 #else
312 #define bbtkWarning(MESSAGE) 
313 #endif
314 //===========================================================
315
316
317 //===========================================================
318 #ifdef BBTK_COMPILE_ERROR_MESSAGES
319 #include "bbtkWx.h"
320 #define bbtkError(MESSAGE)                              \
321   do                                                    \
322     {                                                   \
323       bbtk::wx::ResetCursor();                          \
324       std::ostringstream s;                             \
325       s << MESSAGE;                                     \
326       std::ostringstream f;                             \
327       f << __FILE__ << " (l."<<__LINE__<<")";           \
328       bbtk::Exception e( BBTK_GET_CURRENT_OBJECT_NAME,  \
329                         f.str(),                        \
330                         s.str());                       \
331       throw e;                                          \
332     }                                                   \
333   while (0) 
334
335 #define bbtkGlobalError(MESSAGE)                                \
336   do                                                    \
337     {                                                   \
338       std::ostringstream s;                             \
339       s << MESSAGE;                                     \
340       std::ostringstream f;                             \
341       f << __FILE__ << " (l."<<__LINE__<<")";           \
342       bbtk::Exception e( "global scope",                \
343                         f.str(),                        \
344                         s.str());                       \
345       throw e;                                          \
346     }                                                   \
347   while (0) 
348
349 #define BBTK_INTERNAL_ERROR_MESSAGE \
350   "\n\n***********************************************\n**** THIS IS AN INTERNAL ERROR TO BBTK     ****\n**** Please send a full bug report to :    ****\n****  bbtk-developers@creatis.insa-lyon.fr ****\n***********************************************\n\n"
351
352 #define bbtkInternalError(MESSAGE)                      \
353   do                                                    \
354     {                                                   \
355       std::ostringstream s;                             \
356       s << MESSAGE << BBTK_INTERNAL_ERROR_MESSAGE;      \
357       std::ostringstream f;                             \
358       f << __FILE__ << " (l."<<__LINE__<<")";           \
359       bbtk::Exception e( BBTK_GET_CURRENT_OBJECT_NAME,  \
360                          f.str(),                       \
361                          s.str());                      \
362       throw e;                                          \
363     }                                                   \
364   while (0) 
365
366 #else
367 #define bbtkError(MESSAGE)
368 #define bbtkGlobalError(MESSAGE)
369 #define bbtkInternalError(MESSAGE)
370 #endif
371 //===========================================================
372
373 //===========================================================
374 #define bbtkendl std::endl
375 //===========================================================
376
377
378 namespace bbtk 
379 {
380
381   class BBTK_EXPORT MessageManager
382   {
383   public:
384     ///
385     MessageManager();
386     ///
387     ~MessageManager();
388     ///
389     static MessageManager* GetInstance();
390     ///
391     static void RegisterMessageType(std::string key, 
392                                     std::string help,
393                                     unsigned char default_level = 9);
394     ///
395     static void SetMessageLevel(std::string key, unsigned char level);
396     ///
397     static int GetMessageLevel(std::string key);
398     ///  
399     static std::string& GetTab() { static std::string s; return s; }
400     ///
401     static std::string GetSpace(int n) { 
402       std::string s; s.insert(0,"                ",n); return s; }
403     ///
404     static void IncTab() { GetTab() += std::string(" "); }
405     ///
406     static void DecTab() { GetTab() = GetTab().substr(0,GetTab().length()-1); }
407     ///
408     static void ResetTab() { GetTab() = std::string(""); }
409     ///
410     static void PrintInfo();
411
412   private:
413     std::map<std::string,int> mMessageLevel;
414     std::map<std::string,std::string> mMessageHelp;  
415     unsigned int mMaxMessageLength;
416     int mAllLevel;
417   };
418   //===========================================================
419   
420 }
421
422 #include "bbtkException.h"
423
424 #endif