deba@782: // -*- c++ -*-
deba@782: #ifndef MAP_REGISTRY_H
deba@782: #define MAP_REGISTRY_H
deba@782: 
deba@782: #include <vector>
deba@782: 
alpar@785: ///\ingroup graphmapfactory
alpar@785: ///\file
alpar@785: ///\brief Map registry for graph maps.
alpar@785: 
deba@782: using namespace std;
deba@782: 
deba@782: namespace hugo {
deba@782: 
alpar@785: /// \addtogroup graphmapfactory
alpar@785: /// @{
alpar@785: 
deba@782: /** 
deba@782:  * Registry class to register edge or node maps into the graph. The
deba@782:  * registry helps you to implement an observer pattern. If you add
deba@782:  * or erase an edge or node you must notify all the maps about the
deba@782:  * event.
deba@782: */
deba@782:   template <typename G, typename K, typename KIt>
deba@782:   class MapRegistry {
deba@782:   public:
deba@782:     typedef G Graph;
alpar@786:     typedef K KeyType;
deba@782:     typedef KIt KeyIt;
deba@782: 	
deba@782:     /**
deba@782:      * MapBase is the base class of the registered maps.
deba@782:      * It defines the core modification operations on the maps and
deba@782:      * implements some helper functions. 
deba@782:      */
deba@782:     class MapBase {
deba@782:     public:
deba@782:       typedef G Graph;
alpar@786:       typedef K KeyType;
deba@782:       typedef KIt KeyIt;
deba@782: 
deba@782:       typedef MapRegistry<G, K, KIt> Registry;
deba@782: 	
deba@782:       friend class MapRegistry<G, K, KIt>;
deba@782: 
deba@782:       /**
deba@782:        * Default constructor for MapBase.
deba@782:        */
deba@782: 
deba@782:       MapBase() : graph(0), registry(0) {}
deba@782: 		
deba@782:       /** 
deba@782:        * Simple constructor to register into a graph registry.
deba@782:       */
deba@782: 	
deba@782:       MapBase(const Graph& g, Registry& r) : graph(&g), registry(0) {
deba@782: 	r.attach(*this);
deba@782:       }
deba@782: 
deba@782:       /** 
deba@782:        * Copy constructor to register into the registry.
deba@782:       */	
deba@782: 	
deba@783:       MapBase(const MapBase& copy) : graph(copy.graph), registry(0) {
deba@782: 	if (copy.registry) {
deba@782: 	  copy.registry->attach(*this);
deba@782: 	}
deba@782:       } 
deba@782: 	
deba@782:       /** 
deba@782:        * Assign operator.
deba@782:       */	
deba@782:       const MapBase& operator=(const MapBase& copy) {
deba@782: 	if (registry) {
deba@782: 	  registry->detach(*this);
deba@782: 	}
deba@782: 	graph = copy.graph;
deba@782: 	if (copy.registry) {
deba@782: 	  copy.registry->attach(*this);
deba@782: 	}
deba@783: 	return *this;
deba@782:       }
deba@782: 	
deba@782: 
deba@782:       /** 
deba@782:        * Destructor. 
deba@782:       */		
deba@782: 
deba@782:       virtual ~MapBase() {
deba@782: 	if (registry) {
deba@782: 	  registry->detach(*this);
deba@782: 	}
deba@782:       }
deba@782: 
deba@782:       /*
deba@782:        * Returns the graph that the map belongs to.
deba@782:       */
deba@782: 
deba@782:       const Graph* getGraph() const { return graph; }
deba@782: 	
deba@782:     protected:
deba@782: 		
deba@782:       const Graph* graph;     
deba@782:       Registry* registry;
deba@782: 
deba@782:       int registry_index;
deba@782: 
deba@782:     protected:
deba@782: 	
deba@782:       /**
deba@782: 	 Helper function to implement constructors in the subclasses.
deba@782:       */
deba@782: 	
deba@782:       virtual void init() {
deba@782: 	for (KeyIt it(*graph); it != INVALID; ++it) {
deba@782: 	  add(it);
deba@782: 	}
deba@782:       }
deba@782: 	
deba@782:       /**
deba@782: 	 Helper function to implement the destructor in the subclasses.
deba@782:       */
deba@782: 	
deba@782:       virtual void destroy() {
deba@782: 	for (KeyIt it(*getGraph()); it != INVALID; ++it) {
deba@782: 	  erase(it);
deba@782: 	}
deba@782:       }
deba@782: 	
deba@782:       /** 
deba@782: 	  The add member function should be overloaded in the subclasses.
deba@782: 	  \e Add extends the map with the new node.
deba@782:       */
deba@782: 	
alpar@786:       virtual void add(const KeyType&) = 0;	
deba@782:       /** 
deba@782: 	  The erase member function should be overloaded in the subclasses.
deba@782: 	  \e Erase removes the node from the map.
deba@782:       */
deba@782: 	
alpar@786:       virtual void erase(const KeyType&) = 0;
deba@782: 
deba@782:       /**
deba@782:        *  The clear member function should be overloaded in the subclasses.
deba@782:        *  \e Clear makes empty the data structure.
deba@782:        */
deba@782: 
deba@782:       virtual void clear() = 0;
deba@782: 	
deba@782:       /**
deba@782: 	 Exception class to throw at unsupported operation.
deba@782:       */
deba@782: 	
deba@782:       class NotSupportedOperationException {};
deba@782: 
deba@782:     };
deba@782: 	
deba@782:   protected:
deba@782: 	
deba@782:     /** 
deba@782:      * The container type of the maps.
deba@782:      */
deba@782:     typedef std::vector<MapBase*> Container; 
deba@782: 
deba@782:     /**
deba@782:      * The container of the registered maps.
deba@782:      */
deba@782:     Container container;
deba@782: 
deba@782: 		
deba@782:   public:
deba@782: 	
deba@782:     /**
deba@782:      * Default Constructor of the MapRegistry. It creates an empty registry.
deba@782:      */
deba@782:     MapRegistry() {}
deba@782: 	
deba@782:     /**
deba@782:      * Copy Constructor of the MapRegistry. The new registry does not steal
deba@782:      * the maps from the right value. The new registry will be an empty.
deba@782:      */
deba@782:     MapRegistry(const MapRegistry&) {}
deba@782: 		
deba@782:     /**
deba@782:      * Assign operator. The left value does not steal the maps 
deba@782:      * from the right value. The left value will be an empty registry.
deba@782:      */
deba@782:     MapRegistry& operator=(const MapRegistry&) {
deba@782:       typename Container::iterator it;
deba@782:       for (it = container.begin(); it != container.end(); ++it) {
deba@782: 	(*it)->destroy();
deba@782: 	(*it)->graph = 0;
deba@782: 	(*it)->registry = 0;
deba@782:       }
deba@782:     }
deba@782: 				
deba@782:     /**
deba@782:      * Destructor of the MapRegistry.
deba@782:      */
deba@782:     ~MapRegistry() {
deba@782:       typename Container::iterator it;
deba@782:       for (it = container.begin(); it != container.end(); ++it) {
deba@782: 	(*it)->destroy();
deba@782: 	(*it)->registry = 0;
deba@782: 	(*it)->graph = 0;
deba@782:       }
deba@782:     }
deba@782: 	
deba@782: 	
deba@782:     public:
deba@782: 	
deba@782:     /**
deba@782:      * Attach a map into thr registry. If the map has been attached
deba@782:      * into an other registry it is detached from that automaticly.
deba@782:      */
deba@782:     void attach(MapBase& map) {
deba@782:       if (map.registry) {
deba@782: 	map.registry->detach(map);
deba@782:       }
deba@782:       container.push_back(&map);
deba@782:       map.registry = this;
deba@782:       map.registry_index = container.size()-1;
deba@782:     } 
deba@782: 	
deba@782:     /**
deba@782:      * Detach the map from the registry.
deba@782:      */
deba@782:     void detach(MapBase& map) {
deba@782:       container.back()->registry_index = map.registry_index; 
deba@782:       container[map.registry_index] = container.back();
deba@782:       container.pop_back();
deba@782:       map.registry = 0;
deba@782:       map.graph = 0;
deba@782:     }
deba@782: 	
deba@782: 		
deba@782:     /**
deba@782:      * Notify all the registered maps about a Key added.
deba@782:      */
alpar@786:     void add(KeyType& key) {
deba@782:       typename Container::iterator it;
deba@782:       for (it = container.begin(); it != container.end(); ++it) {
deba@782: 	(*it)->add(key);
deba@782:       }
deba@782:     }	
deba@782: 		
deba@782:     /**
deba@782:      * Notify all the registered maps about a Key erased.
deba@782:      */ 
alpar@786:     void erase(KeyType& key) {
deba@782:       typename Container::iterator it;
deba@782:       for (it = container.begin(); it != container.end(); ++it) {
deba@782: 	(*it)->erase(key);
deba@782:       }
deba@782:     }
deba@782: 
deba@782:     /**
deba@782:      * Notify all the registered maps about the map should be cleared.
deba@782:      */ 
deba@783:     void clear() {
deba@782:       typename Container::iterator it;
deba@782:       for (it = container.begin(); it != container.end(); ++it) {
deba@782: 	(*it)->clear();
deba@782:       }
deba@782:     }
deba@782:   };
deba@782: 
alpar@785:   
alpar@785: /// @}
alpar@785:   
alpar@785: 
deba@782: }
deba@782: 
deba@782: #endif