src/lemon/bits/alteration_notifier.h
changeset 1435 8e85e6bbefdf
parent 1359 1581f961cfaa
equal deleted inserted replaced
3:e2b2ae4154e5 -1:000000000000
     1 /* -*- C++ -*-
       
     2  * src/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 graphmaps
       
    24 ///\file
       
    25 ///\brief Observer registry for graph alteration observers.
       
    26 
       
    27 namespace lemon {
       
    28 
       
    29   /// \addtogroup graphmaps
       
    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       virtual ~ObserverBase() {}
       
    84 
       
    85       /// \brief Attaches the observer into an AlterationNotifier.
       
    86       ///
       
    87       /// This member attaches the observer into an AlterationNotifier.
       
    88       ///
       
    89       void attach(AlterationNotifier& r) {
       
    90 	registry = &r;
       
    91 	registry->attach(*this);
       
    92       }
       
    93 
       
    94       /// \brief Detaches the observer into an AlterationNotifier.
       
    95       ///
       
    96       /// This member detaches the observer from an AlterationNotifier.
       
    97       ///
       
    98       void detach() {
       
    99 	if (registry) {
       
   100 	  registry->detach(*this);
       
   101 	}
       
   102       }
       
   103 	
       
   104 
       
   105       /// Gives back a pointer to the registry what the map attached into.
       
   106 
       
   107       /// This function gives back a pointer to the registry what the map
       
   108       /// attached into.
       
   109       ///
       
   110       Registry* getRegistry() const { return const_cast<Registry*>(registry); }
       
   111       
       
   112       /// Gives back true when the observer is attached into a registry.
       
   113       bool attached() const { return registry != 0; }
       
   114 	
       
   115     private:
       
   116 
       
   117       ObserverBase(const ObserverBase& copy);
       
   118       ObserverBase& operator=(const ObserverBase& copy);
       
   119 
       
   120     protected:
       
   121       
       
   122       Registry* registry;
       
   123       int registry_index;
       
   124 
       
   125     public:
       
   126 
       
   127       /// \brief The member function to notificate the observer about an
       
   128       /// item is added to the container.
       
   129       ///
       
   130       /// The add() member function notificates the observer about an item
       
   131       /// is added to the container. It have to be overrided in the
       
   132       /// subclasses.
       
   133 	
       
   134       virtual void add(const Item&) = 0;
       
   135 
       
   136       /// \brief The member function to notificate the observer about 
       
   137       /// simulitem is added to the container.
       
   138       ///
       
   139       /// The add() member function notificates the observer about an item
       
   140       /// is added to the container. It have to be overrided in the
       
   141       /// subclasses.
       
   142 
       
   143       virtual void add(const std::vector<Item>& items) {
       
   144 	for (int i = 0; i < (int)items.size(); ++i) {
       
   145 	  add(items[i]);
       
   146 	}
       
   147       }
       
   148 
       
   149       /// \brief The member function to notificate the observer about an
       
   150       /// item is erased from the container.
       
   151       ///
       
   152       /// The erase() member function notificates the observer about an
       
   153       /// item is erased from the container. It have to be overrided in
       
   154       /// the subclasses.
       
   155 	
       
   156       virtual void erase(const Item&) = 0;
       
   157 
       
   158       virtual void erase(const std::vector<Item>& items) {
       
   159 	for (int i = 0; i < (int)items.size(); ++i) {
       
   160 	  add(items[i]);
       
   161 	}
       
   162       }
       
   163 
       
   164       /// \brief The member function to notificate the observer about the
       
   165       /// container is built.
       
   166       ///
       
   167       /// The build() member function notificates the observer about the
       
   168       /// container is built from an empty container. It have to be
       
   169       /// overrided in the subclasses.
       
   170 
       
   171       virtual void build() = 0;
       
   172 
       
   173       /// \brief The member function to notificate the observer about all
       
   174       /// items are erased from the container.
       
   175       ///
       
   176       /// The clear() member function notificates the observer about all
       
   177       /// items are erased from the container. It have to be overrided in
       
   178       /// the subclasses.
       
   179       
       
   180       virtual void clear() = 0;
       
   181 
       
   182     };
       
   183 	
       
   184   protected:
       
   185 	
       
   186 
       
   187     typedef std::vector<ObserverBase*> Container; 
       
   188 
       
   189     Container container;
       
   190 
       
   191 		
       
   192   public:
       
   193 
       
   194     /// Default constructor.
       
   195 	
       
   196     ///
       
   197     /// The default constructor of the AlterationNotifier. 
       
   198     /// It creates an empty registry.
       
   199     AlterationNotifier() {}
       
   200 
       
   201     /// Copy Constructor of the AlterationNotifier. 
       
   202 	
       
   203     /// Copy constructor of the AlterationNotifier. 
       
   204     /// It creates only an empty registry because the copiable
       
   205     /// registry's observers have to be registered still into that registry.
       
   206     AlterationNotifier(const AlterationNotifier&) {}
       
   207 
       
   208     /// Assign operator.
       
   209 		
       
   210     /// Assign operator for the AlterationNotifier. 
       
   211     /// It makes the notifier only empty because the copiable
       
   212     /// notifier's observers have to be registered still into that registry.
       
   213     AlterationNotifier& operator=(const AlterationNotifier&) {
       
   214       typename Container::iterator it;
       
   215       for (it = container.begin(); it != container.end(); ++it) {
       
   216 	(*it)->registry = 0;
       
   217       }
       
   218     }
       
   219 
       
   220     /// Destructor.
       
   221 				
       
   222     /// Destructor of the AlterationNotifier.
       
   223     ///
       
   224     ~AlterationNotifier() {
       
   225       typename Container::iterator it;
       
   226       for (it = container.begin(); it != container.end(); ++it) {
       
   227 	(*it)->registry = 0;
       
   228       }
       
   229     }
       
   230 	
       
   231 	
       
   232   protected:
       
   233 
       
   234     void attach(ObserverBase& observer) {
       
   235       container.push_back(&observer);
       
   236       observer.registry = this;
       
   237       observer.registry_index = container.size()-1;
       
   238     } 
       
   239 
       
   240     void detach(ObserverBase& base) {
       
   241       container.back()->registry_index = base.registry_index; 
       
   242       container[base.registry_index] = container.back();
       
   243       container.pop_back();
       
   244       base.registry = 0;
       
   245     }
       
   246 
       
   247   public:
       
   248 	
       
   249     /// \brief Notifies all the registered observers about an Item added to 
       
   250     /// the container.
       
   251     ///
       
   252     /// It notifies all the registered observers about an Item added to 
       
   253     /// the container.
       
   254     /// 
       
   255     void add(const Item& item) {
       
   256       typename Container::iterator it;
       
   257       for (it = container.begin(); it != container.end(); ++it) {
       
   258 	(*it)->add(item);
       
   259       }
       
   260     }	
       
   261 
       
   262     /// \brief Notifies all the registered observers about more Item added to 
       
   263     /// the container.
       
   264     ///
       
   265     /// It notifies all the registered observers about more Item added to 
       
   266     /// the container.
       
   267     /// 
       
   268     void add(const std::vector<Item>& items) {
       
   269       typename Container::iterator it;
       
   270       for (it = container.begin(); it != container.end(); ++it) {
       
   271 	(*it)->add(items);
       
   272       }
       
   273     }	
       
   274 
       
   275     /// \brief Notifies all the registered observers about an Item erased from 
       
   276     /// the container.
       
   277     ///	
       
   278     /// It notifies all the registered observers about an Item erased from 
       
   279     /// the container.
       
   280     /// 
       
   281     void erase(const Item& key) {
       
   282       typename Container::iterator it;
       
   283       for (it = container.begin(); it != container.end(); ++it) {
       
   284 	(*it)->erase(key);
       
   285       }
       
   286     }
       
   287 
       
   288     /// \brief Notifies all the registered observers about more Item erased  
       
   289     /// from the container.
       
   290     ///	
       
   291     /// It notifies all the registered observers about more Item erased from 
       
   292     /// the container.
       
   293     /// 
       
   294     void erase(const std::vector<Item>& items) {
       
   295       typename Container::iterator it;
       
   296       for (it = container.begin(); it != container.end(); ++it) {
       
   297 	(*it)->erase(items);
       
   298       }
       
   299     }
       
   300     
       
   301 
       
   302     /// \brief Notifies all the registered observers about the container is 
       
   303     /// built.
       
   304     ///		
       
   305     /// Notifies all the registered observers about the container is built
       
   306     /// from an empty container.
       
   307     void build() {
       
   308       typename Container::iterator it;
       
   309       for (it = container.begin(); it != container.end(); ++it) {
       
   310 	(*it)->build();
       
   311       }
       
   312     }
       
   313 
       
   314 
       
   315     /// \brief Notifies all the registered observers about all Items are 
       
   316     /// erased.
       
   317     ///
       
   318     /// Notifies all the registered observers about all Items are erased
       
   319     /// from the container.
       
   320     void clear() {
       
   321       typename Container::iterator it;
       
   322       for (it = container.begin(); it != container.end(); ++it) {
       
   323 	(*it)->clear();
       
   324       }
       
   325     }
       
   326   };
       
   327 
       
   328 
       
   329   /// \brief Class to extend a graph with the functionality of alteration
       
   330   /// observing.
       
   331   ///
       
   332   /// AlterableGraphExtender extends the _Base graphs functionality with
       
   333   /// the possibility of alteration observing. It defines two observer
       
   334   /// registrys for the nodes and mapes.
       
   335   /// 
       
   336   /// \todo Document what "alteration observing" is. And probably find a
       
   337   /// better (shorter) name.
       
   338   ///
       
   339   /// \param _Base is the base class to extend.
       
   340   ///
       
   341   /// \pre _Base is conform to the BaseGraphComponent concept.
       
   342   ///
       
   343   /// \post AlterableGraphExtender<_Base> is conform to the
       
   344   /// AlterableGraphComponent concept.
       
   345   ///
       
   346   /// \author Balazs Dezso
       
   347 
       
   348   template <typename _Base> 
       
   349   class AlterableGraphExtender : public _Base {
       
   350   public:
       
   351 
       
   352     typedef AlterableGraphExtender Graph;
       
   353     typedef _Base Parent;
       
   354 
       
   355     typedef typename Parent::Node Node;
       
   356     typedef typename Parent::Edge Edge;
       
   357 
       
   358     /// The edge observer registry.
       
   359     typedef AlterationNotifier<Edge> EdgeNotifier;
       
   360     /// The node observer registry.
       
   361     typedef AlterationNotifier<Node> NodeNotifier;
       
   362 
       
   363 
       
   364   protected:
       
   365 
       
   366     mutable EdgeNotifier edge_notifier;
       
   367 
       
   368     mutable NodeNotifier node_notifier;
       
   369 
       
   370   public:
       
   371 
       
   372     /// \brief Gives back the edge alteration notifier.
       
   373     ///
       
   374     /// Gives back the edge alteration notifier.
       
   375     EdgeNotifier& getNotifier(Edge) const {
       
   376       return edge_notifier;
       
   377     }
       
   378 
       
   379     /// \brief Gives back the node alteration notifier.
       
   380     ///
       
   381     /// Gives back the node alteration notifier.
       
   382     NodeNotifier& getNotifier(Node) const {
       
   383       return node_notifier;
       
   384     }
       
   385 
       
   386     ~AlterableGraphExtender() {
       
   387       node_notifier.clear();
       
   388       edge_notifier.clear();
       
   389     }
       
   390     
       
   391   };
       
   392 
       
   393   /// \brief Class to extend an undirected graph with the functionality of
       
   394   /// alteration observing.
       
   395   ///
       
   396   /// \todo Document.
       
   397   ///
       
   398   /// \sa AlterableGraphExtender
       
   399   ///
       
   400   /// \bug This should be done some other way. Possibilities: template
       
   401   /// specialization (not very easy, if at all possible); some kind of
       
   402   /// enable_if boost technique?
       
   403 
       
   404   template <typename _Base> 
       
   405   class AlterableUndirGraphExtender
       
   406     : public AlterableGraphExtender<_Base> {
       
   407   public:
       
   408 
       
   409     typedef AlterableUndirGraphExtender Graph;
       
   410     typedef AlterableGraphExtender<_Base> Parent;
       
   411 
       
   412     typedef typename Parent::UndirEdge UndirEdge;
       
   413 
       
   414     /// The edge observer registry.
       
   415     typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
       
   416 
       
   417   protected:
       
   418 
       
   419     mutable UndirEdgeNotifier undir_edge_notifier;
       
   420 
       
   421   public:
       
   422 
       
   423     using Parent::getNotifier;
       
   424     UndirEdgeNotifier& getNotifier(UndirEdge) const {
       
   425       return undir_edge_notifier;
       
   426     }
       
   427 
       
   428     ~AlterableUndirGraphExtender() {
       
   429       undir_edge_notifier.clear();
       
   430     }
       
   431   };
       
   432   
       
   433 /// @}
       
   434   
       
   435 
       
   436 }
       
   437 
       
   438 #endif