]> Creatis software - crea.git/blob - src/creaMessageManager.h
#3374 crea Bug New Normal - vtk8itk5wx3-mingw64
[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   
65 #ifndef __creaMessageManager_h__
66 #define __creaMessageManager_h__
67
68 // The do { } while(0) statement in macros is made to "swallow the semicolon" 
69 // see http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html#Swallowing-the-Semicolon
70 #include "creaSystem.h"
71 #include "creaRTTI.h" // for CREA_GET_CURRENT_OBJECT_NAME
72 // Signal/slot mechanism for message events
73 #include <boost/signals2/signal.hpp>
74 #include <boost/bind.hpp>
75 #include <string>
76 #include <map>
77 #include <iostream>
78 #include <sstream>
79
80
81
82 namespace crea 
83 {
84   class CREA_EXPORT MessageManager
85   {
86   public:
87     //=============================================
88     typedef boost::signals2::signal<void (const std::string&)>  MessageSignalType;
89     typedef MessageSignalType::slot_function_type MessageCallbackType;
90     //=============================================
91     MessageManager();
92     ~MessageManager();
93     static MessageManager* GetInstance();
94     static void RegisterMessageType(const std::string& key, 
95                                     const std::string& help,
96                                     unsigned char default_level = 9);
97     static void SetMessageLevel(const std::string& key, unsigned char level);
98     static int GetMessageLevel(const std::string& key);
99     static void HSendMessage(const std::string& key, const std::string& mess);
100     static void AddMessageObserver(const std::string& key, MessageCallbackType callback );
101     static void SendMessagesToCout(bool v = true);
102     static std::string& GetTab() { static std::string s; return s; }
103     static std::string GetSpace(int n)  {       std::string s; s.insert(0,"                ",n); return s; }
104     static void IncTab() { GetTab() += std::string(" "); }
105     static void DecTab() { GetTab() = GetTab().substr(0,GetTab().length()-1); }
106     static void ResetTab() { GetTab() = std::string(""); }
107     static void PrintInfo();
108 private:
109     struct MessageType
110     {
111       MessageType(int l, const std::string& h) : Level(l), Help(h) {}
112       int Level;
113       std::string Help;
114       MessageSignalType Signal;
115     };
116     typedef std::map<std::string,MessageType*> MessageMapType;
117     MessageMapType mMessageMap;
118     unsigned int mMaxMessageLength;
119     bool mSendToCout;
120   };
121   //===========================================================
122 }
123
124
125
126
127
128
129
130
131 // Comment out these symbols to prevent compilation 
132 //#define CREA_COMPILE_MESSAGES
133 //#define CREA_COMPILE_DEBUG_MESSAGES
134 //#define CREA_COMPILE_WARNING_MESSAGES
135 //#define CREA_COMPILE_ERROR_MESSAGES
136 #define creaOnMessageLevel(key,value)                   \
137   int __creaOnMessageLevelVariable =                    \
138     crea::MessageManager::GetMessageLevel(key);         \
139   if ( __creaOnMessageLevelVariable<0)                  \
140     {                                                   \
141       creaWarning("message type '"<<key<<"' unknown");  \
142     }                                                   \
143   else if (value<= __creaOnMessageLevelVariable) 
144
145 #ifdef CREA_PREPEND_MESSAGE_WITH_CODE
146 #define creaMessageCode                         \
147   key[0] << key[1] << key[2] << value << " "
148 #else 
149 #define creaMessageCode ""
150 #endif 
151
152 #ifdef CREA_PREPEND_MESSAGE_WITH_TAB
153 #define creaMessageTab                          \
154   crea::MessageManager::GetTab()
155 #else 
156 #define creaMessageTab ""
157 #endif
158
159 //#define CREA_PREPEND_MESSAGE_WITH_SPACE
160 #ifdef CREA_PREPEND_MESSAGE_WITH_SPACE
161 #define creaMessageSpace(value)                 \
162   crea::MessageManager::GetSpace(value)
163 #else 
164 #define creaMessageSpace(value) ""
165 #endif
166
167  
168
169
170
171 //===========================================================
172
173 #ifdef CREA_COMPILE_MESSAGES
174
175 // Macro for messages
176 #define creaMessage(key,value,MESSAGE)                  \
177   do {                                                  \
178     creaOnMessageLevel(key,value)                       \
179       {                                                 \
180         std::ostringstream s;                           \
181         s << creaMessageCode                            \
182           << creaMessageTab                             \
183           << creaMessageSpace(value)                    \
184           << MESSAGE;                                   \
185         crea::MessageManager::HSendMessage(key,s.str());        \
186       }                                                 \
187   }                                                     \
188   while (0)
189
190
191
192 // Macro for continuing a message (when one wants to split the macro
193 // call into multiple lines)
194 #define creaMessageCont(key,value,MESSAGE)              \
195   do                                                    \
196     {                                                   \
197       creaOnMessageLevel(key,value)                     \
198         {                                               \
199         std::ostringstream s;                           \
200         s << MESSAGE;                                   \
201         crea::MessageManager::HSendMessage(key,s.str());        \
202         }                                               \
203     }                                                   \
204   while (0)
205
206
207 #define creaMessageInc(key,value,MESSAGE)               \
208   do                                                    \
209     {                                                   \
210         std::ostringstream s;                           \
211         s << creaMessageCode                            \
212           << creaMessageTab                             \
213           << creaMessageSpace(value)                    \
214           << MESSAGE;                                   \
215         crea::MessageManager::HSendMessage(key,s.str());        \
216         crea::MessageManager::IncTab();                 \
217         }                                               \
218     }                                                   \
219   while (0)
220
221
222 #define creaMessageDec(key,value,MESSAGE)                       \
223   do                                                            \
224     {                                                           \
225       creaOnMessageLevel(key,value)                             \
226         {                                                       \
227           crea::MessageManager::DecTab();                       \
228           std::ostringstream s;                                 \
229           s << creaMessageCode                                  \
230             << creaMessageTab                                   \
231             << creaMessageSpace(value)                          \
232             << MESSAGE;                                         \
233           crea::MessageManager::HSendMessage(key,s.str());      \
234         }                                                       \
235     }                                                           \
236   while (0)
237
238
239 #define creaDecTab(key,value)                   \
240   do                                            \
241     {                                           \
242       creaOnMessageLevel(key,value)             \
243         {                                       \
244           crea::MessageManager::DecTab();       \
245         }                                       \
246     }                                           \
247   while (0)
248
249
250 #define creaIncTab(key,value)                   \
251   do                                            \
252     {                                           \
253       creaOnMessageLevel(key,value)             \
254         {                                       \
255           crea::MessageManager::IncTab();       \
256         }                                       \
257     }                                           \
258   while (0)
259
260
261 #define creaResetTab()                          \
262   do                                            \
263     {                                           \
264       crea::MessageManager::ResetTab();         \
265     }                                           \
266   while (0)
267
268 #else
269 #define creaMessage(key,value,MESSAGE)
270 #define creaMessageInc(key,value,MESSAGE)
271 #define creaMessageDec(key,value,MESSAGE)
272 #define creaMessageCont(key,value,MESSAGE)
273 #define creaDecTab(key,value)
274 #define creaIncTab(key,value)
275 #define creaResetTab()
276 #endif
277
278 //===========================================================
279
280
281
282
283
284
285
286 //===========================================================
287
288 // Macros for debug messages
289
290 #ifdef CREA_COMPILE_DEBUG_MESSAGES
291
292 #define creaDebugMessage(key,value,MESSAGE) creaMessage(key,value,MESSAGE)
293
294 #define creaDebugMessageCont(key,value,MESSAGE) creaMessageCont(key,value,MESSAGE)
295
296 #define creaDebugMessageInc(key,value,MESSAGE) creaMessageInc(key,value,MESSAGE)  
297
298 #define creaDebugMessageDec(key,value,MESSAGE) creaMessageDec(key,value,MESSAGE)
299
300 #define creaDebugDecTab(key,value) creaDecTab(key,value)
301
302 #define creaDebugIncTab(key,value) creaIncTab(key,value)
303
304 #define creaDebugResetTab() creaResetTab()
305
306 #else
307
308 #define creaDebugMessage(key,value,MESSAGE) 
309
310 #define creaDebugMessageCont(key,value,MESSAGE) 
311
312 #define creaDebugMessageInc(key,value,MESSAGE)
313
314 #define creaDebugMessageDec(key,value,MESSAGE) 
315
316 #define creaDebugDecTab(key,value)
317
318 #define creaDebugIncTab(key,value)
319
320 #endif
321
322 //===========================================================
323
324
325
326 //===========================================================
327
328 #ifdef CREA_COMPILE_WARNING_MESSAGES
329 #define creaWarning(MESSAGE)                                            \
330   do                                                                    \
331     {                                                                   \
332       int lev = crea::MessageManager::GetMessageLevel("warning");       \
333       if (lev >0)                                                       \
334         {                                                               \
335           std::cerr << "!! WARNING !! " << MESSAGE << std::endl;        \
336           if (lev >1)                                                   \
337             {                                                           \
338               std::cerr << "!! WARNING !! In file '"<<__FILE__          \
339                         <<"' ; Line "<<__LINE__<<std::endl;             \
340             }                                                           \
341         }                                                               \
342     }                                                                   \
343   while (0) 
344
345 #else
346 #define creaWarning(MESSAGE) 
347 #endif
348
349 //===========================================================
350
351
352
353
354
355 //===========================================================
356
357 #ifdef CREA_COMPILE_ERROR_MESSAGES
358 //#include "creaWx.h"
359 #define creaError(MESSAGE)                              \
360   do                                                    \
361     {                                                   \
362       std::ostringstream s;                             \
363       s << MESSAGE;                                     \
364       std::ostringstream f;                             \
365       f << __FILE__ << " (l."<<__LINE__<<")";           \
366       crea::Exception e( CREA_GET_CURRENT_OBJECT_NAME,  \
367                         f.str(),                        \
368                         s.str());                       \
369       throw e;                                          \
370     }                                                   \
371   while (0) 
372
373
374
375 #define creaGlobalError(MESSAGE)                                \
376   do                                                    \
377     {                                                   \
378       std::ostringstream s;                             \
379       s << MESSAGE;                                     \
380       std::ostringstream f;                             \
381       f << __FILE__ << " (l."<<__LINE__<<")";           \
382       crea::Exception e( "global scope",                \
383                         f.str(),                        \
384                         s.str());                       \
385       throw e;                                          \
386     }                                                   \
387   while (0) 
388
389
390
391 #define CREA_INTERNAL_ERROR_MESSAGE \
392   "\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"
393
394 #define creaInternalError(MESSAGE)                      \
395   do                                                    \
396     {                                                   \
397       std::ostringstream s;                             \
398       s << MESSAGE << CREA_INTERNAL_ERROR_MESSAGE;      \
399       std::ostringstream f;                             \
400       f << __FILE__ << " (l."<<__LINE__<<")";           \
401       crea::Exception e( CREA_GET_CURRENT_OBJECT_NAME,  \
402                          f.str(),                       \
403                          s.str());                      \
404       throw e;                                          \
405     }                                                   \
406   while (0) 
407
408
409
410 #else
411 #define creaError(MESSAGE)
412 #define creaGlobalError(MESSAGE)
413 #define creaInternalError(MESSAGE)
414 #endif
415
416 //===========================================================
417
418
419
420 //===========================================================
421
422 #define creaendl std::endl
423
424 //===========================================================
425
426
427
428
429
430
431
432
433 #include "creaException.h"
434
435
436
437 #endif
438