1 /*  $Id: message_listener.hpp 632526 2021-06-02 17:25:01Z ivanov $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Frank Ludwig
27  *
28  * File Description:
29  *   Classes for listening to errors, progress, etc.
30  *
31  */
32 
33 #ifndef OBJTOOLS_READERS___MESSAGELISTENER__HPP
34 #define OBJTOOLS_READERS___MESSAGELISTENER__HPP
35 
36 #include <corelib/ncbistd.hpp>
37 #include <corelib/ncbiobj.hpp>
38 #include <corelib/ncbi_message.hpp>
39 #include <objtools/readers/line_error.hpp>
40 #include <objtools/logging/listener.hpp>
41 
42 BEGIN_NCBI_SCOPE
43 
44 BEGIN_SCOPE(objects) // namespace ncbi::objects::
45 
46 //  ============================================================================
47 class ILineErrorListener : public CObject, public IObjtoolsListener
48 //  ============================================================================
49 {
50 public:
~ILineErrorListener()51     virtual ~ILineErrorListener() {}
52 
53     // IListener::Post() implementation
54     NCBI_STD_DEPRECATED("This method is no longer functional and will be removed in SC-25.")
Post(const IMessage &)55     virtual void Post(const IMessage& /*message*/)
56     {
57         // Remove in SC-25
58         return;
59     }
60 
61     NCBI_STD_DEPRECATED("This method is redundant and will be removed in SC-25.")
Push(const IObjtoolsMessage & message)62     virtual void Push(const IObjtoolsMessage& message)
63     {
64         // Remove in SC-25
65         PutMessage(message);
66     }
67     /// Store error in the container, and
68     /// return true if error was stored fine, and
69     /// return false if the caller should terminate all further processing.
70     ///
71     virtual bool
72     PutError(
73         const ILineError& ) = 0;
74 
75     virtual bool
PutMessage(const IObjtoolsMessage & message)76     PutMessage(const IObjtoolsMessage& message) {
77         const ILineError* le = dynamic_cast<const ILineError*>(&message);
78         if (!le) return true;
79         return PutError(*le);
80     }
81 
82     // IListener::Get() implementation
Get(size_t index) const83     virtual const ILineError& Get(size_t index) const
84     { return this->GetError(index); }
85 
86     /// 0-based error retrieval.
87     virtual const ILineError&
88     GetError(size_t ) const =0;
89 
90     virtual size_t Count(void) const = 0;
91 
92     /// Returns the number of errors seen so far at the given severity.
93     virtual size_t
94     LevelCount(
95         EDiagSev )=0;
96 
97     /// Clear all accumulated messages.
98     virtual void
99     ClearAll() =0;
100 
101     // IListener::Progress() implementation
Progress(const string & message,Uint8 current,Uint8 total)102     virtual void Progress(const string& message,
103                           Uint8         current,
104                           Uint8         total) { PutProgress(message, current, total); }
105 
106     /// This is used for processing progress messages.
107     virtual void
108     PutProgress(
109         const string & sMessage,
110         const Uint8 iNumDone = 0,
111         const Uint8 iNumTotal = 0 ) = 0;
112 
GetMessage(size_t index) const113     virtual const ILineError& GetMessage(size_t index) const
114     { return Get(index); }
115 
Clear(void)116     virtual void Clear(void)
117     { ClearAll(); }
118 };
119 
120 
121 // Compatibility declaration, avoid using objects::IMessageListener -
122 // use ncbi::IMessageListener or objects::ILineErrorListener instead.
123 class IMessageListener : public ILineErrorListener
124 {
125 public:
~IMessageListener(void)126     virtual ~IMessageListener(void) {}
127 };
128 
129 
130 //  ============================================================================
131 class NCBI_XOBJREAD_EXPORT CMessageListenerBase : public objects::IMessageListener
132 //  ============================================================================
133 {
134 public:
CMessageListenerBase()135     CMessageListenerBase() : m_pProgressOstrm(0) {};
~CMessageListenerBase()136     virtual ~CMessageListenerBase() {};
137 
138 public:
139     size_t
Count() const140     Count() const { return m_Errors.size(); };
141 
142     virtual size_t
LevelCount(EDiagSev eSev)143     LevelCount(
144         EDiagSev eSev ) {
145         size_t uCount( 0 );
146         for ( size_t u=0; u < Count(); ++u ) {
147             if ( m_Errors[u]->GetSeverity() == eSev ) ++uCount;
148         }
149         return uCount;
150     };
151 
152     void
ClearAll()153     ClearAll() { m_Errors.clear(); };
154 
155     const ILineError&
GetError(size_t uPos) const156     GetError(
157         size_t uPos ) const {
158             return *dynamic_cast<ILineError*>(m_Errors[ uPos ].get()); }
159 
Dump()160     virtual void Dump()
161     {
162         if (m_pProgressOstrm)
163             Dump(*m_pProgressOstrm);
164     }
165 
Dump(std::ostream & out)166     virtual void Dump(
167         std::ostream& out )
168     {
169         if ( m_Errors.size() ) {
170             TLineErrVec::iterator it;
171             for ( it = m_Errors.begin(); it != m_Errors.end(); ++it ) {
172                 (*it)->Dump( out );
173                 out << endl;
174             }
175         }
176         else {
177             out << "(( no errors ))" << endl;
178         }
179     };
180 
DumpAsXML(std::ostream & out)181     virtual void DumpAsXML(
182         std::ostream& out )
183     {
184         if ( m_Errors.size() ) {
185             TLineErrVec::iterator it;
186             for ( it = m_Errors.begin(); it != m_Errors.end(); ++it ) {
187                 (*it)->DumpAsXML( out );
188                 out << endl;
189             }
190         }
191         else {
192             out << "(( no errors ))" << endl;
193         }
194     };
195 
196 
197     virtual void
198     PutProgress(
199         const string & sMessage,
200         const Uint8 iNumDone,
201         const Uint8 iNumTotal );
202 
203     /// This sets the stream to which progress messages are written.
204     ///
205     /// @param pProgressOstrm
206     ///   The output stream for progress messages.  Set this to NULL to
207     ///   stop writing progress messages.
208     /// @param eNcbiOwnership
209     ///   Indicates whether this CMessageListenerBase should own
210     ///   pProgressOstrm.
211     virtual void
SetProgressOstream(CNcbiOstream * pProgressOstrm,ENcbiOwnership eNcbiOwnership=eNoOwnership)212     SetProgressOstream(
213         CNcbiOstream * pProgressOstrm,
214         ENcbiOwnership eNcbiOwnership = eNoOwnership )
215     {
216         m_pProgressOstrm = pProgressOstrm;
217         if( eNcbiOwnership == eTakeOwnership && pProgressOstrm ) {
218             m_progressOstrmDestroyer.reset( pProgressOstrm );
219         } else {
220             m_progressOstrmDestroyer.reset();
221         }
222     }
223 
224 private:
225     // private so later we can change the structure if
226     // necessary (e.g. to have indexing and such to speed up
227     // level-counting)
228     // typedef std::vector< AutoPtr<ILineError> > TLineErrVec;
229 
230     using TLineErrVec = vector<AutoPtr<IObjtoolsMessage>>;
231     TLineErrVec m_Errors;
232 
233 
234     // The stream to which progress messages are written.
235     // If NULL, progress messages are not written.
236     CNcbiOstream * m_pProgressOstrm;
237 
238     // do not read this pointer.  It's just used to make
239     // sure m_pProgressOstrm is destroyed if we own it.
240     AutoPtr<CNcbiOstream> m_progressOstrmDestroyer;
241 
242 protected:
243 
244     // Child classes should use this to store errors
245     // into m_Errors
StoreError(const ILineError & err)246     void StoreError(const ILineError& err)
247     {
248         m_Errors.emplace_back(err.Clone());
249     }
250 
StoreMessage(const IObjtoolsMessage & message)251     void StoreMessage(const IObjtoolsMessage& message)
252     {
253         m_Errors.emplace_back(dynamic_cast<IObjtoolsMessage*>(message.Clone()));
254     }
255 };
256 
257 //  ============================================================================
258 class CMessageListenerLenient:
259 //
260 //  Accept everything.
261 //  ============================================================================
262     public CMessageListenerBase
263 {
264 public:
CMessageListenerLenient()265     CMessageListenerLenient() {};
~CMessageListenerLenient()266     ~CMessageListenerLenient() {};
267 
268     bool
PutMessage(const IObjtoolsMessage & message)269     PutMessage(
270         const IObjtoolsMessage& message)
271     {
272         StoreMessage(message);
273         return true;
274     }
275 
276     bool
PutError(const ILineError & err)277     PutError(
278         const ILineError& err )
279     {
280         return PutMessage(err);
281     };
282 };
283 
284 //  ============================================================================
285 class CMessageListenerStrict:
286 //
287 //  Don't accept any errors, at all.
288 //  ============================================================================
289     public CMessageListenerBase
290 {
291 public:
CMessageListenerStrict()292     CMessageListenerStrict() {};
~CMessageListenerStrict()293     ~CMessageListenerStrict() {};
294 
295     bool
PutMessage(const IObjtoolsMessage & message)296     PutMessage(
297         const IObjtoolsMessage& message)
298     {
299         StoreMessage(message);
300         return false;
301     }
302 
303     bool
PutError(const ILineError & err)304     PutError(
305         const ILineError& err )
306     {
307         return PutMessage(err);
308     };
309 };
310 
311 //  ===========================================================================
312 class CMessageListenerCount:
313 //
314 //  Accept up to <<count>> errors, any level.
315 //  ===========================================================================
316     public CMessageListenerBase
317 {
318 public:
CMessageListenerCount(size_t uMaxCount)319     CMessageListenerCount(
320         size_t uMaxCount ): m_uMaxCount( uMaxCount ) {};
~CMessageListenerCount()321     ~CMessageListenerCount() {};
322 
PutMessage(const IObjtoolsMessage & message)323     bool PutMessage(
324         const IObjtoolsMessage& message)
325     {
326         StoreMessage(message);
327         return (Count() < m_uMaxCount);
328     }
329 
330 
331     bool
PutError(const ILineError & err)332     PutError(
333         const ILineError& err )
334     {
335         return PutMessage(err);
336     };
337 protected:
338     size_t m_uMaxCount;
339 };
340 
341 //  ===========================================================================
342 class CMessageListenerLevel:
343 //
344 //  Accept evrything up to a certain level.
345 //  ===========================================================================
346     public CMessageListenerBase
347 {
348 public:
CMessageListenerLevel(int iLevel)349     CMessageListenerLevel(
350         int iLevel ): m_iAcceptLevel( iLevel ) {};
~CMessageListenerLevel()351     ~CMessageListenerLevel() {};
352 
353     bool
PutMessage(const IObjtoolsMessage & message)354     PutMessage(
355         const IObjtoolsMessage& message)
356     {
357         StoreMessage(message);
358         return (message.GetSeverity() <= m_iAcceptLevel);
359     }
360 
361     bool
PutError(const ILineError & err)362     PutError(
363         const ILineError& err )
364     {
365         return PutMessage(err);
366     };
367     protected:
368         int m_iAcceptLevel;
369     };
370 
371     //  ===========================================================================
372     class CMessageListenerWithLog:
373     //
374     //  Accept everything, and besides storing all errors, post them.
375 //  ===========================================================================
376     public CMessageListenerBase
377 {
378 public:
CMessageListenerWithLog(const CDiagCompileInfo & info)379     CMessageListenerWithLog(const CDiagCompileInfo& info)
380         : m_Info(info) {};
~CMessageListenerWithLog()381     ~CMessageListenerWithLog() {};
382 
383     bool
PutError(const ILineError & err)384     PutError(
385         const ILineError& err )
386     {
387         CNcbiDiag(m_Info, err.Severity(),
388                   eDPF_Log | eDPF_IsMessage).GetRef()
389            << err.Message() << Endm;
390 
391         StoreError(err);
392         return true;
393     };
394 
395 private:
396     const CDiagCompileInfo m_Info;
397 };
398 
399 
400 //  ===========================================================================
401 class NCBI_XOBJREAD_EXPORT CGPipeMessageListener :
402 //  ===========================================================================
403     public CMessageListenerBase
404 {
405 public:
406     CGPipeMessageListener(bool ignoreBadModValue=false);
407 
408     bool PutError(const ILineError& err) override final;
409 private:
410     bool m_IgnoreBadModValue;
411 };
412 
413 END_SCOPE(objects)
414 
415 END_NCBI_SCOPE
416 
417 #endif // OBJTOOLS_READERS___MESSAGELISTENER__HPP
418 
419