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