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