COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/alteration_notifier.h @ 1718:6a958ab38386

Last change on this file since 1718:6a958ab38386 was 1718:6a958ab38386, checked in by Balazs Dezso, 15 years ago

Extending observer interface
It will be used in the indegmap, outdegmap types

File size: 14.1 KB
Line 
1/* -*- C++ -*-
2 * lemon/notifier.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, 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 graphmapfactory
24///\file
25///\brief Observer registry for graph alteration observers.
26
27namespace lemon {
28
29  /// \addtogroup graphmapfactory
30  /// @{
31
32  /// \brief Registry class to register objects observes alterations in
33  /// the graph.
34  ///
35  /// This class is a registry for the objects which observe the
36  /// alterations in a container. The alteration observers can be attached
37  /// to and detached from the registry. The observers have to inherit
38  /// from the \ref AlterationNotifier::ObserverBase and override
39  /// the virtual functions in that.
40  ///
41  /// The most important application of the alteration observing is the
42  /// dynamic map implementation.
43  ///
44  /// \param _Item The item type what the observers are observing, usually
45  /// edge or node.
46  ///
47  /// \author Balazs Dezso
48
49  template <typename _Item>
50  class AlterationNotifier {
51  public:
52    typedef _Item Item;
53
54    /// ObserverBase is the base class for the observers.
55       
56    /// ObserverBase is the abstract base class for the observers.
57    /// It will be notified about an item was inserted into or
58    /// erased from the graph.
59    ///
60    /// The observer interface contains some pure virtual functions
61    /// to override. The add() and erase() functions are
62    /// to notify the oberver when one item is added or
63    /// erased.
64    ///
65    /// The build() and clear() members are to notify the observer
66    /// about the container is built from an empty container or
67    /// is cleared to an empty container.
68    ///
69    /// \author Balazs Dezso
70
71    class ObserverBase {
72    protected:
73      typedef AlterationNotifier Registry;
74
75      friend class AlterationNotifier;
76
77      /// \brief Default constructor.
78      ///
79      /// Default constructor for ObserverBase.
80      ///
81      ObserverBase() : registry(0) {}
82
83      ObserverBase(const ObserverBase& copy) {
84        if (copy.attached()) {
85          copy.getRegistry()->attach(*this);
86        }
87      }
88       
89      virtual ~ObserverBase() {}
90
91      /// \brief Attaches the observer into an AlterationNotifier.
92      ///
93      /// This member attaches the observer into an AlterationNotifier.
94      ///
95      void attach(AlterationNotifier& r) {
96        registry = &r;
97        registry->attach(*this);
98      }
99
100      /// \brief Detaches the observer into an AlterationNotifier.
101      ///
102      /// This member detaches the observer from an AlterationNotifier.
103      ///
104      void detach() {
105        if (registry) {
106          registry->detach(*this);
107        }
108      }
109       
110
111      /// Gives back a pointer to the registry what the map attached into.
112
113      /// This function gives back a pointer to the registry what the map
114      /// attached into.
115      ///
116      Registry* getRegistry() const { return const_cast<Registry*>(registry); }
117     
118      /// Gives back true when the observer is attached into a registry.
119      bool attached() const { return registry != 0; }
120
121    private:
122
123      ObserverBase& operator=(const ObserverBase& copy);
124
125    protected:
126     
127      Registry* registry;
128      int registry_index;
129
130    public:
131
132      /// \brief The member function to notificate the observer about an
133      /// item is added to the container.
134      ///
135      /// The add() member function notificates the observer about an item
136      /// is added to the container. It have to be overrided in the
137      /// subclasses.
138       
139      virtual void add(const Item&) = 0;
140
141      /// \brief The member function to notificate the observer about
142      /// more item is added to the container.
143      ///
144      /// The add() member function notificates the observer about more item
145      /// is added to the container. It have to be overrided in the
146      /// subclasses.
147
148      virtual void add(const std::vector<Item>& items) {
149        for (int i = 0; i < (int)items.size(); ++i) {
150          add(items[i]);
151        }
152      }
153
154      /// \brief The member function to notificate the observer about an
155      /// item is erased from the container.
156      ///
157      /// The erase() member function notificates the observer about an
158      /// item is erased from the container. It have to be overrided in
159      /// the subclasses.
160       
161      virtual void erase(const Item&) = 0;
162
163      /// \brief The member function to notificate the observer about
164      /// more item is erased from the container.
165      ///
166      /// The erase() member function notificates the observer about more item
167      /// is erased from the container. It have to be overrided in the
168      /// subclasses.
169      virtual void erase(const std::vector<Item>& items) {
170        for (int i = 0; i < (int)items.size(); ++i) {
171          erase(items[i]);
172        }
173      }
174
175      /// \brief Signal a property change on the given item.
176      ///
177      /// Signal a property change on the given item. It should
178      /// be used always with the commitChange() function.
179      /// This function is called always the property change.
180      /// The commitChange() is called always after the change.
181      virtual void signalChange(const Item&) {}
182
183      /// \brief Commit the property change on the given item.
184      ///
185      /// Commit the property change on the given item. It should
186      /// be used always with the signalChange() function.
187      /// This function is called always the property change.
188      /// The commitChange() is called always after the change.
189      virtual void commitChange(const Item&) {}
190
191      /// \brief The member function to notificate the observer about the
192      /// container is built.
193      ///
194      /// The build() member function notificates the observer about the
195      /// container is built from an empty container. It have to be
196      /// overrided in the subclasses.
197
198      virtual void build() = 0;
199
200      /// \brief The member function to notificate the observer about all
201      /// items are erased from the container.
202      ///
203      /// The clear() member function notificates the observer about all
204      /// items are erased from the container. It have to be overrided in
205      /// the subclasses.
206     
207      virtual void clear() = 0;
208
209    };
210       
211  protected:
212       
213
214    typedef std::vector<ObserverBase*> Container;
215
216    Container container;
217
218               
219  public:
220
221    /// Default constructor.
222       
223    ///
224    /// The default constructor of the AlterationNotifier.
225    /// It creates an empty registry.
226    AlterationNotifier() {}
227
228    /// Copy Constructor of the AlterationNotifier.
229       
230    /// Copy constructor of the AlterationNotifier.
231    /// It creates only an empty registry because the copiable
232    /// registry's observers have to be registered still into that registry.
233    AlterationNotifier(const AlterationNotifier&) {}
234
235    /// Assign operator.
236               
237    /// Assign operator for the AlterationNotifier.
238    /// It makes the notifier only empty because the copiable
239    /// notifier's observers have to be registered still into that registry.
240    AlterationNotifier& operator=(const AlterationNotifier&) {
241      typename Container::iterator it;
242      for (it = container.begin(); it != container.end(); ++it) {
243        (*it)->registry = 0;
244      }
245    }
246
247    /// Destructor.
248                               
249    /// Destructor of the AlterationNotifier.
250    ///
251    ~AlterationNotifier() {
252      typename Container::iterator it;
253      for (it = container.begin(); it != container.end(); ++it) {
254        (*it)->registry = 0;
255      }
256    }
257       
258       
259  protected:
260
261    void attach(ObserverBase& observer) {
262      container.push_back(&observer);
263      observer.registry = this;
264      observer.registry_index = container.size()-1;
265    }
266
267    void detach(ObserverBase& base) {
268      container.back()->registry_index = base.registry_index;
269      container[base.registry_index] = container.back();
270      container.pop_back();
271      base.registry = 0;
272    }
273
274  public:
275       
276    /// \brief Notifies all the registered observers about an Item added to
277    /// the container.
278    ///
279    /// It notifies all the registered observers about an Item added to
280    /// the container.
281    ///
282    void add(const Item& item) {
283      typename Container::iterator it;
284      for (it = container.begin(); it != container.end(); ++it) {
285        (*it)->add(item);
286      }
287    }   
288
289    /// \brief Notifies all the registered observers about more Item added to
290    /// the container.
291    ///
292    /// It notifies all the registered observers about more Item added to
293    /// the container.
294    ///
295    void add(const std::vector<Item>& items) {
296      typename Container::iterator it;
297      for (it = container.begin(); it != container.end(); ++it) {
298        (*it)->add(items);
299      }
300    }   
301
302    /// \brief Notifies all the registered observers about an Item erased from
303    /// the container.
304    ///
305    /// It notifies all the registered observers about an Item erased from
306    /// the container.
307    ///
308    void erase(const Item& key) {
309      typename Container::iterator it;
310      for (it = container.begin(); it != container.end(); ++it) {
311        (*it)->erase(key);
312      }
313    }
314
315    /// \brief Notifies all the registered observers about more Item erased 
316    /// from the container.
317    ///
318    /// It notifies all the registered observers about more Item erased from
319    /// the container.
320    ///
321    void erase(const std::vector<Item>& items) {
322      typename Container::iterator it;
323      for (it = container.begin(); it != container.end(); ++it) {
324        (*it)->erase(items);
325      }
326    }
327   
328    /// \brief Signal a property change on the given item.
329    ///
330    /// Signal a property change on the given item. It should
331    /// be used always with the commitChange() function.
332    /// This function is called always the property change.
333    /// The commitChange() is called always after the change.
334    void signalChange(const Item& item) {
335      typename Container::iterator it;
336      for (it = container.begin(); it != container.end(); ++it) {
337        (*it)->signalChange(item);
338      }
339    }
340   
341    /// \brief Commit the property change on the given item.
342    ///
343    /// Commit the property change on the given item. It should
344    /// be used always with the signalChange() function.
345    /// This function is called always the property change.
346    /// The commitChange() is called always after the change.
347    void commitChange(const Item& item) {
348      typename Container::iterator it;
349      for (it = container.begin(); it != container.end(); ++it) {
350        (*it)->commitChange(item);
351      }
352    }
353
354    /// \brief Notifies all the registered observers about the container is
355    /// built.
356    ///         
357    /// Notifies all the registered observers about the container is built
358    /// from an empty container.
359    void build() {
360      typename Container::iterator it;
361      for (it = container.begin(); it != container.end(); ++it) {
362        (*it)->build();
363      }
364    }
365
366
367    /// \brief Notifies all the registered observers about all Items are
368    /// erased.
369    ///
370    /// Notifies all the registered observers about all Items are erased
371    /// from the container.
372    void clear() {
373      typename Container::iterator it;
374      for (it = container.begin(); it != container.end(); ++it) {
375        (*it)->clear();
376      }
377    }
378  };
379
380
381  /// \brief Class to extend a graph with the functionality of alteration
382  /// observing.
383  ///
384  /// AlterableGraphExtender extends the _Base graphs functionality with
385  /// the possibility of alteration observing. It defines two observer
386  /// registrys for the nodes and mapes.
387  ///
388  /// \todo Document what "alteration observing" is. And probably find a
389  /// better (shorter) name.
390  ///
391  /// \param _Base is the base class to extend.
392  ///
393  /// \pre _Base is conform to the BaseGraphComponent concept.
394  ///
395  /// \post AlterableGraphExtender<_Base> is conform to the
396  /// AlterableGraphComponent concept.
397  ///
398  /// \author Balazs Dezso
399
400  template <typename _Base>
401  class AlterableGraphExtender : public _Base {
402  public:
403
404    typedef AlterableGraphExtender Graph;
405    typedef _Base Parent;
406
407    typedef typename Parent::Node Node;
408    typedef typename Parent::Edge Edge;
409
410    /// The edge observer registry.
411    typedef AlterationNotifier<Edge> EdgeNotifier;
412    /// The node observer registry.
413    typedef AlterationNotifier<Node> NodeNotifier;
414
415
416  protected:
417
418    mutable EdgeNotifier edge_notifier;
419
420    mutable NodeNotifier node_notifier;
421
422  public:
423
424    /// \brief Gives back the edge alteration notifier.
425    ///
426    /// Gives back the edge alteration notifier.
427    EdgeNotifier& getNotifier(Edge) const {
428      return edge_notifier;
429    }
430
431    /// \brief Gives back the node alteration notifier.
432    ///
433    /// Gives back the node alteration notifier.
434    NodeNotifier& getNotifier(Node) const {
435      return node_notifier;
436    }
437
438    ~AlterableGraphExtender() {
439      node_notifier.clear();
440      edge_notifier.clear();
441    }
442   
443  };
444
445  /// \brief Class to extend an undirected graph with the functionality of
446  /// alteration observing.
447  ///
448  /// \todo Document.
449  ///
450  /// \sa AlterableGraphExtender
451  ///
452  /// \bug This should be done some other way. Possibilities: template
453  /// specialization (not very easy, if at all possible); some kind of
454  /// enable_if boost technique?
455
456  template <typename _Base>
457  class AlterableUndirGraphExtender
458    : public AlterableGraphExtender<_Base> {
459  public:
460
461    typedef AlterableUndirGraphExtender Graph;
462    typedef AlterableGraphExtender<_Base> Parent;
463
464    typedef typename Parent::UndirEdge UndirEdge;
465
466    /// The edge observer registry.
467    typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
468
469  protected:
470
471    mutable UndirEdgeNotifier undir_edge_notifier;
472
473  public:
474
475    using Parent::getNotifier;
476    UndirEdgeNotifier& getNotifier(UndirEdge) const {
477      return undir_edge_notifier;
478    }
479
480    ~AlterableUndirGraphExtender() {
481      undir_edge_notifier.clear();
482    }
483  };
484 
485/// @}
486 
487
488}
489
490#endif
Note: See TracBrowser for help on using the repository browser.