#ifndef MAP_REGISTRY_H #define MAP_REGISTRY_H #include using namespace std; /** Registry class to register edge or node maps in 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. */ namespace hugo { template class MapRegistry { public: typedef G Graph; typedef K Key; typedef KIt KeyIt; class MapBase { public: typedef G Graph; typedef MapRegistry Registry; typedef K Key; typedef KIt KeyIt; friend class Registry; /** Default constructor. */ MapBase() : graph(0), registry(0) {} /** Simple constructor to register into a graph registry. */ MapBase(Graph& g, Registry& r) : graph(&g), registry(0) { r.attach(*this); } /** Copy constructor with registering into the map. */ MapBase(const MapBase& copy) : registry(0), graph(copy.graph) { 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); } } /** Destructor. */ virtual ~MapBase() { if (registry) { registry->detach(*this); } } protected: Graph* graph; Registry* registry; int registry_index; /** Helper function to implement constructors in the subclasses. */ virtual void init() { for (KeyIt it(*graph); graph->valid(it); graph->next(it)) { add(it); } } /** Helper function to implement the destructor in the subclasses. */ virtual void destroy() { for (KeyIt it(*graph); graph->valid(it); graph->next(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 Key&) = 0; /** The erase member function should be overloaded in the subclasses. \e Erase removes the node from the map. */ virtual void erase(const Key&) = 0; /** Exception class to throw at unsupported operation. */ class NotSupportedOperationException {}; }; protected: typedef std::vector Container; Container container; public: MapRegistry() {} MapRegistry(const MapRegistry&) {} MapRegistry& operator=(const MapRegistry&) { for (it = container.begin(); it != container.end(); ++it) { (*it)->destroy(); (*it)->graph = 0; (*it)->registry = 0; } } ~MapRegistry() { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->destroy(); (*it)->registry = 0; (*it)->graph = 0; } } public: void attach(MapBase& map) { if (map.registry) { map.registry->detach(map); } container.push_back(&map); map.registry = this; map.registry_index = container.size()-1; } 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; } virtual void add(Key& key) { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->add(key); } } virtual void erase(Key& key) { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->erase(key); } } }; } #endif