]> Creatis software - crea.git/blob - src/creaMessageManager.h
*** empty log message ***
[crea.git] / src / creaMessageManager.h
1
2 /*! \file
3  
4   \brief Class creaMessageManager and Macros for outputing messages in crea
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   crea::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   creaMessage, creaDebugMessage, creaWarning, creaError or their variants.
23
24   example :
25
26   creaMessage("Kernel",4,"problem with "<<GetName()<<creaendl);
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   crea::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   crea*Cont : continues a previous creaMessage on the same line (without rewriting the type and level)
40   crea*Inc / Dec : displays the message and then increments/decrement the messages tabulation 
41
42 */
43   //===========================================================
44   /**
45      \class crea::MessageManager
46      \brief Manages the messages displayed by crea
47   */
48
49
50 #ifndef __creaMessageManager_h__
51 #define __creaMessageManager_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 "creaSystem.h"
57 #include "creaRTTI.h" // for CREA_GET_CURRENT_OBJECT_NAME
58 // Signal/slot mechanism for message events
59 #include <boost/signal.hpp>
60 #include <boost/bind.hpp>
61
62 #include <string>
63 #include <map>
64 #include <iostream>
65 #include <sstream>
66
67 // Comment out these symbols to prevent compilation 
68 //#define CREA_COMPILE_MESSAGES
69 //#define CREA_COMPILE_DEBUG_MESSAGES
70 //#define CREA_COMPILE_WARNING_MESSAGES
71 //#define CREA_COMPILE_ERROR_MESSAGES
72
73
74 #define creaOnMessageLevel(key,value)                   \
75   int __creaOnMessageLevelVariable =                    \
76     crea::MessageManager::GetMessageLevel(key);         \
77   if ( __creaOnMessageLevelVariable<0)                  \
78     {                                                   \
79       creaWarning("message type '"<<key<<"' unknown");  \
80     }                                                   \
81   else if (value<= __creaOnMessageLevelVariable) 
82
83 #ifdef CREA_PREPEND_MESSAGE_WITH_CODE
84 #define creaMessageCode                         \
85   key[0] << key[1] << key[2] << value << " "
86 #else 
87 #define creaMessageCode ""
88 #endif 
89
90 #ifdef CREA_PREPEND_MESSAGE_WITH_TAB
91 #define creaMessageTab                          \
92   crea::MessageManager::GetTab()
93 #else 
94 #define creaMessageTab ""
95 #endif
96
97 //#define CREA_PREPEND_MESSAGE_WITH_SPACE
98 #ifdef CREA_PREPEND_MESSAGE_WITH_SPACE
99 #define creaMessageSpace(value)                 \
100   crea::MessageManager::GetSpace(value)
101 #else 
102 #define creaMessageSpace(value) ""
103 #endif
104  
105
106 //===========================================================
107 #ifdef CREA_COMPILE_MESSAGES
108
109 // Macro for messages
110 #define creaMessage(key,value,MESSAGE)                  \
111   do {                                                  \
112     creaOnMessageLevel(key,value)                       \
113       {                                                 \
114         std::ostringstream s;                           \
115         s << creaMessageCode                            \
116           << creaMessageTab                             \
117           << creaMessageSpace(value)                    \
118           << MESSAGE;                                   \
119         crea::MessageManager::SendMessage(key,s.str()); \
120       }                                                 \
121   }                                                     \
122   while (0)
123
124 // Macro for continuing a message (when one wants to split the macro
125 // call into multiple lines)
126 #define creaMessageCont(key,value,MESSAGE)              \
127   do                                                    \
128     {                                                   \
129       creaOnMessageLevel(key,value)                     \
130         {                                               \
131         std::ostringstream s;                           \
132         s << MESSAGE;                                   \
133         crea::MessageManager::SendMessage(key,s.str()); \
134         }                                               \
135     }                                                   \
136   while (0)
137
138 #define creaMessageInc(key,value,MESSAGE)               \
139   do                                                    \
140     {                                                   \
141         std::ostringstream s;                           \
142         s << creaMessageCode                            \
143           << creaMessageTab                             \
144           << creaMessageSpace(value)                    \
145           << MESSAGE;                                   \
146         crea::MessageManager::SendMessage(key,s.str()); \
147         crea::MessageManager::IncTab();                 \
148         }                                               \
149     }                                                   \
150   while (0)
151
152 #define creaMessageDec(key,value,MESSAGE)                       \
153   do                                                            \
154     {                                                           \
155       creaOnMessageLevel(key,value)                             \
156         {                                                       \
157           crea::MessageManager::DecTab();                       \
158           std::ostringstream s;                                 \
159           s << creaMessageCode                                  \
160             << creaMessageTab                                   \
161             << creaMessageSpace(value)                          \
162             << MESSAGE;                                         \
163           crea::MessageManager::SendMessage(key,s.str());       \
164         }                                                       \
165     }                                                           \
166   while (0)
167
168 #define creaDecTab(key,value)                   \
169   do                                            \
170     {                                           \
171       creaOnMessageLevel(key,value)             \
172         {                                       \
173           crea::MessageManager::DecTab();       \
174         }                                       \
175     }                                           \
176   while (0)
177
178 #define creaIncTab(key,value)                   \
179   do                                            \
180     {                                           \
181       creaOnMessageLevel(key,value)             \
182         {                                       \
183           crea::MessageManager::IncTab();       \
184         }                                       \
185     }                                           \
186   while (0)
187
188 #define creaResetTab()                          \
189   do                                            \
190     {                                           \
191       crea::MessageManager::ResetTab();         \
192     }                                           \
193   while (0)
194
195 #else
196 #define creaMessage(key,value,MESSAGE)
197 #define creaMessageInc(key,value,MESSAGE)
198 #define creaMessageDec(key,value,MESSAGE)
199 #define creaMessageCont(key,value,MESSAGE)
200 #define creaDecTab(key,value)
201 #define creaIncTab(key,value)
202 #define creaResetTab()
203 #endif
204 //===========================================================
205
206
207
208 //===========================================================
209 // Macros for debug messages
210 #ifdef CREA_COMPILE_DEBUG_MESSAGES
211 #define creaDebugMessage(key,value,MESSAGE) creaMessage(key,value,MESSAGE)
212 #define creaDebugMessageCont(key,value,MESSAGE) creaMessageCont(key,value,MESSAGE)
213 #define creaDebugMessageInc(key,value,MESSAGE) creaMessageInc(key,value,MESSAGE)  
214 #define creaDebugMessageDec(key,value,MESSAGE) creaMessageDec(key,value,MESSAGE)
215 #define creaDebugDecTab(key,value) creaDecTab(key,value)
216 #define creaDebugIncTab(key,value) creaIncTab(key,value)
217 #define creaDebugResetTab() creaResetTab()
218 #else
219 #define creaDebugMessage(key,value,MESSAGE) 
220 #define creaDebugMessageCont(key,value,MESSAGE) 
221 #define creaDebugMessageInc(key,value,MESSAGE)
222 #define creaDebugMessageDec(key,value,MESSAGE) 
223 #define creaDebugDecTab(key,value)
224 #define creaDebugIncTab(key,value)
225 #endif
226 //===========================================================
227
228 //===========================================================
229 #ifdef CREA_COMPILE_WARNING_MESSAGES
230 #define creaWarning(MESSAGE)                                            \
231   do                                                                    \
232     {                                                                   \
233       int lev = crea::MessageManager::GetMessageLevel("warning");       \
234       if (lev >0)                                                       \
235         {                                                               \
236           std::cerr << "!! WARNING !! " << MESSAGE << std::endl;        \
237           if (lev >1)                                                   \
238             {                                                           \
239               std::cerr << "!! WARNING !! In file '"<<__FILE__          \
240                         <<"' ; Line "<<__LINE__<<std::endl;             \
241             }                                                           \
242         }                                                               \
243     }                                                                   \
244   while (0) 
245
246 #else
247 #define creaWarning(MESSAGE) 
248 #endif
249 //===========================================================
250
251
252 //===========================================================
253 #ifdef CREA_COMPILE_ERROR_MESSAGES
254 //#include "creaWx.h"
255 #define creaError(MESSAGE)                              \
256   do                                                    \
257     {                                                   \
258       std::ostringstream s;                             \
259       s << MESSAGE;                                     \
260       std::ostringstream f;                             \
261       f << __FILE__ << " (l."<<__LINE__<<")";           \
262       crea::Exception e( CREA_GET_CURRENT_OBJECT_NAME,  \
263                         f.str(),                        \
264                         s.str());                       \
265       throw e;                                          \
266     }                                                   \
267   while (0) 
268
269 #define creaGlobalError(MESSAGE)                                \
270   do                                                    \
271     {                                                   \
272       std::ostringstream s;                             \
273       s << MESSAGE;                                     \
274       std::ostringstream f;                             \
275       f << __FILE__ << " (l."<<__LINE__<<")";           \
276       crea::Exception e( "global scope",                \
277                         f.str(),                        \
278                         s.str());                       \
279       throw e;                                          \
280     }                                                   \
281   while (0) 
282
283 #define CREA_INTERNAL_ERROR_MESSAGE \
284   "\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"
285
286 #define creaInternalError(MESSAGE)                      \
287   do                                                    \
288     {                                                   \
289       std::ostringstream s;                             \
290       s << MESSAGE << CREA_INTERNAL_ERROR_MESSAGE;      \
291       std::ostringstream f;                             \
292       f << __FILE__ << " (l."<<__LINE__<<")";           \
293       crea::Exception e( CREA_GET_CURRENT_OBJECT_NAME,  \
294                          f.str(),                       \
295                          s.str());                      \
296       throw e;                                          \
297     }                                                   \
298   while (0) 
299
300 #else
301 #define creaError(MESSAGE)
302 #define creaGlobalError(MESSAGE)
303 #define creaInternalError(MESSAGE)
304 #endif
305 //===========================================================
306
307 //===========================================================
308 #define creaendl std::endl
309 //===========================================================
310
311
312 namespace crea 
313 {
314   
315   class CREA_EXPORT MessageManager
316   {
317   public:
318     //=============================================
319     typedef boost::signal<void (const std::string&)>  MessageSignalType;
320     typedef MessageSignalType::slot_function_type MessageCallbackType;
321     //=============================================
322     ///
323     MessageManager();
324     ///
325     ~MessageManager();
326     ///
327     static MessageManager* GetInstance();
328     ///
329     static void RegisterMessageType(const std::string& key, 
330                                     const std::string& help,
331                                     unsigned char default_level = 9);
332     ///
333     static void SetMessageLevel(const std::string& key, unsigned char level);
334     ///
335     static int GetMessageLevel(const std::string& key);
336     ///  
337     static void SendMessage(const std::string& key, const std::string& mess);
338     ///
339     static void AddMessageObserver(const std::string& key, MessageCallbackType callback );
340     ///
341     static void SendMessagesToCout(bool v = true);
342     ///
343     static std::string& GetTab() { static std::string s; return s; }
344     ///
345     static std::string GetSpace(int n) { 
346       std::string s; s.insert(0,"                ",n); return s; }
347     ///
348     static void IncTab() { GetTab() += std::string(" "); }
349     ///
350     static void DecTab() { GetTab() = GetTab().substr(0,GetTab().length()-1); }
351     ///
352     static void ResetTab() { GetTab() = std::string(""); }
353     ///
354     static void PrintInfo();
355     /// 
356     
357   private:
358     struct MessageType
359     {
360       MessageType(int l, const std::string& h) : Level(l), Help(h) {}
361       int Level;
362       std::string Help;
363       MessageSignalType Signal;
364     };
365     typedef std::map<std::string,MessageType*> MessageMapType;
366     MessageMapType mMessageMap;
367     unsigned int mMaxMessageLength;
368     bool mSendToCout;
369   };
370   //===========================================================
371   
372 }
373
374 #include "creaException.h"
375
376 #endif