COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/hugo/map_registry.h @ 783:81bf2d766164

Last change on this file since 783:81bf2d766164 was 783:81bf2d766164, checked in by Balazs Dezso, 16 years ago
File size: 5.5 KB
Line 
1// -*- c++ -*-
2#ifndef MAP_REGISTRY_H
3#define MAP_REGISTRY_H
4
5#include <vector>
6
7using namespace std;
8
9namespace 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) : graph(copy.graph), registry(0) {
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        return *this;
78      }
79       
80
81      /**
82       * Destructor.
83      */               
84
85      virtual ~MapBase() {
86        if (registry) {
87          registry->detach(*this);
88        }
89      }
90
91      /*
92       * Returns the graph that the map belongs to.
93      */
94
95      const Graph* getGraph() const { return graph; }
96       
97    protected:
98               
99      const Graph* graph;     
100      Registry* registry;
101
102      int registry_index;
103
104    protected:
105       
106      /**
107         Helper function to implement constructors in the subclasses.
108      */
109       
110      virtual void init() {
111        for (KeyIt it(*graph); it != INVALID; ++it) {
112          add(it);
113        }
114      }
115       
116      /**
117         Helper function to implement the destructor in the subclasses.
118      */
119       
120      virtual void destroy() {
121        for (KeyIt it(*getGraph()); it != INVALID; ++it) {
122          erase(it);
123        }
124      }
125       
126      /**
127          The add member function should be overloaded in the subclasses.
128          \e Add extends the map with the new node.
129      */
130       
131      virtual void add(const Key&) = 0;
132      /**
133          The erase member function should be overloaded in the subclasses.
134          \e Erase removes the node from the map.
135      */
136       
137      virtual void erase(const Key&) = 0;
138
139      /**
140       *  The clear member function should be overloaded in the subclasses.
141       *  \e Clear makes empty the data structure.
142       */
143
144      virtual void clear() = 0;
145       
146      /**
147         Exception class to throw at unsupported operation.
148      */
149       
150      class NotSupportedOperationException {};
151
152    };
153       
154  protected:
155       
156    /**
157     * The container type of the maps.
158     */
159    typedef std::vector<MapBase*> Container;
160
161    /**
162     * The container of the registered maps.
163     */
164    Container container;
165
166               
167  public:
168       
169    /**
170     * Default Constructor of the MapRegistry. It creates an empty registry.
171     */
172    MapRegistry() {}
173       
174    /**
175     * Copy Constructor of the MapRegistry. The new registry does not steal
176     * the maps from the right value. The new registry will be an empty.
177     */
178    MapRegistry(const MapRegistry&) {}
179               
180    /**
181     * Assign operator. The left value does not steal the maps
182     * from the right value. The left value will be an empty registry.
183     */
184    MapRegistry& operator=(const MapRegistry&) {
185      typename Container::iterator it;
186      for (it = container.begin(); it != container.end(); ++it) {
187        (*it)->destroy();
188        (*it)->graph = 0;
189        (*it)->registry = 0;
190      }
191    }
192                               
193    /**
194     * Destructor of the MapRegistry.
195     */
196    ~MapRegistry() {
197      typename Container::iterator it;
198      for (it = container.begin(); it != container.end(); ++it) {
199        (*it)->destroy();
200        (*it)->registry = 0;
201        (*it)->graph = 0;
202      }
203    }
204       
205       
206    public:
207       
208    /**
209     * Attach a map into thr registry. If the map has been attached
210     * into an other registry it is detached from that automaticly.
211     */
212    void attach(MapBase& map) {
213      if (map.registry) {
214        map.registry->detach(map);
215      }
216      container.push_back(&map);
217      map.registry = this;
218      map.registry_index = container.size()-1;
219    }
220       
221    /**
222     * Detach the map from the registry.
223     */
224    void detach(MapBase& map) {
225      container.back()->registry_index = map.registry_index;
226      container[map.registry_index] = container.back();
227      container.pop_back();
228      map.registry = 0;
229      map.graph = 0;
230    }
231       
232               
233    /**
234     * Notify all the registered maps about a Key added.
235     */
236    void add(Key& key) {
237      typename Container::iterator it;
238      for (it = container.begin(); it != container.end(); ++it) {
239        (*it)->add(key);
240      }
241    }   
242               
243    /**
244     * Notify all the registered maps about a Key erased.
245     */
246    void erase(Key& key) {
247      typename Container::iterator it;
248      for (it = container.begin(); it != container.end(); ++it) {
249        (*it)->erase(key);
250      }
251    }
252
253    /**
254     * Notify all the registered maps about the map should be cleared.
255     */
256    void clear() {
257      typename Container::iterator it;
258      for (it = container.begin(); it != container.end(); ++it) {
259        (*it)->clear();
260      }
261    }
262  };
263
264}
265
266#endif
Note: See TracBrowser for help on using the repository browser.