deba@782: // -*- c++ -*- deba@782: #ifndef MAP_REGISTRY_H deba@782: #define MAP_REGISTRY_H deba@782: deba@782: #include 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 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 Registry; deba@782: deba@782: friend class MapRegistry; 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: 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 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