ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/oberror.cpp
Revision: 2440
Committed: Wed Nov 16 19:42:11 2005 UTC (18 years, 8 months ago) by tim
File size: 6711 byte(s)
Log Message:
adding openbabel

File Contents

# User Rev Content
1 tim 2440 /**********************************************************************
2     oberror.cpp - Handle error messages.
3    
4     Copyright (C) 2002 by Stefan Kebekus
5     Some portions Copyright (C) 2002-2005 by Geoffrey R. Hutchison
6    
7     This file is part of the Open Babel project.
8     For more information, see <http://openbabel.sourceforge.net/>
9    
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation version 2 of the License.
13    
14     This program is distributed in the hope that it will be useful, but
15     WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17     General Public License for more details.
18     ***********************************************************************/
19    
20     #include "babelconfig.hpp"
21    
22     #if HAVE_IOSTREAM
23     #include <iostream>
24     #elif HAVE_IOSTREAM_H
25     #include <iostream.h>
26     #endif
27     #include <string>
28    
29     #include "oberror.hpp"
30    
31     using namespace std;
32    
33     namespace OpenBabel
34     {
35    
36     OBMessageHandler obErrorLog;
37    
38     OBError::OBError( const string &method,
39     const string &errorMsg,
40     const string &explanation,
41     const string &possibleCause,
42     const string &suggestedRemedy,
43     const obMessageLevel level) :
44     _method(method), _errorMsg(errorMsg), _explanation(explanation),
45     _possibleCause(possibleCause), _suggestedRemedy(suggestedRemedy),
46     _level(level)
47     { }
48    
49     string OBError::message() const
50     {
51     string tmp = "==============================\n";
52    
53     if (_level == obError)
54     tmp += "*** Open Babel Error ";
55     else if (_level == obWarning)
56     tmp += "*** Open Babel Warning ";
57     else if (_level == obInfo)
58     tmp += "*** Open Babel Information ";
59     else if (_level == obAuditMsg)
60     tmp += "*** Open Babel Audit Log ";
61     else
62     tmp += "*** Open Babel Debugging Message ";
63    
64     if (_method.length() != 0)
65     {
66     tmp += " in " + _method + string("\n ");
67     }
68     tmp += _errorMsg + "\n";
69     if (_explanation.size() != 0)
70     tmp += " " + _explanation + "\n";
71     if (_possibleCause.size() != 0)
72     tmp += " Possible reason: " + _possibleCause + "\n";
73     if (_suggestedRemedy.size() != 0)
74     tmp += " Suggestion: " + _suggestedRemedy + "\n";
75     return tmp;
76     }
77    
78    
79     /** \class OBMessageHandler
80    
81     OBMessageHandler represents a configurable error system for Open Babel.
82    
83     A global error log is defined by the Open Babel library for use of
84     internal code as well as code built on top of Open Babel. This class
85     allows flexible filtering based on urgency (defined by the
86     obMessageLevel type), an "audit log" of molecular changes, including
87     recall using the GetMessagesOfLevel method, etc.
88    
89     The default is to only log and output errors of priority
90     obMessageLevel::obError or obMessageLevel::obWarning.
91    
92     Long-running code may wish to set the size of the in-memory error log
93     using the StartLogging / StopLogging methods and
94     SetMaxLogEntries. Otherwise, the error log may easily fill up,
95     requiring large amounts of memory.
96    
97     If you wish to divert error output to a different std::ostream (i.e.,
98     for graphical display, or a file log), use the SetOutputStream method
99     -- the default goes to the std::clog stream. Furthermore, some older
100     code uses std::cerr for direct error output, rather than the
101     ThrowError() methods in this class. To prevent this, you can turn on
102     "error wrapping" using the StartErrorWrap method -- this behavior is
103     turned off by default.
104    
105     To make it easy to use the OBMessageHandler class and error logging
106     facilities, a global log is defined:
107    
108     \code
109     EXTERN OBMessageHandler obErrorLog;
110     \endcode
111    
112     Therefore, it is very easy to log errors:
113    
114     \code
115     if (atomIndex < 1 || atomIndex > mol.NumAtoms() )
116     obErrorLog.ThrowError(__FUNCTION__, "Requested Atom Out of Range", obDebug);
117     \endcode
118    
119     or
120    
121     \code
122     stringstream errorMsg;
123     errorMsg << " Could not parse line in type translation table types.txt -- incorect number of columns";
124     errorMsg << " found " << vc.size() << " expected " << _ncols << ".";
125     obErrorLog.ThrowError(__FUNCTION__, errorMsg.str(), obInfo);
126     \endcode
127    
128     The __FUNCTION__ builtin is defined by many compilers (e.g., <a
129     href="http://gcc.gnu.org/">GCC</a>) but can be defined to an empty
130     string on some platforms without this compiler extension.
131    
132     Output from the error log typically looks like:
133     \code
134     ==============================
135     *** Open Babel Audit Log in ReadChemObject
136     OpenBabel::Read molecule Protein Data Bank format
137     ==============================
138     *** Open Babel Information in ParseConectRecord
139     WARNING: Problems reading a PDB file
140     Problems reading a CONECT record.
141     According to the PDB specification,
142     the record should have 70 columns, but OpenBabel found 61 columns.
143     \endcode
144    
145     **/
146    
147     OBMessageHandler::OBMessageHandler() :
148     _outputLevel(obWarning), _outputStream(&clog), _logging(true)
149     {
150     // StartErrorWrap(); // (don't turn on error wrapping by default)
151     }
152    
153     OBMessageHandler::~OBMessageHandler()
154     {
155     StopErrorWrap();
156    
157     // free the internal filter streambuf
158     if (_filterStreamBuf != NULL)
159     delete _filterStreamBuf;
160     }
161    
162     void OBMessageHandler::ThrowError(OBError err)
163     {
164     _messageList.push_back(err);
165     if (_maxEntries != 0 && _messageList.size() > _maxEntries)
166     _messageList.pop_front();
167    
168     if (_logging && err.GetLevel() <= _outputLevel)
169     {
170     *_outputStream << err;
171     }
172     }
173    
174     void OBMessageHandler::ThrowError(const std::string &method,
175     const std::string &errorMsg,
176     obMessageLevel level)
177     {
178     if (errorMsg.length() > 1)
179     {
180     OBError err(method, errorMsg, "", "", "", level);
181     ThrowError(err);
182     }
183     }
184    
185     std::vector<std::string> OBMessageHandler::GetMessagesOfLevel(const obMessageLevel level)
186     {
187     vector<string> results;
188     deque<OBError>::iterator i;
189     OBError error;
190    
191     for (i = _messageList.begin(); i != _messageList.end(); i++)
192     {
193     error = (*i);
194     if (error.GetLevel() == level)
195     results.push_back( error.message() );
196     }
197    
198     return results;
199     }
200    
201     bool OBMessageHandler::StartErrorWrap()
202     {
203     if (_inWrapStreamBuf != NULL)
204     return true; // already wrapped cerr -- don't go into loops!
205    
206     _inWrapStreamBuf = cerr.rdbuf();
207    
208     if (_filterStreamBuf == NULL)
209     {
210     _filterStreamBuf = new(obLogBuf);
211     }
212    
213     cerr.rdbuf(_filterStreamBuf);
214     return true;
215     }
216    
217     bool OBMessageHandler::StopErrorWrap()
218     {
219     if (_inWrapStreamBuf == NULL)
220     return true; // never wrapped cerr
221    
222     // don't free the filter streambuf yet -- we might start wrapping later
223     // it's freed in the dtor
224    
225     cerr.rdbuf(_inWrapStreamBuf);
226     return true;
227     }
228    
229     } // end namespace OpenBabel
230    
231     //! \file oberror.cpp
232     //! \brief Handle error messages, warnings, notices, etc.
233     //! Implements OBMessageHandler class.