#include "Utility/ExH/Compound.hpp"
#include "Utility/ExH/System/Exception.hpp"
#include "Utility/ExH/Logic/DescriptiveException.hpp"
#include "Utility/ExH/StringStreamConverter.hpp"
#include <iostream>
using std::cerr;
using std::endl;
using std::string;
using std::ostringstream;
using namespace Utility::ExH;
class Base
{
public:
  class Exception_ {};
  typedef
  Compound <Exception_, Logic::DescriptiveException>
  Exception;
  class InvalidArgument_ {};
  typedef
  Compound <InvalidArgument_, Exception>
  InvalidArgument;
  class NotInitialized_ {};
  typedef
  Compound <NotInitialized_, Exception>
  NotInitialized;
public:
  void
  foo (char const* str) throw (InvalidArgument, NotInitialized)
  {
    if (str == 0)
    {
      throw InvalidArgument ("Base::foo: first parameter is zero.");
    }
    else
    {
      ostringstream ostr;
      ostr << "Base::foo [this = " << this << "]: object is not initialized.";
      throw NotInitialized (ostr);
    }
  }
  virtual void
  vfoo () throw (Exception, System::Exception) = 0;
};
class Derived : public Base
{
public:
  class NotImplemented_ {};
  typedef
  Compound <NotImplemented_, Exception>
  NotImplemented;
public:
  virtual void
  vfoo () throw (NotImplemented, System::Exception)
  {
    std::string str ("Derived::vfoo: not implemented yet.");
    throw NotImplemented (str);
  }
};
int
main ()
{
  try
  {
    Derived d;
    Base* pb (&d);
    try
    {
      pb->vfoo ();
    }
    catch (Base::Exception const& ex)
    {
      cerr << "Caught Base::Exception: " << ex.what () << endl;
    }
    try
    {
      pb->foo ("hello");
    }
    catch (Base::NotInitialized const& ex)
    {
      cerr << "Caught Base::NotInitialized: " << ex.what () << endl;
    }
    pb->foo (0);
  }
  catch (Logic::Exception const& ex)
  {
    cerr << "Caught Logic::Exception: " << ex.what () << endl;
  }
  catch (...)
  {
    cerr << "Caught unknown exception using catch-all handler" << endl;
    return -1;
  }
}