|
1 // -*- c++ -*- |
|
2 #ifndef MAP_REGISTRY_H |
|
3 #define MAP_REGISTRY_H |
|
4 |
|
5 #include <vector> |
|
6 |
|
7 using namespace std; |
|
8 |
|
9 namespace hugo { |
|
10 |
|
11 /** |
|
12 * Registry class to register edge or node maps into the graph. The |
|
13 * registry helps you to implement an observer pattern. If you add |
|
14 * or erase an edge or node you must notify all the maps about the |
|
15 * event. |
|
16 */ |
|
17 template <typename G, typename K, typename KIt> |
|
18 class MapRegistry { |
|
19 public: |
|
20 typedef G Graph; |
|
21 typedef K Key; |
|
22 typedef KIt KeyIt; |
|
23 |
|
24 |
|
25 |
|
26 /** |
|
27 * MapBase is the base class of the registered maps. |
|
28 * It defines the core modification operations on the maps and |
|
29 * implements some helper functions. |
|
30 */ |
|
31 class MapBase { |
|
32 public: |
|
33 typedef G Graph; |
|
34 typedef K Key; |
|
35 typedef KIt KeyIt; |
|
36 |
|
37 typedef MapRegistry<G, K, KIt> Registry; |
|
38 |
|
39 friend class MapRegistry<G, K, KIt>; |
|
40 |
|
41 /** |
|
42 * Default constructor for MapBase. |
|
43 */ |
|
44 |
|
45 MapBase() : graph(0), registry(0) {} |
|
46 |
|
47 /** |
|
48 * Simple constructor to register into a graph registry. |
|
49 */ |
|
50 |
|
51 MapBase(const Graph& g, Registry& r) : graph(&g), registry(0) { |
|
52 r.attach(*this); |
|
53 } |
|
54 |
|
55 /** |
|
56 * Copy constructor to register into the registry. |
|
57 */ |
|
58 |
|
59 MapBase(const MapBase& copy) : registry(0), graph(copy.graph) { |
|
60 if (copy.registry) { |
|
61 copy.registry->attach(*this); |
|
62 } |
|
63 } |
|
64 |
|
65 /** |
|
66 * Assign operator. |
|
67 */ |
|
68 |
|
69 const MapBase& operator=(const MapBase& copy) { |
|
70 if (registry) { |
|
71 registry->detach(*this); |
|
72 } |
|
73 graph = copy.graph; |
|
74 if (copy.registry) { |
|
75 copy.registry->attach(*this); |
|
76 } |
|
77 } |
|
78 |
|
79 |
|
80 /** |
|
81 * Destructor. |
|
82 */ |
|
83 |
|
84 virtual ~MapBase() { |
|
85 if (registry) { |
|
86 registry->detach(*this); |
|
87 } |
|
88 } |
|
89 |
|
90 /* |
|
91 * Returns the graph that the map belongs to. |
|
92 */ |
|
93 |
|
94 const Graph* getGraph() const { return graph; } |
|
95 |
|
96 protected: |
|
97 |
|
98 const Graph* graph; |
|
99 Registry* registry; |
|
100 |
|
101 int registry_index; |
|
102 |
|
103 protected: |
|
104 |
|
105 /** |
|
106 Helper function to implement constructors in the subclasses. |
|
107 */ |
|
108 |
|
109 virtual void init() { |
|
110 for (KeyIt it(*graph); it != INVALID; ++it) { |
|
111 add(it); |
|
112 } |
|
113 } |
|
114 |
|
115 /** |
|
116 Helper function to implement the destructor in the subclasses. |
|
117 */ |
|
118 |
|
119 virtual void destroy() { |
|
120 for (KeyIt it(*getGraph()); it != INVALID; ++it) { |
|
121 erase(it); |
|
122 } |
|
123 } |
|
124 |
|
125 /** |
|
126 The add member function should be overloaded in the subclasses. |
|
127 \e Add extends the map with the new node. |
|
128 */ |
|
129 |
|
130 virtual void add(const Key&) = 0; |
|
131 /** |
|
132 The erase member function should be overloaded in the subclasses. |
|
133 \e Erase removes the node from the map. |
|
134 */ |
|
135 |
|
136 virtual void erase(const Key&) = 0; |
|
137 |
|
138 /** |
|
139 * The clear member function should be overloaded in the subclasses. |
|
140 * \e Clear makes empty the data structure. |
|
141 */ |
|
142 |
|
143 virtual void clear() = 0; |
|
144 |
|
145 /** |
|
146 Exception class to throw at unsupported operation. |
|
147 */ |
|
148 |
|
149 class NotSupportedOperationException {}; |
|
150 |
|
151 }; |
|
152 |
|
153 protected: |
|
154 |
|
155 /** |
|
156 * The container type of the maps. |
|
157 */ |
|
158 typedef std::vector<MapBase*> Container; |
|
159 |
|
160 /** |
|
161 * The container of the registered maps. |
|
162 */ |
|
163 Container container; |
|
164 |
|
165 |
|
166 public: |
|
167 |
|
168 /** |
|
169 * Default Constructor of the MapRegistry. It creates an empty registry. |
|
170 */ |
|
171 MapRegistry() {} |
|
172 |
|
173 /** |
|
174 * Copy Constructor of the MapRegistry. The new registry does not steal |
|
175 * the maps from the right value. The new registry will be an empty. |
|
176 */ |
|
177 MapRegistry(const MapRegistry&) {} |
|
178 |
|
179 /** |
|
180 * Assign operator. The left value does not steal the maps |
|
181 * from the right value. The left value will be an empty registry. |
|
182 */ |
|
183 MapRegistry& operator=(const MapRegistry&) { |
|
184 typename Container::iterator it; |
|
185 for (it = container.begin(); it != container.end(); ++it) { |
|
186 (*it)->destroy(); |
|
187 (*it)->graph = 0; |
|
188 (*it)->registry = 0; |
|
189 } |
|
190 } |
|
191 |
|
192 /** |
|
193 * Destructor of the MapRegistry. |
|
194 */ |
|
195 ~MapRegistry() { |
|
196 typename Container::iterator it; |
|
197 for (it = container.begin(); it != container.end(); ++it) { |
|
198 (*it)->destroy(); |
|
199 (*it)->registry = 0; |
|
200 (*it)->graph = 0; |
|
201 } |
|
202 } |
|
203 |
|
204 |
|
205 public: |
|
206 |
|
207 /** |
|
208 * Attach a map into thr registry. If the map has been attached |
|
209 * into an other registry it is detached from that automaticly. |
|
210 */ |
|
211 void attach(MapBase& map) { |
|
212 if (map.registry) { |
|
213 map.registry->detach(map); |
|
214 } |
|
215 container.push_back(&map); |
|
216 map.registry = this; |
|
217 map.registry_index = container.size()-1; |
|
218 } |
|
219 |
|
220 /** |
|
221 * Detach the map from the registry. |
|
222 */ |
|
223 void detach(MapBase& map) { |
|
224 container.back()->registry_index = map.registry_index; |
|
225 container[map.registry_index] = container.back(); |
|
226 container.pop_back(); |
|
227 map.registry = 0; |
|
228 map.graph = 0; |
|
229 } |
|
230 |
|
231 |
|
232 /** |
|
233 * Notify all the registered maps about a Key added. |
|
234 */ |
|
235 virtual void add(Key& key) { |
|
236 typename Container::iterator it; |
|
237 for (it = container.begin(); it != container.end(); ++it) { |
|
238 (*it)->add(key); |
|
239 } |
|
240 } |
|
241 |
|
242 /** |
|
243 * Notify all the registered maps about a Key erased. |
|
244 */ |
|
245 virtual void erase(Key& key) { |
|
246 typename Container::iterator it; |
|
247 for (it = container.begin(); it != container.end(); ++it) { |
|
248 (*it)->erase(key); |
|
249 } |
|
250 } |
|
251 |
|
252 /** |
|
253 * Notify all the registered maps about the map should be cleared. |
|
254 */ |
|
255 virtual void clear() { |
|
256 typename Container::iterator it; |
|
257 for (it = container.begin(); it != container.end(); ++it) { |
|
258 (*it)->clear(); |
|
259 } |
|
260 } |
|
261 }; |
|
262 |
|
263 } |
|
264 |
|
265 #endif |