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