#if   !defined(__COMMANDFRAME_HPP)
#define  __COMMANDFRAME_HPP

/*
  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(__ABSTRACTCOMMAND_HPP)
#include <AbstractCommand.hpp>
#endif

#if   !defined(__VECTOR_HPP)
#include <Vector.hpp>
#endif

#if   !defined(__COMMANDFRAMEEXCEPTION_HPP)
#include <CommandFrameException.hpp>
#endif

namespace corelinux
{
   CORELINUX_VECTOR(  AbstractCommandPtr ,  Commands );

   DECLARE_CLASS( CommandFrame );

   /**
   State of execution
   */

   enum  WorkState
   {
      /// The state is in building, no work has been performed

      BUILDING = 0,
      EXECUTING,
      COMPLETED,
      REVERSING,
      REVERSED,
      NEVERCOMPLETED
   };

   /**
   CommandFrame builds a unit of work around one
   or more Commands. It maintains state and can
   be flagged to auto recover (reverse) the command
   effects.
   */

   class CommandFrame : public Synchronized
   {

   public:

      //
      // Constructors and destructor
      //
                        /// Default Constructor

                        CommandFrame( bool autoReverse = false );

                        /**
                        Copy constructor
                        @param CommandFrame another CommandFrame reference
                        @exception CommandFrameException if the state
                        of the argument is not BUILDING, COMPLETED, or
                        REVERSED. The state of this CommandFrame is set
                        to BUILDING
                        */

                        CommandFrame( CommandFrameCref )
                           throw( CommandFrameException );

                        /**
                        Virtual destructor. Clears the
                        colleciton of commands from the
                        list. DOES NOT DESTROY THEM!!!
                        */

      virtual           ~CommandFrame( void );      

      //
      // Operator overloads
      //

               /**
               Operator assignment. The commands from
               the argument replace the commands in the
               current CommandFrame.
               @param CommandFrame const reference
               @return CommandFrame reference to self
               @exception CommandFrameException if not building
               */

               CommandFrameRef   operator=( CommandFrameCref )
                  throw( CommandFrameException );

               /// Equality operator

               bool  operator==( CommandFrameCref ) const;

      //
      // Accessors
      //

               /**
               Retrieves the state of the frame
               @return WorkState
               */

               WorkState   getState( void ) const;

               /**
               Retrieves the auto reverse flag
               @return bool true if autoreverse enabled
               */

               bool  getReverseFlag( void ) const;

               /**
               Retrieves the commands into a Command 
               collection
               @param Commands reference
               */

      virtual  void  getCommands( CommandsRef ) const;

      //
      // Mutators
      //

               /**
               Operator overload for adding a command
               @param AbstractCommand pointer
               @return CommandFrame reference
               @exception CommandFrameException if not building
               or pointer is NULLPTR
               */

               CommandFrameRef   operator+=( AbstractCommandPtr )
                  throw( CommandFrameException );

               /**
               Operator overload for appending commands from
               another CommandFrame to the current frame
               @param CommandFrame const reference
               @return CommandFrame reference to self
               @exception CommandFrameException if not building
               */

               CommandFrameRef   operator+=( CommandFrameCref )
                  throw( CommandFrameException );

               /**
               Explicit call to add command
               @param AbstractCommand pointer
               @exception CommandFrameException if not building
               or pointer is NULLPTR
               */

      virtual  void  addCommand( AbstractCommandPtr )
                  throw( CommandFrameException );


               /**
               Sets the auto reverse flag
               @param bool true to auto recover from exceptions
               @exception CommandFrameException if not building
               */

               void  setAutoReverse( bool ) throw( CommandFrameException );

               /**
               Run the frame which will iterate through
               the commands, calling execute for each on.
               The state must be BUILDING, which will change to
               COMPLETED if all goes well, REVERSED if auto reverse is true
               and there was a need to roll-back the commands, or
               NEVERCOMPLETED if auto reverse if false.         
               @exception CommandFrameException if state not BUILDING
               */

               void  execute( void ) throw( CommandFrameException );

               /**
               Run the reverse commands. The state must be COMPLETED for 
               this to work. You can reverse a CommandFrame even if the
               auto reverse command is off. The state, upon valid completion
               will be REVERSED or NEVERCOMPLETED in case of error
               @exception CommandFrameException if state not COMPLETED
               */

               void  executeReverse( void ) throw( CommandFrameException );

   protected:

               /**
               Called from execute AFTER the state is set to
               EXECUTING and a synchronized monitor is created.
               @return WorkState indicating the last state of
               execution.
               */

      virtual  WorkState   executeCommands( void );

               /**
               Called from executeReverse AFTER the state is set to
               REVERSING and a synchronized monitor is created.
               @return WorkState indicating the last state of
               execution.
               */

      virtual  WorkState   executeReverseCommands( void );

   protected:

               /// The recovery flag

               bool        theAutoReverseFlag;

               /// The state of execution

               WorkState   theWorkState;

               /// The Commands that make up the frame
         
               Commands   theCommands;
   };
}

#endif // if !defined(__COMMANDFRAME_HPP)

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



