/*
  CoreLinux++ 
  Copyright (C) 2000 CoreLinux Consortium
  
   The CoreLinux++ Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The CoreLinux++ Library Library is distributed in the hope that it will 
   be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  
*/   

/** \example examp17.cpp
   This example is to show use of Chain Of Responsibility pattern.
   
   1. Declare and define various handlers and requests
   2. Create requets
   3. Pass it to the chain head
*/                   


#include <corelinux/Common.hpp>
#include <RequestHelpHandler.hpp>
#include <HandlerHelpHandler.hpp>

using namespace corelinux;
using namespace std;

#include <iostream>
#include <exception>

//
// In module function prototypes
//

int   main( void );
void  addHelpHandler( HelpHandlerPtr );
void  callHandler( HelpRequestPtr );

//
// General Functions 
//

void  handleAssertion( AssertionCref );
void  handleException( ExceptionCref );

//
// Global data
//

//
// Main entry point
//


int main( void )
{

   cout << endl;

   //
   // Practice graceful exception management
   //


   try
   {

      // Create and register our handler types

      RequestHelpHandler   aRequestHandler;

      addHelpHandler( &aRequestHandler );

      HandlerHelpHandler   aHandlerHandler;

      addHelpHandler( &aHandlerHandler );

      // Call requests

      HelpRequest aRequestRequest( REQUEST_HELP );

      callHandler(&aRequestRequest);

      HelpRequest aHandlerRequest( HANDLER_HELP );

      callHandler(&aHandlerRequest);

      // Test the unknown

      HelpRequest aUnknownRequest( UNKNOWN_HELP );      

      callHandler(&aUnknownRequest);
   }

   catch( AssertionRef aAssert )
   {
      handleAssertion(aAssert);
   }
   catch( ExceptionRef aException )
   {
      handleException(aException);
   }
   catch( std::exception & e )
   {
      cerr  << e.what() << endl;
   }
   catch( ... )
   {
      cerr  << "Unknown exception." << endl;
   }

   return 0;               
}

// Setup the chain of responsibility root
// and perform adding to the chain

static   HelpHandlerPtr aRoot( NULLPTR );

void  addHelpHandler( HelpHandlerPtr aHandler )
{
   if( aRoot != NULLPTR )
   {
      aHandler->succeedHandler( aRoot );
   }
   else
   {
      aRoot = aHandler;
   }
}

//
// Handle the request, exception if unhandled
//

void  callHandler( HelpRequestPtr aRequest )
{
   if( aRoot != NULLPTR )
   {
      aRoot->handleRequest( aRequest );
      if( aRequest->wasHandled() == false )
      {
         cout << "Unhandled request [" << *aRequest << "] " << endl;
      }
      else
      {
         ;  // do nothing
      }
   }
   else
   {
      NEVER_GET_HERE;
   }
}

//
// Error handlers
//

void  handleAssertion( AssertionCref aAssert )
{
   cerr << aAssert.getFile() << ":" << aAssert.getLine() << ":" << 
      "Assertion: ";

   if( aAssert.getType() == Assertion::NEVERGETHERE )
   {
      cerr << "NEVER_GET_HERE";
   }
   else
   {
      if( aAssert.getType() == Assertion::REQUIRE )
      {
         cerr  << "REQUIRE";
      }
      else if( aAssert.getType() == Assertion::ENSURE )
      {
         cerr  << "ENSURE";
      }
      else if( aAssert.getType() == Assertion::CHECK )
      {
         cerr  << "CHECK";
      }
      else 
      {
         cerr  << "ASSERT";
      }
      cerr << "( " << aAssert.getWhy() << " )";
   }

   cerr << endl;
}

void  handleException( ExceptionCref aExcp )
{
   cerr << aExcp.getFile() << ":" << aExcp.getLine() << ":" <<
      "Exception: " << aExcp.getWhy() << endl;
}

/*
   Common rcs information do not modify
   $Author: prudhomm $
   $Revision: 1.2 $
   $Date: 2000/08/31 22:49:02 $
   $Locker:  $
*/


