COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/alteration_observer_registry.h @ 963:5a7556e9e340

Last change on this file since 963:5a7556e9e340 was 962:1a770e9f80b2, checked in by Mihaly Barasz, 20 years ago

Undirect graph implementation.
Not yet done, untested.

File size: 10.6 KB
Line 
1/* -*- C++ -*-
2 * src/lemon/observer_registry.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
6 *
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
10 *
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
13 * purpose.
14 *
15 */
16
17#ifndef LEMON_ALTERATION_OBSERVER_REGISTRY_H
18#define LEMON_ALTERATION_OBSERVER_REGISTRY_H
19
20#include <vector>
21#include <algorithm>
22
23///\ingroup graphmaps
24///\file
25///\brief Observer registry for graph alteration observers.
26
27using namespace std;
28
29namespace lemon {
30
31  /// \addtogroup graphmaps
32  /// @{
33
34  /// Registry class to register objects observes alterations in the graph.
35
36  /// This class is a registry for the objects which observe the
37  /// alterations in a container. The alteration observers can be attached
38  /// to and detached from the registry. The observers have to inherit
39  /// from the \ref AlterationObserverRegistry::ObserverBase and override
40  /// the virtual functions in that.
41  ///
42  /// The most important application of the alteration observing is the
43  /// dynamic map implementation when the observers are observing the
44  /// alterations in the graph.
45  ///
46  /// \param _Item The item type what the observers are observing, usually
47  /// edge or node.
48  ///
49  /// \author Balazs Dezso
50
51  template <typename _Item>
52  class AlterationObserverRegistry {
53  public:
54    typedef _Item Item;
55
56    /// ObserverBase is the base class for the observers.
57       
58    /// ObserverBase is the abstract base class for the observers.
59    /// It will be notified about an item was inserted into or
60    /// erased from the graph.
61    ///
62    /// The observer interface contains some pure virtual functions
63    /// to override. The add() and erase() functions are
64    /// to notify the oberver when one item is added or
65    /// erased.
66    ///
67    /// The build() and clear() members are to notify the observer
68    /// about the container is builded from an empty container or
69    /// is cleared to an empty container.
70    ///
71    /// \author Balazs Dezso
72
73    class ObserverBase {
74    protected:
75      typedef AlterationObserverRegistry Registry;
76
77      friend class Registry;
78
79      /// Default constructor.
80
81      /// Default constructor for ObserverBase.
82      ///
83      ObserverBase() : registry(0) {}
84
85      virtual ~ObserverBase() {}
86
87      /// Attaches the observer into an AlterationObserverRegistry.
88
89      /// This member attaches the observer into an AlterationObserverRegistry.
90      ///
91      void attach(AlterationObserverRegistry& r) {
92        registry = &r;
93        registry->attach(*this);
94      }
95
96      /// Detaches the observer into an AlterationObserverRegistry.
97
98      /// This member detaches the observer from an AlterationObserverRegistry.
99      ///
100      void detach() {
101        if (registry) {
102          registry->detach(*this);
103        }
104      }
105       
106
107      /// Gives back a pointer to the registry what the map attached into.
108
109      /// This function gives back a pointer to the registry what the map
110      /// attached into.
111      ///
112      Registry* getRegistry() const { return const_cast<Registry*>(registry); }
113     
114      /// Gives back true when the observer is attached into a registry.
115      bool attached() const { return registry != 0; }
116       
117    private:
118
119      ObserverBase(const ObserverBase& copy);
120      ObserverBase& operator=(const ObserverBase& copy);
121
122    protected:
123     
124      Registry* registry;
125      int registry_index;
126
127    public:
128
129      /// \brief The member function to notificate the observer about an
130      /// item is added to the container.
131      ///
132      /// The add() member function notificates the observer about an item
133      /// is added to the container. It have to be overrided in the
134      /// subclasses.
135       
136      virtual void add(const Item&) = 0;       
137
138
139      /// \brief The member function to notificate the observer about an
140      /// item is erased from the container.
141      ///
142      /// The erase() member function notificates the observer about an
143      /// item is erased from the container. It have to be overrided in
144      /// the subclasses.
145       
146      virtual void erase(const Item&) = 0;
147
148      /// \brief The member function to notificate the observer about the
149      /// container is builded.
150      ///
151      /// The build() member function notificates the observer about the
152      /// container is builded from an empty container. It have to be
153      /// overrided in the subclasses.
154
155      virtual void build() = 0;
156
157      /// \brief The member function to notificate the observer about all
158      /// items are erased from the container.
159      ///
160      /// The clear() member function notificates the observer about all
161      /// items are erased from the container. It have to be overrided in
162      /// the subclasses.
163     
164      virtual void clear() = 0;
165
166    };
167       
168  protected:
169       
170
171    typedef std::vector<ObserverBase*> Container;
172
173    Container container;
174
175               
176  public:
177
178    /// Default constructor.
179       
180    ///
181    /// The default constructor of the AlterationObserverRegistry.
182    /// It creates an empty registry.
183    AlterationObserverRegistry() {}
184
185    /// Copy Constructor of the AlterationObserverRegistry.
186       
187    /// Copy constructor of the AlterationObserverRegistry.
188    /// It creates only an empty registry because the copiable
189    /// registry's observers have to be registered still into that registry.
190    AlterationObserverRegistry(const AlterationObserverRegistry&) {}
191
192    /// Assign operator.
193               
194    /// Assign operator for the AlterationObserverRegistry.
195    /// It makes the registry only empty because the copiable
196    /// registry's observers have to be registered still into that registry.
197    AlterationObserverRegistry& operator=(const AlterationObserverRegistry&) {
198      typename Container::iterator it;
199      for (it = container.begin(); it != container.end(); ++it) {
200        (*it)->registry = 0;
201      }
202    }
203
204    /// Destructor.
205                               
206    /// Destructor of the AlterationObserverRegistry.
207    ///
208    ~AlterationObserverRegistry() {
209      typename Container::iterator it;
210      for (it = container.begin(); it != container.end(); ++it) {
211        (*it)->registry = 0;
212      }
213    }
214       
215       
216  protected:
217
218    void attach(ObserverBase& observer) {
219      container.push_back(&observer);
220      observer.registry = this;
221      observer.registry_index = container.size()-1;
222    }
223
224    void detach(ObserverBase& base) {
225      container.back()->registry_index = base.registry_index;
226      container[base.registry_index] = container.back();
227      container.pop_back();
228      base.registry = 0;
229    }
230
231  public:
232       
233    /// Notifies all the registered observers about an Item added to the container.
234               
235    /// It notifies all the registered observers about an Item added to the container.
236    ///
237    void add(const Item& key) {
238      typename Container::iterator it;
239      for (it = container.begin(); it != container.end(); ++it) {
240        (*it)->add(key);
241      }
242    }   
243
244    /// Notifies all the registered observers about an Item erased from the container.
245               
246    /// It notifies all the registered observers about an Item erased from the container.
247    ///
248    void erase(const Item& key) {
249      typename Container::iterator it;
250      for (it = container.begin(); it != container.end(); ++it) {
251        (*it)->erase(key);
252      }
253    }
254   
255
256    /// Notifies all the registered observers about the container is builded.
257               
258    /// Notifies all the registered observers about the container is builded
259    /// from an empty container.
260    void build() {
261      typename Container::iterator it;
262      for (it = container.begin(); it != container.end(); ++it) {
263        (*it)->build();
264      }
265    }
266
267
268    /// Notifies all the registered observers about all Items are erased.
269
270    /// Notifies all the registered observers about all Items are erased
271    /// from the container.
272    void clear() {
273      typename Container::iterator it;
274      for (it = container.begin(); it != container.end(); ++it) {
275        (*it)->clear();
276      }
277    }
278  };
279
280
281  /// \brief Class to extend a graph with the functionality of alteration
282  /// observing.
283  ///
284  /// AlterableGraphExtender extends the _Base graphs functionality with
285  /// the possibility of alteration observing. It defines two observer
286  /// registrys for the nodes and mapes.
287  ///
288  /// \todo Document what "alteration observing" is. And probably find a
289  /// better (shorter) name.
290  ///
291  /// \param _Base is the base class to extend.
292  ///
293  /// \pre _Base is conform to the BaseGraphComponent concept.
294  ///
295  /// \post AlterableGraphExtender<_Base> is conform to the
296  /// AlterableGraphComponent concept.
297  ///
298  /// \author Balazs Dezso
299
300  template <typename _Base>
301  class AlterableGraphExtender : public _Base {
302  public:
303
304    typedef AlterableGraphExtender Graph;
305    typedef _Base Parent;
306
307    typedef typename Parent::Node Node;
308    typedef typename Parent::Edge Edge;
309
310    /// The edge observer registry.
311    typedef AlterationObserverRegistry<Edge> EdgeObserverRegistry;
312    /// The node observer registry.
313    typedef AlterationObserverRegistry<Node> NodeObserverRegistry;
314
315
316  protected:
317
318    mutable EdgeObserverRegistry edge_observers;
319
320    mutable NodeObserverRegistry node_observers;
321
322  public:
323
324    EdgeObserverRegistry& getEdgeObserverRegistry() const {
325      return edge_observers;
326    }
327
328    NodeObserverRegistry& getNodeObserverRegistry() const {
329      return node_observers;
330    }
331
332    ~AlterableGraphExtender() {
333      node_observers.clear();
334      edge_observers.clear();
335    }
336   
337  };
338
339  /// \brief Class to extend an undirected graph with the functionality of
340  /// alteration observing.
341  ///
342  /// \todo Document.
343  ///
344  /// \sa AlterableGraphExtender
345  ///
346  /// \bug This should be done some other way. Possibilities: template
347  /// specialization (not very easy, if at all possible); some kind of
348  /// enable_if boost technique?
349
350  template <typename _Base>
351  class AlterableUndirGraphExtender
352    : public AlterableGraphExtender<_Base> {
353  public:
354
355    typedef AlterableUndirGraphExtender Graph;
356    typedef AlterableGraphExtender<_Base> Parent;
357
358    typedef typename Parent::UndirEdge UndirEdge;
359
360    /// The edge observer registry.
361    typedef AlterationObserverRegistry<UndirEdge> UndirEdgeObserverRegistry;
362
363  protected:
364
365    mutable UndirEdgeObserverRegistry undir_edge_observers;
366
367    UndirEdgeObserverRegistry& getUndirEdgeObserverRegistry() const {
368      return undir_edge_observers;
369    }
370
371    ~AlterableUndirGraphExtender() {
372      undir_edge_observers.clear();
373    }
374  };
375 
376/// @}
377 
378
379}
380
381#endif
Note: See TracBrowser for help on using the repository browser.