This section contains the necessary components to set up a framework for augmented exceptions. Although this page does contain enough information to get started, it may be more easily understood (and definitely more useful) once one is familiar with setting up error logs.
Declare a ZMexAugmented exception class at global scope with some sort of extraObj:
//When deriving from a regular ZMexception use ZMexAugmented<>
#include "ErrLogEx/ZMexAugmented.h"
typedef ZMexAugmented<ZMexception, point> overQuota; //point is my extraObj
//When deriving from a ZMexAugmented<> use ZMexDerivedAug<>
#include "ErrLogEx/ZMexDerivedAug.h"
typedef ZMexDerivedAug<overQuota> whoopsee; //derive from overQuota class
typedef ZMexDerivedAug<whoopsee> whoopseedaisy; //derive from whoopsee
Notice that these derived classes only take one argument and will have the
same type for their extraObj as their parent class (in this case a
'point').
Once all the classes are declared you can #include the physicist's module. Be careful not to include it before these declaration or the physicist's code will not know about them and won't be able to throw them.
An ELadministrator must be created, and the output of the exceptions
may be sent to log files or to an ostream via the attach function. The syntax
is the same as
setting up an ErrorLogger.
Here are the minimum requirements to log an augmented exception to cout and a
file whenever the exception is ZMthrow'n :
#include "ErrorLogger/ELadministrator.h"
#include "ErrorLogger/ELoutput.h"
int main() {
ELadministrator* logger = ELadministrator::instance();
logger->attach(ELoutput(std::cout)); //output logs to cout
logger->attach(ELoutput("filename.log")); //and to file "filename.log"
//...
}
Because the extra object can be of any type, the handler must know how to deal with it. Thus, a new handler class derived from ZMexHandlerBehavior must be created by the frameworker. It should #include the file that has the declarations of the augmented exception classes. Here is what the constructor should look like:
class ZMexAugHandler : public ZMexHandlerBehavior {
public:
ZMexAugHandler() : ZMexHandlerBehavior( "ZMexAugHandler" ) { }
//...
}
The handler requires a clone( ) function that must look like this:
virtual ZM_COVARIANT_TYPE(ZMexHandlerBehavior,ZMexAugHandler)*
clone() const { return new ZMexAugHandler( *this ); }
The most important function of the handler class is takeCareOf( ). It
determines if its argument is actually an augmented exception, and it
examines or alters the extra object. This function can also determine whether
the exception should be logged at all.
virtual ZMexAction takeCareOf( const ZMexception & x ) {
if (!(overQuota::isBaseOf(x))) //is x an augmented exception?
return standardHandling( x, //if not, log exception the regular way
true ); //and throw it
overQuota& blah = (overQuota&) x; //convert x to an augmented exception
point& p = blah.extraObj; //access its extraObj
ErrorObj& o = blah.getErrorObj(); //access its ErrorObj
//do whatever you want with it here. Maybe put extraObj into your log:
o << "x-coord =" << p.x << " y-coord =" << p.y;
if( p == origin )
return standardHandling( x, //log exception in the regular way
false ); //and do not throw it
else return ZMexIgnoreIt; //don't even log it
}
The standardHandling function shown above takes an exception as its first
argument and a bool for its second argument. It calls the exception's
ZMexLogger, and the bool determines whether the exception should be thrown
(true) or not (false). If for some reason the frameworker does not want the
exception to be logged by the ZMexLogger he/she can just return either
ZMexIgnoreIt which will continue with the program or ZMexThrowIt which will
exit the program (neither of which will log the exception).
The constructor and the two functions above are required in your handler. takeCareOf( ) will have some other content in order to deal with the user's extra object while everything else should only differ in name.
Most of the modifications to the output of an augmented exception log can be accomplished in the same manner one would modify an ErrorLogger log, but here are a few particularly helpful tips.
#include "ErrorLogger/ELdestControl.h" /... ELdestControl dest=logger->attach(ELoutput(std::cout)); dest.suppressTime();Other formatting control options are found in the ErrorLogger Package.
ELstatistics stats(cout); stats->summary(dest);For other summary options and a description of the summary output take a look at the summary information in the ErrorLogger Package.