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: alpar@676: namespace hugo { alpar@676: deba@627: /** deba@701: * Registry class to register edge or node maps into the graph. The deba@701: * registry helps you to implement an observer pattern. If you add deba@701: * or erase an edge or node you must notify all the maps about the deba@701: * event. deba@627: */ 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@701: /** deba@701: * MapBase is the base class of the registered maps. deba@701: * It defines the core modification operations on the maps and deba@701: * implements some helper functions. deba@701: */ 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@701: deba@701: /** deba@701: * Default constructor for MapBase. deba@701: */ deba@701: deba@701: MapBase() : graph(0), registry(0) {} deba@627: deba@627: /** deba@701: * Simple constructor to register into a graph registry. deba@627: */ deba@378: deba@701: MapBase(const Graph& g, Registry& r) : graph(&g), registry(0) { deba@627: r.attach(*this); deba@627: } deba@627: deba@627: /** deba@701: * Copy constructor to register into the registry. 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@701: * 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@701: * Destructor. deba@627: */ deba@627: deba@627: virtual ~MapBase() { deba@627: if (registry) { deba@627: registry->detach(*this); deba@627: } deba@627: } deba@701: deba@701: /* deba@701: * Returns the graph that the map belongs to. deba@701: */ deba@701: deba@701: const Graph* getGraph() const { return graph; } deba@627: deba@703: protected: deba@627: deba@703: const Graph* graph; deba@627: Registry* registry; deba@627: deba@627: int registry_index; deba@701: deba@701: protected: 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@701: for (KeyIt it(*getGraph()); getGraph()->valid(it); getGraph()->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@701: /** deba@701: * The container type of the maps. deba@701: */ deba@627: typedef std::vector Container; deba@701: deba@701: /** deba@701: * The container of the registered maps. deba@701: */ deba@627: Container container; deba@378: deba@378: deba@701: public: deba@378: deba@701: /** deba@701: * Default Constructor of the MapRegistry. It creates an empty registry. deba@701: */ deba@627: MapRegistry() {} deba@571: deba@701: /** deba@701: * Copy Constructor of the MapRegistry. The new registry does not steal deba@701: * the maps from the right value. The new registry will be an empty. deba@701: */ deba@627: MapRegistry(const MapRegistry&) {} deba@571: deba@701: /** deba@701: * Assign operator. The left value does not steal the maps deba@701: * from the right value. The left value will be an empty registry. deba@701: */ 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@701: /** deba@701: * Destructor of the MapRegistry. deba@701: */ 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@701: /** deba@701: * Attach a map into thr registry. If the map has been attached deba@701: * into an other registry it is detached from that automaticly. deba@701: */ 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@701: /** deba@701: * Detach the map from the registry. deba@701: */ 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@701: /** deba@701: * Notify all the registered maps about a Key added. deba@701: */ 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@701: /** deba@701: * Notify all the registered maps about a Key erased. deba@701: */ 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