1 #ifndef CORELIB___NCBI_MESSAGE__HPP
2 #define CORELIB___NCBI_MESSAGE__HPP
3
4 /* $Id: ncbi_message.hpp 591546 2019-08-16 16:59:06Z vasilche $
5 * ===========================================================================
6 *
7 * PUBLIC DOMAIN NOTICE
8 * National Center for Biotechnology Information
9 *
10 * This software/database is a "United States Government Work" under the
11 * terms of the United States Copyright Act. It was written as part of
12 * the author's official duties as a United States Government employee and
13 * thus cannot be copyrighted. This software/database is freely available
14 * to the public for use. The National Library of Medicine and the U.S.
15 * Government have not placed any restriction on its use or reproduction.
16 *
17 * Although all reasonable efforts have been taken to ensure the accuracy
18 * and reliability of the software and data, the NLM and the U.S.
19 * Government do not and cannot warrant the performance or results that
20 * may be obtained by using this software or data. The NLM and the U.S.
21 * Government disclaim all warranties, express or implied, including
22 * warranties of performance, merchantability or fitness for any particular
23 * purpose.
24 *
25 * Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Authors: Aleksey Grichenko
30 *
31 * File Description: IMessage/IMessageListener interfaces
32 *
33 */
34
35 /// @file ncbi_message.hpp
36 ///
37 /// IMessage/IMessageListener interfaces and basic implementations.
38 ///
39
40 #include <corelib/ncbiobj.hpp>
41 #include <list>
42
43 /** @addtogroup MESSAGE
44 *
45 * @{
46 */
47
48 BEGIN_NCBI_SCOPE
49
50 /////////////////////////////////////////////////////////////////////////////
51 ///
52 /// IMessage_Base::
53 ///
54 /// Common base class for IMessage and IProgressMessage.
55 ///
56
57 class IMessage_Base
58 {
59 public:
~IMessage_Base(void)60 virtual ~IMessage_Base(void) {}
61
62 /// Get text message.
63 virtual string GetText(void) const = 0;
64
65 /// Print the message and any additional information to the stream.
66 virtual void Write(CNcbiOstream& out) const = 0;
67
68 /// Get the whole composed message as string.
69 /// The default implementations use Write() to compose the string.
70 virtual string Compose(void) const = 0;
71
72 /// Create a copy of the message. The caller is responsible for
73 /// destroying the copy.
74 virtual IMessage_Base* Clone(void) const = 0;
75 };
76
77
78 inline
operator <<(CNcbiOstream & out,const IMessage_Base & msg)79 ostream& operator<<(CNcbiOstream& out, const IMessage_Base& msg)
80 {
81 msg.Write(out);
82 return out;
83 }
84
85
86 /////////////////////////////////////////////////////////////////////////////
87 ///
88 /// IMessage::
89 ///
90 /// Generic message interface to be used with IMessageListener to collect and
91 /// report error messages.
92 ///
93
94 class IMessage : public IMessage_Base
95 {
96 public:
~IMessage(void)97 virtual ~IMessage(void) {}
98
99 /// Get message severity.
100 virtual EDiagSev GetSeverity(void) const = 0;
101
102 /// Get error code. Zero = not set.
103 virtual int GetCode(void) const = 0;
104
105 /// Get error subcode. Zero = not set.
106 virtual int GetSubCode(void) const = 0;
107
108 virtual IMessage* Clone(void) const = 0;
109 };
110
111
112 /////////////////////////////////////////////////////////////////////////////
113 ///
114 /// IProgressMessage::
115 ///
116 /// Generic progress status interface to be used with IMessageListener.
117 /// Unlike IMessage, typical IProgressMessage is intended for immediate
118 /// display rather than collecting and reporting later.
119 ///
120
121 class IProgressMessage : public IMessage_Base
122 {
123 public:
~IProgressMessage(void)124 virtual ~IProgressMessage(void) {}
125
126 /// Get current progress value (e.g. % or bytes written).
127 virtual Uint8 GetCurrent(void) const = 0;
128
129 /// Get total progress value (e.g. 100% or file size).
130 virtual Uint8 GetTotal(void) const = 0;
131
132 virtual IProgressMessage* Clone(void) const = 0;
133 };
134
135
136 /// Default IMessage implementation: text and severity only.
137 class NCBI_XNCBI_EXPORT CMessage_Basic : public IMessage
138 {
139 public:
140 CMessage_Basic(const string& txt,
141 EDiagSev sev,
142 int err_code = 0,
143 int sub_code = 0);
144
145 virtual string GetText(void) const;
146 virtual EDiagSev GetSeverity(void) const;
147 virtual int GetCode(void) const;
148 virtual int GetSubCode(void) const;
149 virtual IMessage* Clone(void) const;
150 virtual void Write(CNcbiOstream& out) const;
151 virtual string Compose(void) const;
152
153 private:
154 string m_Text;
155 EDiagSev m_Severity;
156 int m_ErrCode;
157 int m_SubCode;
158 };
159
160
161 /// Default IProgressMessage implementation.
162 class NCBI_XNCBI_EXPORT CProgressMessage_Basic : public IProgressMessage
163 {
164 public:
165 CProgressMessage_Basic(const string& txt,
166 Uint8 current,
167 Uint8 total);
168
169 virtual string GetText(void) const;
170 virtual Uint8 GetCurrent(void) const;
171 virtual Uint8 GetTotal(void) const;
172 virtual CProgressMessage_Basic* Clone(void) const;
173 virtual void Write(CNcbiOstream& out) const;
174 virtual string Compose(void) const;
175
176 private:
177 string m_Text;
178 Uint8 m_Current;
179 Uint8 m_Total;
180 };
181
182
183 /////////////////////////////////////////////////////////////////////////////
184 ///
185 /// IMessageListener::
186 ///
187 /// Interface for IMessage listener/collector.
188 ///
189
190 class NCBI_XNCBI_EXPORT IMessageListener : public CObject
191 {
192 public:
~IMessageListener(void)193 virtual ~IMessageListener(void) {}
194
195 /// Result of PostXXXX() operation.
196 enum EPostResult {
197 eHandled, ///< The message was successfully handled and will not be
198 ///< passed to other listeners installed with
199 ///< eListen_Unhandled flag.
200 eUnhandled ///< The message was not handled and should be passed to
201 ///< other listeners.
202 };
203
204 /// Post new message to the listener.
205 virtual EPostResult PostMessage(const IMessage& message) = 0;
206
207 /// Report progress.
208 /// @param message
209 /// Text message explaining the current state.
210 /// @param current
211 /// Current progress value.
212 /// @param total
213 /// Max progress value.
214 virtual EPostResult PostProgress(const IProgressMessage& progress) = 0;
215
216 /// Get a previously collected message.
217 /// @param index
218 /// Index of the message, must be less than Count().
219 virtual const IMessage& GetMessage(size_t index) const = 0;
220
221 /// Get total number of collected messages.
222 virtual size_t Count(void) const = 0;
223
224 /// Clear all collected messages.
225 virtual void Clear(void) = 0;
226
227 /// Which messages should be passed to the listener
228 enum EListenFlag {
229 eListen_Unhandled, ///< Default flag. The listener only wants messages
230 ///< not handled by previous listeners.
231 eListen_All ///< The listener wants to see all messages, even
232 ///< those already handled.
233 };
234
235 /// Push a new listener to the stack in the current thread.
236 /// @param listener
237 /// The listener to be installed.
238 /// @param flag
239 /// Flag specifying if the new listener should receive all messages
240 /// or only those not handled by other listeners above the current.
241 /// @return
242 /// Total number of listeners in the current thread's stack including
243 /// the new one. This number can be passed to PopListener() for more
244 /// reliable cleanup.
245 /// @sa PopListener()
246 static size_t PushListener(IMessageListener& listener,
247 EListenFlag flag = eListen_Unhandled);
248
249 /// Remove listener(s) from the current thread's stack.
250 /// @param depth
251 /// Index of the listener to be removed, as returned by PushListener().
252 /// If the depth is zero (default), only the topmost listener is removed.
253 /// If there are listeners whose index is larger than (non-zero) depth, then
254 /// all such listeners will be removed too, and a warning will be posted.
255 /// If the current stack size is less than depth, no action is performed,
256 /// and a warning will be posted.
257 /// @sa PushListener()
258 static void PopListener(size_t depth = 0);
259
260 /// Check if there are any listeners installed in the current thread.
261 static bool HaveListeners(void);
262
263 /// Post the message to listener(s), if any. The message is posted
264 /// to each listener starting from the top of the stack. After a
265 /// listener returns eHandled, the message is posted only to the
266 /// listeners which were installed with eListen_All flag.
267 /// @return
268 /// eHandled if at least one listener has handled the message,
269 /// eUnhandled otherwise.
270 /// @sa PostMessage()
271 static EPostResult Post(const IMessage& message);
272
273 /// Post the progress to listener(s), if any. The progress is posted
274 /// to each listener starting from the top of the stack. After a
275 /// listener returns eHandled, the progress is posted only to the
276 /// listeners which were installed with eListen_All flag.
277 /// @return
278 /// eHandled if at least one listener has handled the event,
279 /// eUnhandled otherwise.
280 /// @sa PostProgress()
281 static EPostResult Post(const IProgressMessage& progress);
282 };
283
284
285 /// Default implementation of IMessageListener: collects all messages
286 /// posted.
287 class NCBI_XNCBI_EXPORT CMessageListener_Basic : public IMessageListener
288 {
289 public:
290 virtual EPostResult PostMessage(const IMessage& message);
291 virtual EPostResult PostProgress(const IProgressMessage& progress);
292 virtual const IMessage& GetMessage(size_t index) const;
293 virtual size_t Count(void) const;
294 virtual void Clear(void);
295 private:
296 typedef vector< AutoPtr<IMessage> > TMessages;
297
298 TMessages m_Messages;
299 };
300
301
302 /* @} */
303
304 END_NCBI_SCOPE
305
306 #include <corelib/impl/listener_stack.hpp>
307
308 #endif /* CORELIB___NCBI_MESSAGE__HPP */
309