#if   !defined(__MAZEFACTORY_HPP)
#define __MAZEFACTORY_HPP

/*
  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.  
*/   


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

#if   !defined(__ABSTRACTFACTORY_HPP)
#include <AbstractFactory.hpp>
#endif

#if   !defined(__ALLOCATOR_HPP)
#include <Allocator.hpp>
#endif

#if   !defined(__MAP_HPP)
#include <Map.hpp>
#endif

#if   !defined(__NAMEIDENTIFIER_HPP)
#include <NameIdentifier.hpp>
#endif

#if   !defined(__DOOR_HPP)
#include <Door.hpp>
#endif

#if   !defined(__ROOM_HPP)
#include <Room.hpp>
#endif

#if   !defined(__WALL_HPP)
#include <Wall.hpp>
#endif


//
// We use a map for storing our allocators. We could have fire-walled this
// as well.
//

CORELINUX_MAP( 
   NameIdentifier, 
   CORELINUX(AllocatorPtr), 
   less<NameIdentifier>,
   NamedAllocators
);


/**
Maze Factory creates Rooms, Doors, and Walls. It is a AbstractFactory
that uses a NameIdentifier as a key association to the respective 
Allocators (DoorAllocator, etc.).
We use protected inheritence for the AbstractFactory because we are not
interested letting the application have to do the work, they just need
to create things!
*/

DECLARE_CLASS( MazeFactory );

class MazeFactory : protected CORELINUX(AbstractFactory<NameIdentifier>)
{
public:

   //
   // Constructors and destructor
   //

                        /// Default constructor

                        MazeFactory( void );

                        /// Copy constructor

                        MazeFactory( MazeFactoryCref );

                        /// Virtual Destructor

   virtual              ~MazeFactory( void );

   //
   // Operator overloads
   //

            /// Assignment operator

            MazeFactoryRef operator=( MazeFactoryCref ) 
                              throw(CORELINUX(Exception));

            /// Equality operator

            bool  operator==( MazeFactoryCref ) const;

   //
   // Accessors
   //

            /// Return number of allocators registered

            CORELINUX(Count)  getAllocatorCount( void ) const;

            /// Return some instrumentation for this Factory

            CORELINUX(Count)  getTotalAllocates( void ) const;

            /// Return some instrumentation for this Factory

            CORELINUX(Count)  getTotalDeallocates( void ) const;

   //
   // Factory methods
   //

            /// Create a Room and give it a number

   virtual  RoomPtr     createRoom( RoomNumberCref ) const
                           throw(CORELINUX(AllocatorNotFoundException));

            /// Create a Wall

   virtual  WallPtr     createWall( void ) const
                           throw(CORELINUX(AllocatorNotFoundException));

            /// Create a door joining two rooms

   virtual  DoorPtr     createDoor( RoomPtr, RoomPtr ) const
                           throw(CORELINUX(AllocatorNotFoundException));

            /// Destroy a Room

   virtual  void        destroyRoom( RoomPtr ) const
                           throw(CORELINUX(AllocatorNotFoundException));

            /// Destroy a Wall

   virtual  void        destroyWall( WallPtr ) const
                           throw(CORELINUX(AllocatorNotFoundException));

            /// Destroy a Door

   virtual  void        destroyDoor( DoorPtr ) const
                           throw(CORELINUX(AllocatorNotFoundException));


protected:

   //
   // Accessors overriden from AbstractFactory
   //

            /// Get the total MapSite objects created

   virtual  CORELINUX(Count)  getCreateCount( void ) const;

            /// Get the total MapSite objects destroyed

   virtual  CORELINUX(Count)  getDestroyCount( void ) const;

            /// Get the allocator identifier by NameIdentifier

   virtual  CORELINUX(AllocatorPtr) getAllocator( NameIdentifier ) const
                        throw(CORELINUX(AllocatorNotFoundException));

   //
   // Mutators overriden from AbstractFactory
   //

            /// Add a allocator to the factory

   virtual  void  addAllocator( NameIdentifier, CORELINUX(AllocatorPtr) )
                        throw(CORELINUX(AllocatorAlreadyExistsException));

            /// Remove the allocator from the factory and return to the
            /// caller

   virtual  CORELINUX(AllocatorPtr) removeAllocator( NameIdentifier )
                        throw(CORELINUX(AllocatorNotFoundException));
   //
   // Overides Iterator factory methods from AbstractFactory
   //
            /**
            Interface for creating an Iterator to iterate
            through the Allocators of an implementation.
            @return Iterator pointer of type Allocator pointer
            */

   virtual  CORELINUX(Iterator<corelinux::AllocatorPtr>)* createIterator( void ) const;

            /**
            Interface for returning a created Iterator.
            @return Iterator pointer of type Allocator pointer
            */

   virtual  void  destroyIterator( CORELINUX(Iterator<corelinux::AllocatorPtr>)* ) const;

            /**
            Interface for creating an AssociativeIterator to iterate
            through the Identifiers and Allocators of an implementation.
            @return AssociativeIterator pointer of type 
            <Identifier,Allocator pointer>
            */

   virtual  corelinux::AssociativeIterator<NameIdentifier,corelinux::AllocatorPtr>*   
               createAssociativeIterator( void ) const;

            /**
            Interface for returning a created AssociativeIterator.
            @return Iterator pointer of type 
            <Identifier,Allocator pointer>
            */

   virtual  void  destroyAssociativeIterator
                     ( 
                        corelinux::AssociativeIterator<NameIdentifier,corelinux::AllocatorPtr>* 
                     ) const;

      
protected:

            /// Routine to flush contents from map

            void  flushAllocators( void );

private:

            NamedAllocators   theAllocators;
};

#endif // if !defined(__MAZEFACTORY_HPP)

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


