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