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