deba@378: #ifndef MAP_REGISTRY_H deba@378: #define MAP_REGISTRY_H deba@378: deba@378: #include deba@378: deba@595: using namespace std; deba@595: deba@627: /** deba@627: Registry class to register edge or node maps in the graph. The deba@627: registry helps you to implement an observer pattern. If you add deba@627: or erase an edge or node you must notify all the maps about the deba@627: event. deba@627: */ deba@378: deba@378: namespace hugo { deba@378: deba@627: template deba@627: class MapRegistry { deba@627: public: deba@627: typedef G Graph; deba@627: typedef K Key; deba@627: typedef KIt KeyIt; deba@378: deba@627: deba@627: deba@627: class MapBase { deba@627: public: deba@627: typedef G Graph; deba@627: typedef MapRegistry Registry; deba@627: typedef K Key; deba@627: typedef KIt KeyIt; deba@378: deba@627: friend class Registry; deba@627: deba@627: /** deba@627: Default constructor. deba@627: */ deba@627: deba@627: MapBase() : graph(0), registry(0) {} deba@627: deba@627: /** deba@627: Simple constructor to register into a graph registry. deba@627: */ deba@378: deba@627: MapBase(Graph& g, Registry& r) : graph(&g), registry(0) { deba@627: r.attach(*this); deba@627: } deba@627: deba@627: /** deba@627: Copy constructor with registering into the map. deba@627: */ deba@627: deba@627: MapBase(const MapBase& copy) : registry(0), graph(copy.graph) { deba@627: if (copy.registry) { deba@627: copy.registry->attach(*this); deba@627: } deba@627: } deba@627: deba@627: /** deba@627: Assign operator. deba@627: */ deba@627: deba@627: const MapBase& operator=(const MapBase& copy) { deba@627: if (registry) { deba@627: registry->detach(*this); deba@627: } deba@627: graph = copy.graph; deba@627: if (copy.registry) { deba@627: copy.registry->attach(*this); deba@627: } deba@627: } deba@627: deba@627: deba@627: /** deba@627: Destructor. deba@627: */ deba@627: deba@627: virtual ~MapBase() { deba@627: if (registry) { deba@627: registry->detach(*this); deba@627: } deba@627: } deba@627: deba@627: protected: deba@627: deba@627: Graph* graph; deba@627: Registry* registry; deba@627: deba@627: int registry_index; deba@627: deba@627: /** deba@627: Helper function to implement constructors in the subclasses. deba@627: */ deba@627: deba@627: virtual void init() { deba@627: for (KeyIt it(*graph); graph->valid(it); graph->next(it)) { deba@627: add(it); deba@627: } deba@627: } deba@627: deba@627: /** deba@627: Helper function to implement the destructor in the subclasses. deba@627: */ deba@627: deba@627: virtual void destroy() { deba@627: for (KeyIt it(*graph); graph->valid(it); graph->next(it)) { deba@627: erase(it); deba@627: } deba@627: } deba@627: deba@627: /** deba@627: The add member function should be overloaded in the subclasses. deba@627: \e Add extends the map with the new node. deba@627: */ deba@627: deba@627: virtual void add(const Key&) = 0; deba@627: /** deba@627: The erase member function should be overloaded in the subclasses. deba@627: \e Erase removes the node from the map. deba@627: */ deba@627: deba@627: virtual void erase(const Key&) = 0; deba@627: deba@627: /** deba@627: Exception class to throw at unsupported operation. deba@627: */ deba@627: deba@627: class NotSupportedOperationException {}; deba@627: deba@627: }; deba@627: deba@627: protected: deba@627: deba@627: typedef std::vector Container; deba@627: Container container; deba@378: deba@378: deba@627: public: deba@378: deba@627: MapRegistry() {} deba@571: deba@627: MapRegistry(const MapRegistry&) {} deba@571: deba@627: MapRegistry& operator=(const MapRegistry&) { deba@627: for (it = container.begin(); it != container.end(); ++it) { deba@627: (*it)->destroy(); deba@627: (*it)->graph = 0; deba@627: (*it)->registry = 0; deba@627: } deba@627: } deba@378: deba@627: ~MapRegistry() { deba@627: typename Container::iterator it; deba@627: for (it = container.begin(); it != container.end(); ++it) { deba@627: (*it)->destroy(); deba@627: (*it)->registry = 0; deba@627: (*it)->graph = 0; deba@627: } deba@627: } deba@378: deba@378: deba@627: public: deba@378: deba@627: void attach(MapBase& map) { deba@627: if (map.registry) { deba@627: map.registry->detach(map); deba@627: } deba@627: container.push_back(&map); deba@627: map.registry = this; deba@627: map.registry_index = container.size()-1; deba@627: } deba@378: deba@627: void detach(MapBase& map) { deba@627: container.back()->registry_index = map.registry_index; deba@627: container[map.registry_index] = container.back(); deba@627: container.pop_back(); deba@627: map.registry = 0; deba@627: map.graph = 0; deba@627: } deba@378: deba@378: deba@627: virtual void add(Key& key) { deba@627: typename Container::iterator it; deba@627: for (it = container.begin(); it != container.end(); ++it) { deba@627: (*it)->add(key); deba@627: } deba@627: } deba@378: deba@627: virtual void erase(Key& key) { deba@627: typename Container::iterator it; deba@627: for (it = container.begin(); it != container.end(); ++it) { deba@627: (*it)->erase(key); deba@627: } deba@627: } deba@378: deba@627: }; deba@378: deba@378: } deba@378: deba@378: #endif