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