/*
  CoreLinux++ 
  Copyright (C) 1999,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.  
*/   

#if   !defined(__COMMON_HPP)
#include <Common.hpp>
#endif

#if   !defined(__HANDLER_HPP)
#include <Handler.hpp>
#endif

namespace   corelinux
{
   // Default constructor

   Handler::Handler( void )
      :
      Synchronized(),
      theSuccessor( NULLPTR ),
      thePredecessor( NULLPTR )
   {
      ;  // do nothing else for the moment
   }

   // Copy constructor

   Handler::Handler( HandlerCref aHandler )
      :
      Synchronized( aHandler ),
      theSuccessor( NULLPTR ),
      thePredecessor( NULLPTR )
   {
      ;  // do nothing else for the moment
   }

   // Destructor will handle removing itself
   // from the chain if needed

   Handler::~Handler( void )
   {
      this->extractSelf();
   }

   // Assignment operator

   HandlerRef  Handler::operator=( HandlerCref )
   {
      return ( *this );
   }

   // Equality operator

   bool Handler::operator==( HandlerCref aHandler ) const
   {
      return ( this == &aHandler );
   }

   // Retrieve successor operator overload

   HandlerPtr  Handler::operator++( void ) 
   {
      GUARD;
      return theSuccessor;
   }

   // Retrieve the predecessor

   HandlerPtr  Handler::operator--( void ) 
   {
      GUARD;
      return thePredecessor;
   }

   // Inserts self after handler

   void  Handler::succeedHandler( HandlerPtr aHandler ) 
      throw ( Assertion )
   {
      REQUIRE( aHandler != NULLPTR );
      REQUIRE( aHandler != this );
      REQUIRE( theSuccessor == NULLPTR );
      REQUIRE( thePredecessor == NULLPTR );

      GUARD;

      // Double-linked list behavior

      //
      // Get the existing successor for the target
      // if none exists, do nothing, otherwise
      // make the existing one our successor.
      //

      HandlerPtr  existingLink( ++(*aHandler) );

      if( existingLink == NULLPTR )
      {
         ;  // do nothing, taken care of later
      }
      else if( existingLink != this )
      {
         existingLink->setPredecessor(this);
         theSuccessor = existingLink;
      }
      else
      {
         NEVER_GET_HERE;
      }

      //
      // Let target know we succeed it and
      // let ourselves know our predeccessor.
      //

      aHandler->setSuccessor(this);
      thePredecessor = aHandler;
   }

   // Insert self before handler

   void  Handler::precedeHandler( HandlerPtr aHandler ) 
      throw ( Assertion )
   {
      REQUIRE( aHandler != NULLPTR );
      REQUIRE( aHandler != this );
      REQUIRE( theSuccessor == NULLPTR );
      REQUIRE( thePredecessor == NULLPTR );

      GUARD;

      // Double-linked list behavior

      //
      // Get the existing predecessor for the target
      // if none exists, do nothing, otherwise
      // make the existing one our predeccessor
      //

      HandlerPtr  existingLink( --(*aHandler) );

      if( existingLink == NULLPTR )
      {
         ;  // do nothing, taken care of later
      }
      else if( existingLink != this )
      {
         existingLink->setSuccessor(this);
         thePredecessor = existingLink;
      }
      else
      {
         NEVER_GET_HERE;
      }

      //
      // Make us the predeccessor of the target
      // and let us know our successor
      //

      aHandler->setPredecessor(this);
      theSuccessor = aHandler;
   }

   // Removes ourselves from the chain

   void  Handler::extractSelf( void )
   {
      GUARD;

      if( theSuccessor != NULLPTR )
      {
         theSuccessor->setPredecessor( thePredecessor );
      }
      else
      {
         ;  // do nothing
      }

      if( thePredecessor != NULLPTR )
      {
         thePredecessor->setSuccessor( theSuccessor );
      }
      else
      {
         ;  // do nothing
      }

      theSuccessor = thePredecessor = NULLPTR;
   }

   // Either handle the request, pass it on, or ???

   void  Handler::handleRequest( RequestPtr aRequest ) 
   {
      if( this->handlesType( aRequest ) == true )
      {
         this->handle( aRequest );
      }
      else
      {
         if( ++(*this) != NULLPTR )
         {
            (++(*this))->handleRequest( aRequest );
         }
         else
         {
            ;  // unhandled request exception?
         }
      }
   }

   // Protected access to member

   void  Handler::setSuccessor( HandlerPtr aHandler ) 
   {
      GUARD;
      theSuccessor = aHandler;
   }

   // Sets the objects thePredecessor member

   void  Handler::setPredecessor( HandlerPtr aHandler ) 
   {
      GUARD;
      thePredecessor = aHandler;
   }

   // Sets the object siblings as atomic operation

   void  Handler::setSiblings( HandlerPtr aSuccessor, HandlerPtr aPredecessor )
   {
      GUARD;
      theSuccessor = aSuccessor;
      thePredecessor = aPredecessor;
   }
}

/*
   Common rcs information do not modify
   $Author: frankc $
   $Revision: 1.2 $
   $Date: 2000/06/06 12:04:12 $
   $Locker:  $
*/

