src/lemon/alteration_observer_registry.h
changeset 1039 bd01c5a3f989
parent 1022 567f392d1d2e
equal deleted inserted replaced
5:347ef8f00f41 -1:000000000000
     1 /* -*- C++ -*-
       
     2  * src/lemon/notifier.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 
       
    27 using namespace std;
       
    28 
       
    29 namespace 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 AlterationNotifier::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 AlterationNotifier {
       
    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 AlterationNotifier Registry;
       
    76 
       
    77       friend class AlterationNotifier;
       
    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 AlterationNotifier.
       
    88 
       
    89       /// This member attaches the observer into an AlterationNotifier.
       
    90       ///
       
    91       void attach(AlterationNotifier& r) {
       
    92 	registry = &r;
       
    93 	registry->attach(*this);
       
    94       }
       
    95 
       
    96       /// Detaches the observer into an AlterationNotifier.
       
    97 
       
    98       /// This member detaches the observer from an AlterationNotifier.
       
    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 AlterationNotifier. 
       
   182     /// It creates an empty registry.
       
   183     AlterationNotifier() {}
       
   184 
       
   185     /// Copy Constructor of the AlterationNotifier. 
       
   186 	
       
   187     /// Copy constructor of the AlterationNotifier. 
       
   188     /// It creates only an empty registry because the copiable
       
   189     /// registry's observers have to be registered still into that registry.
       
   190     AlterationNotifier(const AlterationObserverRegistry&) {}
       
   191 
       
   192     /// Assign operator.
       
   193 		
       
   194     /// Assign operator for the AlterationNotifier. 
       
   195     /// It makes the registry only empty because the copiable
       
   196     /// registry's observers have to be registered still into that registry.
       
   197     AlterationNotifier& 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 AlterationNotifier.
       
   207     ///
       
   208     ~AlterationNotifier() {
       
   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 AlterationNotifier<Edge> EdgeObserverRegistry;
       
   312     /// The node observer registry.
       
   313     typedef AlterationNotifier<Node> NodeObserverRegistry;
       
   314 
       
   315 
       
   316   protected:
       
   317 
       
   318     mutable EdgeNotifier edge_observers;
       
   319 
       
   320     mutable NodeNotifier node_observers;
       
   321 
       
   322   public:
       
   323 
       
   324     EdgeNotifier& getObserverRegistry(Edge = INVALID) const {
       
   325       return edge_observers;
       
   326     }
       
   327 
       
   328     NodeNotifier& getObserverRegistry(Node = INVALID) 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 AlterationNotifier<UndirEdge> UndirEdgeObserverRegistry;
       
   362 
       
   363   protected:
       
   364 
       
   365     mutable UndirEdgeNotifier undir_edge_observers;
       
   366 
       
   367   public:
       
   368 
       
   369     using Parent::getNotifier;
       
   370     UndirEdgeNotifier& getObserverRegistry(UndirEdge) const {
       
   371       return undir_edge_observers;
       
   372     }
       
   373 
       
   374     ~AlterableUndirGraphExtender() {
       
   375       undir_edge_observers.clear();
       
   376     }
       
   377   };
       
   378   
       
   379 /// @}
       
   380   
       
   381 
       
   382 }
       
   383 
       
   384 #endif