Sunday, October 21, 2007

Exception using Map an example

Here i will explain exception handling with map template.


Though i prefer a proper class hiearachy for exception handling . But this one also an interesting one.
I need 4 class to explain tis , we can take few less or more then i take.

one enum type we declare which contains the exception type like SUCCESS ,FAILURE ,LOGINFAILURE etc.
Just define this in a .h file called ExceptionType.h
These are the contentent of this ExceptionType.h file
enum ExceptionType
{
SUCCESS = 0, // apps execution is success
LOGINFAIL = 101, // Login Failed
FAIL, // Failed executing
UNKNOWN // Unknown Exception
};


Now we will discuss one more container class (this will map all the exception which we have defined in exceptionType.h)
example
Let say this container class called EnumString.h
// Local Headers
#include "ExceptionType.h"

using namespace std;

// Class Definition
template < class T >
class EnumString
{
public:
// Default Constructor
EnumString< T >();

// Destructor
~EnumString< T >() {}

// Explicit Constructor
explicit EnumString< T >( const T value );// Get method for retreiving value
const T getValue() const
{
return _value;
}

// Get method for retreiving Name
const string& getName() const
{
return _stringMap[_value];
}

// Class Name retrieval method
static const char* className() { return "EnumString"; }


private:
// Method to Container
static void populate();
// Method to set Unknown Exception value into container
static void setUnknownValue();

// Method to get Unknown Exception value from container
static T getUnknownValue();

T _value; // Enum type value
static map< T, string, less< T > > _stringMap;// Container for Enum types
};

template < class T >
map< T, string, less< T > > EnumString< T >::_stringMap;

// Default Constructor
template '<' class T'>'
EnumString'<'T'>'::EnumString()
{
// Do Nothing
}
template '<'class T'>'
EnumString'<'T'>'::EnumString( const T value ) : _value(value)
{

// Check for container empty
if ( _stringMap.size() == 0 )
{
populate();
}

// Check Exception is present in Container
if ( _stringMap.find(value) == _stringMap.end() )
{
// This can occur if the Exception is not defined in the
// omexcpdefs.h and that is thrown from the application
// For this case set "UnKnown Exception" into Container
// And into the KeyType value
_value = getUnknownValue();
setUnknownValue();
}



} // end of EnumString'<'T'>'::EnumString()






template '<'class T'>'
EnumString'<'T'>'::EnumString( const T value ) : _value(value)
{

// Check for container empty
if ( _stringMap.size() == 0 )
{
populate();
}

// Check Exception is present in Container
if ( _stringMap.find(value) == _stringMap.end() )
{
// This can occur if the Exception is not defined in the
// omexcpdefs.h and that is thrown from the application
// For this case set "UnKnown Exception" into Container
// And into the KeyType value
_value = getUnknownValue();
setUnknownValue();
}


} // end of EnumString'<'T'>'::EnumString()

template '<'class ExceptionType'>'
void EnumString'<'ExceptionType'>'::populate()
{

// Add all the Known exceptions
_stringMap[SUCCESS] = " SUCCESS DONE";
_stringMap[LOGINFAIL] = " LOGIN FAILED";
_stringMap[FAIL] = " EXECUTION FAILED";


} // end of EnumString::populate()



template '<'class ExceptionType'>'
void EnumString'<'ExceptionType'>'::setUnknownValue()
{
// Update Unknown exceptions
_stringMap[UNKNOWN] = " UNKNOWN ERROR";

} // end of EnumString'<'ExceptionType'>'::setUnknownValue()

template '<'class ExceptionType'>'
void EnumString'<'ExceptionType'>'::setUnknownValue()
{
// Update Unknown exceptions
_stringMap[UNKNOWN] = "UNKNOWN ERROR";

} // end of EnumString'<'ExceptionType'>'::setUnknownValue()

Now I have defined the container class , this class actually maped the error and all thye stufs...
Now i will define a class which will have a data member of type this container class. This class i have defined for one more level
of indirection.

lets define the class as MyException. and the file name MyException.h
#ifndef MYEXCEPTION_H
#define MYEXCEPTION_H
#include "EnumString.h"
// Class Definition
template '<'class T'>'
class MyException
{
public:
// Default Constructor
MyException < T >();

// Destructor
~MyException'<'T'>'() {}

// Explicit Constructor
explicit MyException( T err ) : _ExpMap(err){}

private:

protected:
EnumString < T > _ExpMap;
};

// Default constructor
template '<'class T'>'
MyException'<'T''>'::MyException()
{
// Do Nothing
}

#endif /* MYEXCEPTION_H */



Then I will define the application class where i will use this , I mean inherit this MyException class .Just have a look
#ifndef APPEXCEPTION_H
#define APPEXCEPTION_H
#include "ExceptionType.h"
#include "MyException.h"
#include

// Class Definition
class AppException : public MyException
{
public:
// Default Constructor
AppException() {}

// Destructor
~AppException() {}

// Explicit Constructor
explicit AppException( ExceptionType expNum )
: MyException(expNum)
{
}

// Method to get Exception Description
const string& getExpName() const
{
return ( _ExpMap.getName() );
}

// Class Name retrieval method
const char* className() { return "AppException"; }

};

#endif /* APPEXCEPTION_H */


So if i want to through an exception of particular type, Just create the object of this type and through it.
Below the unit test code



#include
#include "MyException.h"
#include "appException.h"

int main()
{

for ( int i=0; i != 4; i++ )
{
try
{
if ( i == 0 )
throw AppException(SUCCESS);

if ( i == 1 )
throw AppException(LOGINFAIL);

if ( i == 2 )
throw AppException(FAIL);

if ( i == 3 )
throw AppException((ExceptionType)300);


}
catch ( AppException &exp )
{
cout << "Caught Exception: "'< <' exp.getExpName() << endl;
}
}
return ( 0 );
}

No comments: