author | marci |
Fri, 14 May 2004 18:33:17 +0000 | |
changeset 643 | f8053cb51047 |
parent 595 | e10b5e9419ef |
child 676 | 7ec5e7e6c7b4 |
permissions | -rw-r--r-- |
deba@378 | 1 |
#ifndef MAP_REGISTRY_H |
deba@378 | 2 |
#define MAP_REGISTRY_H |
deba@378 | 3 |
|
deba@378 | 4 |
#include <vector> |
deba@378 | 5 |
|
deba@595 | 6 |
using namespace std; |
deba@595 | 7 |
|
deba@627 | 8 |
/** |
deba@627 | 9 |
Registry class to register edge or node maps in the graph. The |
deba@627 | 10 |
registry helps you to implement an observer pattern. If you add |
deba@627 | 11 |
or erase an edge or node you must notify all the maps about the |
deba@627 | 12 |
event. |
deba@627 | 13 |
*/ |
deba@378 | 14 |
|
deba@378 | 15 |
namespace hugo { |
deba@378 | 16 |
|
deba@627 | 17 |
template <typename G, typename K, typename KIt> |
deba@627 | 18 |
class MapRegistry { |
deba@627 | 19 |
public: |
deba@627 | 20 |
typedef G Graph; |
deba@627 | 21 |
typedef K Key; |
deba@627 | 22 |
typedef KIt KeyIt; |
deba@378 | 23 |
|
deba@627 | 24 |
|
deba@627 | 25 |
|
deba@627 | 26 |
class MapBase { |
deba@627 | 27 |
public: |
deba@627 | 28 |
typedef G Graph; |
deba@627 | 29 |
typedef MapRegistry<G, K, KIt> Registry; |
deba@627 | 30 |
typedef K Key; |
deba@627 | 31 |
typedef KIt KeyIt; |
deba@378 | 32 |
|
deba@627 | 33 |
friend class Registry; |
deba@627 | 34 |
|
deba@627 | 35 |
/** |
deba@627 | 36 |
Default constructor. |
deba@627 | 37 |
*/ |
deba@627 | 38 |
|
deba@627 | 39 |
MapBase() : graph(0), registry(0) {} |
deba@627 | 40 |
|
deba@627 | 41 |
/** |
deba@627 | 42 |
Simple constructor to register into a graph registry. |
deba@627 | 43 |
*/ |
deba@378 | 44 |
|
deba@627 | 45 |
MapBase(Graph& g, Registry& r) : graph(&g), registry(0) { |
deba@627 | 46 |
r.attach(*this); |
deba@627 | 47 |
} |
deba@627 | 48 |
|
deba@627 | 49 |
/** |
deba@627 | 50 |
Copy constructor with registering into the map. |
deba@627 | 51 |
*/ |
deba@627 | 52 |
|
deba@627 | 53 |
MapBase(const MapBase& copy) : registry(0), graph(copy.graph) { |
deba@627 | 54 |
if (copy.registry) { |
deba@627 | 55 |
copy.registry->attach(*this); |
deba@627 | 56 |
} |
deba@627 | 57 |
} |
deba@627 | 58 |
|
deba@627 | 59 |
/** |
deba@627 | 60 |
Assign operator. |
deba@627 | 61 |
*/ |
deba@627 | 62 |
|
deba@627 | 63 |
const MapBase& operator=(const MapBase& copy) { |
deba@627 | 64 |
if (registry) { |
deba@627 | 65 |
registry->detach(*this); |
deba@627 | 66 |
} |
deba@627 | 67 |
graph = copy.graph; |
deba@627 | 68 |
if (copy.registry) { |
deba@627 | 69 |
copy.registry->attach(*this); |
deba@627 | 70 |
} |
deba@627 | 71 |
} |
deba@627 | 72 |
|
deba@627 | 73 |
|
deba@627 | 74 |
/** |
deba@627 | 75 |
Destructor. |
deba@627 | 76 |
*/ |
deba@627 | 77 |
|
deba@627 | 78 |
virtual ~MapBase() { |
deba@627 | 79 |
if (registry) { |
deba@627 | 80 |
registry->detach(*this); |
deba@627 | 81 |
} |
deba@627 | 82 |
} |
deba@627 | 83 |
|
deba@627 | 84 |
protected: |
deba@627 | 85 |
|
deba@627 | 86 |
Graph* graph; |
deba@627 | 87 |
Registry* registry; |
deba@627 | 88 |
|
deba@627 | 89 |
int registry_index; |
deba@627 | 90 |
|
deba@627 | 91 |
/** |
deba@627 | 92 |
Helper function to implement constructors in the subclasses. |
deba@627 | 93 |
*/ |
deba@627 | 94 |
|
deba@627 | 95 |
virtual void init() { |
deba@627 | 96 |
for (KeyIt it(*graph); graph->valid(it); graph->next(it)) { |
deba@627 | 97 |
add(it); |
deba@627 | 98 |
} |
deba@627 | 99 |
} |
deba@627 | 100 |
|
deba@627 | 101 |
/** |
deba@627 | 102 |
Helper function to implement the destructor in the subclasses. |
deba@627 | 103 |
*/ |
deba@627 | 104 |
|
deba@627 | 105 |
virtual void destroy() { |
deba@627 | 106 |
for (KeyIt it(*graph); graph->valid(it); graph->next(it)) { |
deba@627 | 107 |
erase(it); |
deba@627 | 108 |
} |
deba@627 | 109 |
} |
deba@627 | 110 |
|
deba@627 | 111 |
/** |
deba@627 | 112 |
The add member function should be overloaded in the subclasses. |
deba@627 | 113 |
\e Add extends the map with the new node. |
deba@627 | 114 |
*/ |
deba@627 | 115 |
|
deba@627 | 116 |
virtual void add(const Key&) = 0; |
deba@627 | 117 |
/** |
deba@627 | 118 |
The erase member function should be overloaded in the subclasses. |
deba@627 | 119 |
\e Erase removes the node from the map. |
deba@627 | 120 |
*/ |
deba@627 | 121 |
|
deba@627 | 122 |
virtual void erase(const Key&) = 0; |
deba@627 | 123 |
|
deba@627 | 124 |
/** |
deba@627 | 125 |
Exception class to throw at unsupported operation. |
deba@627 | 126 |
*/ |
deba@627 | 127 |
|
deba@627 | 128 |
class NotSupportedOperationException {}; |
deba@627 | 129 |
|
deba@627 | 130 |
}; |
deba@627 | 131 |
|
deba@627 | 132 |
protected: |
deba@627 | 133 |
|
deba@627 | 134 |
typedef std::vector<MapBase*> Container; |
deba@627 | 135 |
Container container; |
deba@378 | 136 |
|
deba@378 | 137 |
|
deba@627 | 138 |
public: |
deba@378 | 139 |
|
deba@627 | 140 |
MapRegistry() {} |
deba@571 | 141 |
|
deba@627 | 142 |
MapRegistry(const MapRegistry&) {} |
deba@571 | 143 |
|
deba@627 | 144 |
MapRegistry& operator=(const MapRegistry&) { |
deba@627 | 145 |
for (it = container.begin(); it != container.end(); ++it) { |
deba@627 | 146 |
(*it)->destroy(); |
deba@627 | 147 |
(*it)->graph = 0; |
deba@627 | 148 |
(*it)->registry = 0; |
deba@627 | 149 |
} |
deba@627 | 150 |
} |
deba@378 | 151 |
|
deba@627 | 152 |
~MapRegistry() { |
deba@627 | 153 |
typename Container::iterator it; |
deba@627 | 154 |
for (it = container.begin(); it != container.end(); ++it) { |
deba@627 | 155 |
(*it)->destroy(); |
deba@627 | 156 |
(*it)->registry = 0; |
deba@627 | 157 |
(*it)->graph = 0; |
deba@627 | 158 |
} |
deba@627 | 159 |
} |
deba@378 | 160 |
|
deba@378 | 161 |
|
deba@627 | 162 |
public: |
deba@378 | 163 |
|
deba@627 | 164 |
void attach(MapBase& map) { |
deba@627 | 165 |
if (map.registry) { |
deba@627 | 166 |
map.registry->detach(map); |
deba@627 | 167 |
} |
deba@627 | 168 |
container.push_back(&map); |
deba@627 | 169 |
map.registry = this; |
deba@627 | 170 |
map.registry_index = container.size()-1; |
deba@627 | 171 |
} |
deba@378 | 172 |
|
deba@627 | 173 |
void detach(MapBase& map) { |
deba@627 | 174 |
container.back()->registry_index = map.registry_index; |
deba@627 | 175 |
container[map.registry_index] = container.back(); |
deba@627 | 176 |
container.pop_back(); |
deba@627 | 177 |
map.registry = 0; |
deba@627 | 178 |
map.graph = 0; |
deba@627 | 179 |
} |
deba@378 | 180 |
|
deba@378 | 181 |
|
deba@627 | 182 |
virtual void add(Key& key) { |
deba@627 | 183 |
typename Container::iterator it; |
deba@627 | 184 |
for (it = container.begin(); it != container.end(); ++it) { |
deba@627 | 185 |
(*it)->add(key); |
deba@627 | 186 |
} |
deba@627 | 187 |
} |
deba@378 | 188 |
|
deba@627 | 189 |
virtual void erase(Key& key) { |
deba@627 | 190 |
typename Container::iterator it; |
deba@627 | 191 |
for (it = container.begin(); it != container.end(); ++it) { |
deba@627 | 192 |
(*it)->erase(key); |
deba@627 | 193 |
} |
deba@627 | 194 |
} |
deba@378 | 195 |
|
deba@627 | 196 |
}; |
deba@378 | 197 |
|
deba@378 | 198 |
} |
deba@378 | 199 |
|
deba@378 | 200 |
#endif |