]> Creatis software - crea.git/blob - src/creaMessageManager.h
9fbaae5be932bca8f282d99d4422039481da9c90
[crea.git] / src / creaMessageManager.h
1 /*! \file
2   \brief Class creaMessageManager and Macros for outputing messages in crea
3   There are 4 kinds of messages :
4   - Messages (normal messages)
5   - Debug messages (not compiled in release)
6   - Warnings 
7   - Errors
8   There are also "types" of messages which are strings which identify the nature of the message 
9   (for example : "Kernel" messages are generated by the core classes of the library, there can be a type of 
10   message for each type of Node, and so on...)
11   A type of message must be declared by registering it into the MessageManager. This is done by a line like :
12   crea::MessageManager::RegisterMessageType("Kernel","Messages generated by the core classes of the library",5);
13   where : 
14   -The first string is the type of the message (the category which will be used to generate a message of this type)
15   -The second string is help string
16   -The integer is the initial level for the messages of this type (see below).
17   To generate a message of a known type then use one of the macros :
18   creaMessage, creaDebugMessage, creaWarning, creaError or their variants.
19   example :
20   creaMessage("Kernel",4,"problem with "<<GetName()<<creaendl);
21   will push the 3rd argument in std::cout if the message level of "Kernel" messages is greater or equal to 4.
22   which means that it generates a message of level 4 (0 : very important/always displayed ... 9 : deep debug message).
23   At run time, one is able to change the level of the messages displayed by using a command like :
24   crea::MessageManager::SetMessageLevel("Kernel",5); 
25   which tells the manager to display all Kernel messages of level up to 5.
26   Variants :
27   crea*Cont : continues a previous creaMessage on the same line (without rewriting the type and level)
28   crea*Inc / Dec : displays the message and then increments/decrement the messages tabulation 
29 */
30
31   //===========================================================
32   /**
33      \class crea::MessageManager
34      \brief Manages the messages displayed by crea
35   */
36
37 #ifndef __creaMessageManager_h__
38 #define __creaMessageManager_h__
39
40 // The do { } while(0) statement in macros is made to "swallow the semicolon" 
41 // see http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html#Swallowing-the-Semicolon
42 #include "creaSystem.h"
43 #include "creaRTTI.h" // for CREA_GET_CURRENT_OBJECT_NAME
44 // Signal/slot mechanism for message events
45 #include <boost/signal.hpp>
46 #include <boost/bind.hpp>
47 #include <string>
48 #include <map>
49 #include <iostream>
50 #include <sstream>
51 // Comment out these symbols to prevent compilation 
52 //#define CREA_COMPILE_MESSAGES
53 //#define CREA_COMPILE_DEBUG_MESSAGES
54 //#define CREA_COMPILE_WARNING_MESSAGES
55 //#define CREA_COMPILE_ERROR_MESSAGES
56 #define creaOnMessageLevel(key,value)                   \
57   int __creaOnMessageLevelVariable =                    \
58     crea::MessageManager::GetMessageLevel(key);         \
59   if ( __creaOnMessageLevelVariable<0)                  \
60     {                                                   \
61       creaWarning("message type '"<<key<<"' unknown");  \
62     }                                                   \
63   else if (value<= __creaOnMessageLevelVariable) 
64
65 #ifdef CREA_PREPEND_MESSAGE_WITH_CODE
66 #define creaMessageCode                         \
67   key[0] << key[1] << key[2] << value << " "
68 #else 
69 #define creaMessageCode ""
70 #endif 
71
72 #ifdef CREA_PREPEND_MESSAGE_WITH_TAB
73 #define creaMessageTab                          \
74   crea::MessageManager::GetTab()
75 #else 
76 #define creaMessageTab ""
77 #endif
78
79 //#define CREA_PREPEND_MESSAGE_WITH_SPACE
80 #ifdef CREA_PREPEND_MESSAGE_WITH_SPACE
81 #define creaMessageSpace(value)                 \
82   crea::MessageManager::GetSpace(value)
83 #else 
84 #define creaMessageSpace(value) ""
85 #endif
86
87  
88
89
90
91 //===========================================================
92
93 #ifdef CREA_COMPILE_MESSAGES
94
95 // Macro for messages
96 #define creaMessage(key,value,MESSAGE)                  \
97   do {                                                  \
98     creaOnMessageLevel(key,value)                       \
99       {                                                 \
100         std::ostringstream s;                           \
101         s << creaMessageCode                            \
102           << creaMessageTab                             \
103           << creaMessageSpace(value)                    \
104           << MESSAGE;                                   \
105         crea::MessageManager::SendMessage(key,s.str()); \
106       }                                                 \
107   }                                                     \
108   while (0)
109
110
111
112 // Macro for continuing a message (when one wants to split the macro
113 // call into multiple lines)
114 #define creaMessageCont(key,value,MESSAGE)              \
115   do                                                    \
116     {                                                   \
117       creaOnMessageLevel(key,value)                     \
118         {                                               \
119         std::ostringstream s;                           \
120         s << MESSAGE;                                   \
121         crea::MessageManager::SendMessage(key,s.str()); \
122         }                                               \
123     }                                                   \
124   while (0)
125
126
127 #define creaMessageInc(key,value,MESSAGE)               \
128   do                                                    \
129     {                                                   \
130         std::ostringstream s;                           \
131         s << creaMessageCode                            \
132           << creaMessageTab                             \
133           << creaMessageSpace(value)                    \
134           << MESSAGE;                                   \
135         crea::MessageManager::SendMessage(key,s.str()); \
136         crea::MessageManager::IncTab();                 \
137         }                                               \
138     }                                                   \
139   while (0)
140
141
142 #define creaMessageDec(key,value,MESSAGE)                       \
143   do                                                            \
144     {                                                           \
145       creaOnMessageLevel(key,value)                             \
146         {                                                       \
147           crea::MessageManager::DecTab();                       \
148           std::ostringstream s;                                 \
149           s << creaMessageCode                                  \
150             << creaMessageTab                                   \
151             << creaMessageSpace(value)                          \
152             << MESSAGE;                                         \
153           crea::MessageManager::SendMessage(key,s.str());       \
154         }                                                       \
155     }                                                           \
156   while (0)
157
158
159 #define creaDecTab(key,value)                   \
160   do                                            \
161     {                                           \
162       creaOnMessageLevel(key,value)             \
163         {                                       \
164           crea::MessageManager::DecTab();       \
165         }                                       \
166     }                                           \
167   while (0)
168
169
170 #define creaIncTab(key,value)                   \
171   do                                            \
172     {                                           \
173       creaOnMessageLevel(key,value)             \
174         {                                       \
175           crea::MessageManager::IncTab();       \
176         }                                       \
177     }                                           \
178   while (0)
179
180
181 #define creaResetTab()                          \
182   do                                            \
183     {                                           \
184       crea::MessageManager::ResetTab();         \
185     }                                           \
186   while (0)
187
188 #else
189 #define creaMessage(key,value,MESSAGE)
190 #define creaMessageInc(key,value,MESSAGE)
191 #define creaMessageDec(key,value,MESSAGE)
192 #define creaMessageCont(key,value,MESSAGE)
193 #define creaDecTab(key,value)
194 #define creaIncTab(key,value)
195 #define creaResetTab()
196 #endif
197
198 //===========================================================
199
200
201
202
203
204
205
206 //===========================================================
207
208 // Macros for debug messages
209
210 #ifdef CREA_COMPILE_DEBUG_MESSAGES
211
212 #define creaDebugMessage(key,value,MESSAGE) creaMessage(key,value,MESSAGE)
213
214 #define creaDebugMessageCont(key,value,MESSAGE) creaMessageCont(key,value,MESSAGE)
215
216 #define creaDebugMessageInc(key,value,MESSAGE) creaMessageInc(key,value,MESSAGE)  
217
218 #define creaDebugMessageDec(key,value,MESSAGE) creaMessageDec(key,value,MESSAGE)
219
220 #define creaDebugDecTab(key,value) creaDecTab(key,value)
221
222 #define creaDebugIncTab(key,value) creaIncTab(key,value)
223
224 #define creaDebugResetTab() creaResetTab()
225
226 #else
227
228 #define creaDebugMessage(key,value,MESSAGE) 
229
230 #define creaDebugMessageCont(key,value,MESSAGE) 
231
232 #define creaDebugMessageInc(key,value,MESSAGE)
233
234 #define creaDebugMessageDec(key,value,MESSAGE) 
235
236 #define creaDebugDecTab(key,value)
237
238 #define creaDebugIncTab(key,value)
239
240 #endif
241
242 //===========================================================
243
244
245
246 //===========================================================
247
248 #ifdef CREA_COMPILE_WARNING_MESSAGES
249 #define creaWarning(MESSAGE)                                            \
250   do                                                                    \
251     {                                                                   \
252       int lev = crea::MessageManager::GetMessageLevel("warning");       \
253       if (lev >0)                                                       \
254         {                                                               \
255           std::cerr << "!! WARNING !! " << MESSAGE << std::endl;        \
256           if (lev >1)                                                   \
257             {                                                           \
258               std::cerr << "!! WARNING !! In file '"<<__FILE__          \
259                         <<"' ; Line "<<__LINE__<<std::endl;             \
260             }                                                           \
261         }                                                               \
262     }                                                                   \
263   while (0) 
264
265 #else
266 #define creaWarning(MESSAGE) 
267 #endif
268
269 //===========================================================
270
271
272
273
274
275 //===========================================================
276
277 #ifdef CREA_COMPILE_ERROR_MESSAGES
278 //#include "creaWx.h"
279 #define creaError(MESSAGE)                              \
280   do                                                    \
281     {                                                   \
282       std::ostringstream s;                             \
283       s << MESSAGE;                                     \
284       std::ostringstream f;                             \
285       f << __FILE__ << " (l."<<__LINE__<<")";           \
286       crea::Exception e( CREA_GET_CURRENT_OBJECT_NAME,  \
287                         f.str(),                        \
288                         s.str());                       \
289       throw e;                                          \
290     }                                                   \
291   while (0) 
292
293
294
295 #define creaGlobalError(MESSAGE)                                \
296   do                                                    \
297     {                                                   \
298       std::ostringstream s;                             \
299       s << MESSAGE;                                     \
300       std::ostringstream f;                             \
301       f << __FILE__ << " (l."<<__LINE__<<")";           \
302       crea::Exception e( "global scope",                \
303                         f.str(),                        \
304                         s.str());                       \
305       throw e;                                          \
306     }                                                   \
307   while (0) 
308
309
310
311 #define CREA_INTERNAL_ERROR_MESSAGE \
312   "\n\n***********************************************\n**** THIS IS AN INTERNAL ERROR TO crea     ****\n**** Please send a full bug report to :    ****\n****  creatools@creatis.insa-lyon.fr ****\n***********************************************\n\n"
313
314 #define creaInternalError(MESSAGE)                      \
315   do                                                    \
316     {                                                   \
317       std::ostringstream s;                             \
318       s << MESSAGE << CREA_INTERNAL_ERROR_MESSAGE;      \
319       std::ostringstream f;                             \
320       f << __FILE__ << " (l."<<__LINE__<<")";           \
321       crea::Exception e( CREA_GET_CURRENT_OBJECT_NAME,  \
322                          f.str(),                       \
323                          s.str());                      \
324       throw e;                                          \
325     }                                                   \
326   while (0) 
327
328
329
330 #else
331 #define creaError(MESSAGE)
332 #define creaGlobalError(MESSAGE)
333 #define creaInternalError(MESSAGE)
334 #endif
335
336 //===========================================================
337
338
339
340 //===========================================================
341
342 #define creaendl std::endl
343
344 //===========================================================
345
346
347
348
349
350 namespace crea 
351
352 {
353
354   
355
356   class CREA_EXPORT MessageManager
357
358   {
359
360   public:
361
362     //=============================================
363
364     typedef boost::signal<void (const std::string&)>  MessageSignalType;
365
366     typedef MessageSignalType::slot_function_type MessageCallbackType;
367
368     //=============================================
369
370     ///
371
372     MessageManager();
373
374     ///
375
376     ~MessageManager();
377
378     ///
379
380     static MessageManager* GetInstance();
381
382     ///
383
384     static void RegisterMessageType(const std::string& key, 
385
386                                     const std::string& help,
387
388                                     unsigned char default_level = 9);
389
390     ///
391
392     static void SetMessageLevel(const std::string& key, unsigned char level);
393
394     ///
395
396     static int GetMessageLevel(const std::string& key);
397
398     ///  
399
400     static void SendMessage(const std::string& key, const std::string& mess);
401
402     ///
403
404     static void AddMessageObserver(const std::string& key, MessageCallbackType callback );
405
406     ///
407
408     static void SendMessagesToCout(bool v = true);
409
410     ///
411
412     static std::string& GetTab() { static std::string s; return s; }
413
414     ///
415
416     static std::string GetSpace(int n) { 
417
418       std::string s; s.insert(0,"                ",n); return s; }
419
420     ///
421
422     static void IncTab() { GetTab() += std::string(" "); }
423
424     ///
425
426     static void DecTab() { GetTab() = GetTab().substr(0,GetTab().length()-1); }
427
428     ///
429
430     static void ResetTab() { GetTab() = std::string(""); }
431
432     ///
433
434     static void PrintInfo();
435
436     /// 
437
438     
439
440   private:
441
442     struct MessageType
443
444     {
445
446       MessageType(int l, const std::string& h) : Level(l), Help(h) {}
447
448       int Level;
449
450       std::string Help;
451
452       MessageSignalType Signal;
453
454     };
455
456     typedef std::map<std::string,MessageType*> MessageMapType;
457
458     MessageMapType mMessageMap;
459
460     unsigned int mMaxMessageLength;
461
462     bool mSendToCout;
463
464   };
465
466   //===========================================================
467
468   
469
470 }
471
472
473
474 #include "creaException.h"
475
476
477
478 #endif
479