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