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, 7 months ago) by tim
File size: 6711 byte(s)
Log Message:
adding openbabel

File Contents

# Content
1 /**********************************************************************
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.