casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
LogIO.h
Go to the documentation of this file.
00001 //# LogIO.h: ostream-like interface to creating log messages.
00002 //# Copyright (C) 1997,1999,2000,2001,2003
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //#
00027 //# $Id: LogIO.h 21005 2010-12-08 08:56:59Z gervandiepen $
00028 
00029 #ifndef CASA_LOGIO_H
00030 #define CASA_LOGIO_H
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <casa/Logging/LogMessage.h>
00035 #include <casa/Logging/LogSink.h>
00036 #include <casa/BasicSL/Complex.h>
00037 #include <casa/iosstrfwd.h>
00038 
00039 namespace casa { //# NAMESPACE CASA - BEGIN
00040 
00041 //# Forward Declarations
00042 class LogSink;
00043 class LogOrigin;
00044 
00045 // <summary>
00046 // ostream-like interface to creating log messages.
00047 // </summary>
00048 
00049 // <use visibility=export>
00050 
00051 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tLogIO.cc" demos="dLogging.cc">
00052 // </reviewed>
00053 
00054 // <prerequisite>
00055 //   <li> <linkto class=LogSink>LogSink</linkto> class
00056 //   <li> <linkto class=LogMessage>LogMessage</linkto> class
00057 //   <li> <linkto class=LogMessage>LogOrigin</linkto> class
00058 // </prerequisite>
00059 //
00060 // <etymology>
00061 // <src>Log</src> message, <src>I</src>nput/<src>O</src>utput.
00062 // </etymology>
00063 //
00064 // <synopsis>
00065 // LogIO is intended to be used in a way similar to the ostream class.
00066 // However, rather than sending it's output to a file or stdout, it bundles
00067 // its output up into <linkto class=LogMessage>LogMessage</linkto> objects 
00068 // and posts them to a <linkto class=LogSink>LogSink</linkto>.
00069 //
00070 // When you use the "<<" operator on a LogIO, you are building up a log message
00071 // inside the LogIO object. The message is posted when:
00072 // <ol>
00073 //    <li> <src>LogIO::post()</src> is called
00074 //    <li> You send the <src>LogIO::POST</src> or <src>LogIO::EXCEPTION</src>
00075 //         commands to the LogIO with the shift (<src> << </src>) command.
00076 //    <li> The LogIO object is destructed.
00077 // </ol>
00078 // Note that log messages may span multiple lines, so sending the LogIO a
00079 // newline (via "\n" or endl) does not force the message to be emitted.
00080 // </synopsis>
00081 //
00082 // <example>
00083 // A LogIO may be created in the following ways:
00084 // <srcblock>
00085 //    LogIO   os;
00086 // </srcblock>
00087 // Here, <src>os</src> is attached to the global log sink, and no origin
00088 // information is set.
00089 //
00090 // <srcblock>
00091 //    TableLogSink tab(...);
00092 //    LogIO   os(tab);
00093 // </srcblock>
00094 // Here, <src>os</src> is attached to <src>tab</src> (and also to the global
00095 // log sink since every sink's <src>post</src> also calls the global sink's
00096 // <src>post</src>).
00097 //
00098 // 
00099 // <srcblock>
00100 //    LogIO   os(LogOrigin("class", "func(args)", WHERE));
00101 // </srcblock>
00102 // Here, <src>os</src> is attached to the global sink and the origin
00103 // information is set to <src>class::func(args)</src> and the line number and
00104 // source file information is set (with <src>WHERE</src>).
00105 //
00106 // <srcblock>
00107 //    TableLogSink tab(...);
00108 //    LogIO   os(LogOrigin("class", "func(args)", WHERE), tab);
00109 // </srcblock>
00110 // Here all the above information is set.
00111 //
00112 // Once you have a <src>LogIO</src>, using it is pretty simple:
00113 // <srcblock>
00114 //   os << "Every good boy deserves" << 5 << " pieces of fudge!";
00115 // </srcblock>
00116 // This accumulates the message but does not send it. If you want to force it
00117 // to be sent you can do so with either of the following methods:
00118 // <srcblock>
00119 //    os << LogIO::POST;     // From the Commands enum
00120 //    os.post();             // Member function
00121 // </srcblock>
00122 // Note that after a post the priority is reset to NORMAL.
00123 //
00124 // If you want to change the level of the message you can also do so with the
00125 // shift operator:
00126 // <srcblock>
00127 //   os << LogIO::DEBUGGING << "Boring message" << 
00128 //         LogIO::SEVERE << "Error!" << LogIO::POST;
00129 // </srcblock>
00130 // Note that changing the priority changes the priority of the entire
00131 // message. The message does not get posted until the POST is done.
00132 // So in the above example the DEBUGGING priority does not do anything
00133 // because the priority is overwritten by the SEVERE one.
00134 //
00135 // You can also change the origin information with the << operator:
00136 // <srcblock>
00137 //    os << LogOrigin("class", "func(args)");
00138 //    os << WHERE;
00139 // </srcblock>
00140 //
00141 // A class which has an operator<< to std::ostream but not LogIO can be handled
00142 // like so:
00143 // <srcblock>
00144 // os << LogIO::SEVERE << " at ";
00145 // os.output() << MEpoch::Convert(time_p, MEpoch::Ref(MEpoch::UTC))();
00146 // os << LogIO::POST;
00147 // </srcblock>
00148 // </example>
00149 //
00150 // <motivation>
00151 // The earlier method of creating log messages solely through LogSink and
00152 // LogMessage required the programmer to type in more lines of code than
00153 // this solution. Also, this interface makes it easy to drop log messages
00154 // into existing code that uses ostreams.
00155 // </motivation>
00156 //
00157 // <todo asof="1997/01/29">
00158 //   <li> Add << operators for all classes that have ostream<< defined.
00159 //        (We could probably do it with a template, but might result
00160 //        in ambiguity).
00161 //   <li> Have a function for changing the LogSink only? (You can get
00162 //        much the same effect with operator=).
00163 //        them?
00164 // </todo>
00165 
00166 class LogIO
00167 {
00168 public:
00169     // Special commands to the LogIO object
00170     enum Command {
00171         // Post the accumulated message. Equivalent to calling LogIO::post().
00172         POST, 
00173         // Post the accumulated message then throw an exception.
00174         // Always posts the message at SEVERE priority. Equivalent to calling 
00175         // LogIO::postThenThrow().
00176         EXCEPTION, 
00177         // Change the message priority to SEVERE.
00178         SEVERE, 
00179         // Change the message priority to WARN.
00180         WARN, 
00181         // Change the message priority to NORMAL.
00182         NORMAL, 
00183         NORMAL1, 
00184         NORMAL2, 
00185         NORMAL3, 
00186         NORMAL4, 
00187         NORMAL5, 
00188         // Change the message priority to DEBUGGING.
00189         DEBUG1,
00190         DEBUG2,
00191         DEBUGGING};
00192 
00193     // Attach this LogIO object to the global sink with no origin information.
00194     LogIO();
00195     // Attach this LogIO object to the supplied sink. A referencing copy of
00196     // the sink is made inside the LogIO object, so you do not need to worry
00197     // about memory management.
00198     LogIO(LogSink &sink);
00199     // Attach this LogIO object to the supplied origin and global sink.
00200     LogIO(const LogOrigin &OR);
00201     // Attach this LogIO object to the supplied origin and sink.
00202     LogIO(const LogOrigin &OR, LogSink &sink);
00203     
00204     // Copying uses reference semantics, i.e. the same sink will be shared
00205     // by both copies.
00206     // <group>
00207     LogIO(const LogIO &other);
00208     LogIO &operator=(const LogIO &other);
00209     // </group>
00210 
00211     // The destructor will post any accumulated message that has not already
00212     // been posted.
00213     ~LogIO();
00214     
00215     // Post the accumulated message.  If you wish, you can post the messages
00216     // only locally to the sink.
00217     // After the post the priority is reset to NORMAL.
00218     void post();
00219     void post(LogMessage &amess);
00220 
00221     // Post the accumulated message locally.
00222     // After the post the priority is reset to NORMAL.
00223     void postLocally();
00224 
00225     // Post the accumulated message at SEVERE priority and then throw an
00226     // exception.
00227     // After the post the priority is reset to NORMAL.
00228     template<typename EXC> void postThenThrow (const EXC& exc)
00229       { preparePostThenThrow(exc); sink_p.postThenThrow (msg_p, exc); }
00230 
00231     // Change the priority of the message. It does NOT post the accumulated
00232     // message at the old priority first.
00233     void priority(LogMessage::Priority which);
00234     LogMessage::Priority priority();
00235     // Change the location in the origin. Almost always this is called with the
00236     // macro WHERE as its argument.
00237     void sourceLocation(const SourceLocation *where);
00238     // Change the origin of the accumulated message.
00239     void origin(const LogOrigin &origin);
00240 
00241     // Acumulate output in this ostream.
00242     ostream& output();
00243 
00244     // Occasionally it is useful to interrogate the local log sink.
00245     LogSinkInterface &localSink();
00246     const LogSinkInterface &localSink() const;
00247 
00248 private:
00249     // Prepare message stream for postThenThrow function.
00250     void preparePostThenThrow (const AipsError& x);
00251 
00252     LogSink sink_p;
00253     LogMessage msg_p;
00254     ostringstream *text_p;
00255 
00256 };
00257 
00258 // <summary>
00259 // Functions to send commands to a LogIO object.
00260 // </summary>
00261 // The following commands don't change the accumulated message, rather they
00262 // send commands to the LogIO object, either to:
00263 // <ol>
00264 //   <li>post the current message: <src>os << "message" << LogIO::POST;</src>
00265 //   <li>post the current message and then throw an exception: 
00266 //       <src>os << "error" << LogIO::EXCEPTION;</src>
00267 //   <li> Change the priority of the current message:
00268 //        <src>os << LogIO::DEBUGGING;</src>
00269 //   <li> Change the origin of the message:
00270 //        <srcblock>
00271 //          os << LogOrigin(...);
00272 //          os << WHERE;             // Changes only source file/line number
00273 //        </srcblock>
00274 // </ol>
00275 // <group name=command>
00276 LogIO &operator<<(LogIO &os, LogIO::Command item);
00277 LogIO &operator<<(LogIO &os, const SourceLocation *item);
00278 LogIO &operator<<(LogIO &os, const LogOrigin &OR);
00279 // </group>
00280 
00281 // <summary>
00282 // Functions to accumulate text in the output message.
00283 // </summary>
00284 // Accumulate text in the output message. The last entry is for things like 
00285 // <src>endl</src>.
00286 // <group name=output>
00287 LogIO &operator<<(LogIO &os, const String &item);
00288 LogIO &operator<<(LogIO &os, const char *item);
00289 LogIO &operator<<(LogIO &os, Double item);
00290 LogIO &operator<<(LogIO &os, Complex item);
00291 LogIO &operator<<(LogIO &os, DComplex item);
00292 LogIO &operator<<(LogIO &os, Int item);
00293 LogIO &operator<<(LogIO &os, uInt item);
00294 LogIO &operator<<(LogIO &os, uLong item);
00295 LogIO &operator<<(LogIO &os, Long item);
00296 LogIO &operator<<(LogIO &os, Bool item);
00297 LogIO &operator<<(LogIO &os, ostream &(*item)(ostream &));
00298 // </group>
00299 
00300 inline LogSinkInterface &LogIO::localSink()
00301 {
00302     return sink_p.localSink();
00303 }
00304 
00305 inline const LogSinkInterface &LogIO::localSink() const
00306 {
00307     return sink_p.localSink();
00308 }
00309 
00310 
00311 } //# NAMESPACE CASA - END
00312 
00313 #endif