/* -*- C++ -*- * src/hugo/map_registry.h - Part of HUGOlib, a generic C++ optimization library * * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Combinatorial Optimization Research Group, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef HUGO_MAP_REGISTRY_H #define HUGO_MAP_REGISTRY_H #include ///\ingroup graphmapfactory ///\file ///\brief Map registry for graph maps. using namespace std; namespace hugo { /// \addtogroup graphmapfactory /// @{ /** * Registry class to register edge or node maps into the graph. The * registry helps you to implement an observer pattern. If you add * or erase an edge or node you must notify all the maps about the * event. */ template class MapRegistry { public: typedef G Graph; typedef K KeyType; typedef KIt KeyIt; /** * MapBase is the base class of the registered maps. * It defines the core modification operations on the maps and * implements some helper functions. */ class MapBase { public: typedef G Graph; typedef K KeyType; typedef KIt KeyIt; typedef MapRegistry Registry; friend class MapRegistry; /** * Default constructor for MapBase. */ MapBase() : graph(0), registry(0) {} /** * Simple constructor to register into a graph registry. */ MapBase(const Graph& g, Registry& r) : graph(&g), registry(0) { r.attach(*this); } /** * Copy constructor to register into the registry. */ MapBase(const MapBase& copy) : graph(copy.graph), registry(0) { if (copy.registry) { copy.registry->attach(*this); } } /** * Assign operator. */ const MapBase& operator=(const MapBase& copy) { if (registry) { registry->detach(*this); } graph = copy.graph; if (copy.registry) { copy.registry->attach(*this); } return *this; } /** * Destructor. */ virtual ~MapBase() { if (registry) { registry->detach(*this); } } /* * Returns the graph that the map belongs to. */ const Graph* getGraph() const { return graph; } protected: const Graph* graph; Registry* registry; int registry_index; protected: /** Helper function to implement constructors in the subclasses. */ virtual void init() { for (KeyIt it(*graph); it != INVALID; ++it) { add(it); } } /** Helper function to implement the destructor in the subclasses. */ virtual void destroy() { for (KeyIt it(*getGraph()); it != INVALID; ++it) { erase(it); } } /** The add member function should be overloaded in the subclasses. \e Add extends the map with the new node. */ virtual void add(const KeyType&) = 0; /** The erase member function should be overloaded in the subclasses. \e Erase removes the node from the map. */ virtual void erase(const KeyType&) = 0; /** * The clear member function should be overloaded in the subclasses. * \e Clear makes empty the data structure. */ virtual void clear() = 0; /** Exception class to throw at unsupported operation. */ class NotSupportedOperationException {}; }; protected: /** * The container type of the maps. */ typedef std::vector Container; /** * The container of the registered maps. */ Container container; public: /** * Default Constructor of the MapRegistry. It creates an empty registry. */ MapRegistry() {} /** * Copy Constructor of the MapRegistry. The new registry does not steal * the maps from the right value. The new registry will be an empty. */ MapRegistry(const MapRegistry&) {} /** * Assign operator. The left value does not steal the maps * from the right value. The left value will be an empty registry. */ MapRegistry& operator=(const MapRegistry&) { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->destroy(); (*it)->graph = 0; (*it)->registry = 0; } } /** * Destructor of the MapRegistry. */ ~MapRegistry() { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->destroy(); (*it)->registry = 0; (*it)->graph = 0; } } public: /** * Attach a map into thr registry. If the map has been attached * into an other registry it is detached from that automaticly. */ void attach(MapBase& map) { if (map.registry) { map.registry->detach(map); } container.push_back(&map); map.registry = this; map.registry_index = container.size()-1; } /** * Detach the map from the registry. */ void detach(MapBase& map) { container.back()->registry_index = map.registry_index; container[map.registry_index] = container.back(); container.pop_back(); map.registry = 0; map.graph = 0; } /** * Notify all the registered maps about a Key added. */ void add(KeyType& key) { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->add(key); } } /** * Notify all the registered maps about a Key erased. */ void erase(KeyType& key) { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->erase(key); } } /** * Notify all the registered maps about the map should be cleared. */ void clear() { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->clear(); } } }; /// @} } #endif