lemon/bits/alteration_notifier.h
author deba
Fri, 14 Oct 2005 10:44:49 +0000
changeset 1718 6a958ab38386
parent 1701 77bb84387815
child 1729 06f939455cb1
permissions -rw-r--r--
Extending observer interface
It will be used in the indegmap, outdegmap types
     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 
    27 namespace 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